From: Andrew Deason Date: Fri, 20 Nov 2009 20:15:28 +0000 (-0600) Subject: Add safety checks on all hostList traversals X-Git-Tag: openafs-stable-1_4_12pre1~13 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=dd55ac8ad042a1ddabdaf7ac0d4f6d7489402cb4;p=packages%2Fo%2Fopenafs.git Add safety checks on all hostList traversals Currently, h_Enumerate checks that it doesn't enumerate over more than hostCount hosts, in case the hostList has a cycle or is otherwise corrupt. Add similar checks to all places in the code that loop over hostList, to prevent the code from getting in an infinite loop under H_LOCK in the case of a hostList cycle. Also, ShutDownAndCore instead of assert'ing, so we try and detach volumes first, possibly reducing salvaging time when we restart after core'ing. (cherry picked from 58258ba3b89732ea825e1aff2decab54347ab92e) Change-Id: Ide1e5aca7c2c4a4af3f62bc07821db694f2f9999 Reviewed-on: http://gerrit.openafs.org/863 Tested-by: Andrew Deason Reviewed-by: Alistair Ferguson Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear Reviewed-on: http://gerrit.openafs.org/990 Reviewed-by: Andrew Deason --- diff --git a/src/viced/host.c b/src/viced/host.c index 06d86853d..153e6baf9 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -1079,7 +1079,7 @@ h_Enumerate(int (*proc) (), char *param) ViceLog(0, ("h_Enumerate found %d of %d hosts\n", count, hostCount)); } else if (host != NULL) { ViceLog(0, ("h_Enumerate found more than %d hosts\n", hostCount)); - assert(0); + ShutDownAndCore(PANIC); } H_UNLOCK; for (i = 0; i < count; i++) { @@ -1107,13 +1107,14 @@ h_Enumerate_r(int (*proc) (), struct host *enumstart, char *param) register struct host *host, *next; int held = 0; int nheld = 0; + int count; if (hostCount == 0) { return; } if (enumstart && !(held = h_Held_r(enumstart))) h_Hold_r(enumstart); - for (host = enumstart; host; host = next, held = nheld) { + for (count = 0, host = enumstart; host && count < hostCount; host = next, held = nheld, count++) { next = host->next; if (next && !(nheld = h_Held_r(next))) h_Hold_r(next); @@ -1121,6 +1122,10 @@ h_Enumerate_r(int (*proc) (), struct host *enumstart, char *param) if (!held) h_Release_r(host); /* this might free up the host */ } + if (host != NULL) { + ViceLog(0, ("h_Enumerate_r found more than %d hosts\n", hostCount)); + ShutDownAndCore(PANIC); + } } /*h_Enumerate_r */ /* inserts a new HashChain structure corresponding to this UUID */ @@ -2085,9 +2090,10 @@ h_ID2Client(afs_int32 vid) { register struct client *client; register struct host *host; + int count; H_LOCK; - for (host = hostList; host; host = host->next) { + for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) { if (host->hostFlags & HOSTDELETED) continue; for (client = host->FirstClient; client; client = client->next) { @@ -2099,6 +2105,12 @@ h_ID2Client(afs_int32 vid) } } } + if (count != hostCount) { + ViceLog(0, ("h_ID2Client found %d of %d hosts\n", count, hostCount)); + } else if (host != NULL) { + ViceLog(0, ("h_ID2Client found more than %d hosts\n", hostCount)); + ShutDownAndCore(PANIC); + } H_UNLOCK; return NULL; @@ -2666,9 +2678,10 @@ h_GetWorkStats(int *nump, int *activep, int *delp, afs_int32 cutofftime) { register struct host *host; register int num = 0, active = 0, del = 0; + int count; H_LOCK; - for (host = hostList; host; host = host->next) { + for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) { if (!(host->hostFlags & HOSTDELETED)) { num++; if (host->ActiveCall > cutofftime) @@ -2677,6 +2690,12 @@ h_GetWorkStats(int *nump, int *activep, int *delp, afs_int32 cutofftime) del++; } } + if (count != hostCount) { + ViceLog(0, ("h_GetWorkStats found %d of %d hosts\n", count, hostCount)); + } else if (host != NULL) { + ViceLog(0, ("h_GetWorkStats found more than %d hosts\n", hostCount)); + ShutDownAndCore(PANIC); + } H_UNLOCK; if (nump) *nump = num; @@ -2831,6 +2850,7 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP, register struct host *hostP; /*Ptr to current host entry */ register afs_uint32 currAddr_HBO; /*Curr host addr, host byte order */ + int count; /* * Clear out the storage pointed to by our parameters. @@ -2841,7 +2861,7 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP, *a_diffNetworkP = (afs_int32) 0; H_LOCK; - for (hostP = hostList; hostP; hostP = hostP->next) { + for (count = 0, hostP = hostList; hostP && count < hostCount; hostP = hostP->next, count++) { if (!(hostP->hostFlags & HOSTDELETED)) { /* * Bump the number of undeleted host entries found. @@ -2855,6 +2875,12 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP, a_diffNetworkP); } /*Only look at non-deleted hosts */ } /*For each host record hashed to this index */ + if (count != hostCount) { + ViceLog(0, ("h_GetHostNetStats found %d of %d hosts\n", count, hostCount)); + } else if (hostP != NULL) { + ViceLog(0, ("h_GetHostNetStats found more than %d hosts\n", hostCount)); + ShutDownAndCore(PANIC); + } H_UNLOCK; } /*h_GetHostNetStats */