h_TossStuff_r: make sure host does not go away
authorAndrew Deason <adeason@sinenomine.net>
Tue, 16 Feb 2010 17:08:38 +0000 (11:08 -0600)
committerDerrick Brashear <shadow@dementia.org>
Mon, 22 Feb 2010 20:00:55 +0000 (12:00 -0800)
When h_TossStuff_r h_NBLock_r's a host, it is not only possible for
someone else to grab a hold on the host, but in theory it's also
possible for someone to hold a host, release it, and for the host to be
deleted again (assuming some callers hold HOSTDELETED hosts, which they
should not be doing).

To make this safety check a bit more robust, hold the host in
h_TossStuff_r before h_NBLock_r'ing, to ensure that it does not go away
while we're waiting for H_LOCK.

Change-Id: I018a611143d6dccba79cc627803cce74aa830c77
Reviewed-on: http://gerrit.openafs.org/1330
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/viced/host.c
src/viced/host.h

index 2acce8c..bdd3255 100644 (file)
@@ -842,9 +842,18 @@ void
 h_TossStuff_r(register struct host *host)
 {
     register struct client **cp, *client;
+    int code;
+
+    /* make sure host doesn't go away over h_NBLock_r */
+    h_Hold_r(host);
+
+    code = h_NBLock_r(host);
+
+    /* don't use h_Release_r, since that may call h_TossStuff_r again */
+    h_Decrement_r(host);
 
     /* if somebody still has this host locked */
-    if (h_NBLock_r(host) != 0) {
+    if (code != 0) {
        char hoststr[16];
        ViceLog(0,
                ("Warning:  h_TossStuff_r failed; Host %" AFS_PTR_FMT " (%s:%d) was locked.\n",
index bbcdb7d..44e1e14 100644 (file)
@@ -174,9 +174,14 @@ do { \
        ++((x)->refCount); \
 } while(0)
 
-#define h_Release_r(x) \
+#define h_Decrement_r(x) \
 do { \
        --((x)->refCount); \
+} while (0)
+
+#define h_Release_r(x) \
+do { \
+       h_Decrement_r(x); \
        if (((x)->refCount < 1) && \
                (((x)->hostFlags & HOSTDELETED) || \
                 ((x)->hostFlags & CLIENTDELETED))) h_TossStuff_r((x));  \