From: Andrew Deason Date: Wed, 22 Jun 2011 18:44:38 +0000 (-0500) Subject: afs: Ensure afs_calc_inum yields nonzero ino X-Git-Tag: upstream/1.6.2_pre2^2~192 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=e7ea7af6573cd03859b357387a3ee666e2a6ded5;p=packages%2Fo%2Fopenafs.git afs: Ensure afs_calc_inum yields nonzero ino afs_calc_inum can currently yield an inode of 0 if MD5-based inode numbers are turned on. Some userspace applications (and for some platforms, maybe even the kernel) make certain assumptions about the inode number for a file; in particular for example, 'ls' will not display a file with inode 0 in a normal directory listing. So, read the md5 digest until we get a non-zero result. Fall back to the non-md5 calculation if we still somehow end up with a 0. While this case may at first glance seem to be extremely rare, in practice it can occur, as the current calculation for volume 538313506, vnode 26178 does actually yield a 0. Reviewed-on: http://gerrit.openafs.org/4901 Reviewed-by: Derrick Brashear Tested-by: BuildBot (cherry picked from commit 39083fe1edab784fcd75eacbdaaf7f6affa14c9f) Change-Id: I3d06a4b5dc76934b24ced883b1985bced35c893a Reviewed-on: http://gerrit.openafs.org/7276 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/afs/afs_util.c b/src/afs/afs_util.c index 2b20a94ba..daf86ff4c 100644 --- a/src/afs/afs_util.c +++ b/src/afs/afs_util.c @@ -372,18 +372,32 @@ afs_data_pointer_to_int32(const void *p) afs_int32 afs_calc_inum(afs_int32 volume, afs_int32 vnode) { - afs_int32 ino, vno = vnode; + afs_int32 ino = 0, vno = vnode; char digest[16]; struct afs_md5 ct; if (afs_new_inum) { + int offset; AFS_MD5_Init(&ct); AFS_MD5_Update(&ct, &volume, 4); AFS_MD5_Update(&ct, &vnode, 4); AFS_MD5_Final(digest, &ct); - memcpy(&ino, digest, sizeof(afs_int32)); - ino ^= (ino ^ vno) & 1; - } else { + + /* Userspace may react oddly to an inode number of 0 or 1, so keep + * reading more of the md5 digest if we get back one of those. + * Make sure not to read beyond the end of the digest; if we somehow + * still have a 0, we will fall through to the non-md5 calculation. */ + for (offset = 0; + (ino == 0 || ino == 1) && + offset + sizeof(ino) <= sizeof(digest); + offset++) { + + memcpy(&ino, &digest[offset], sizeof(ino)); + ino ^= (ino ^ vno) & 1; + ino &= 0x7fffffff; /* Assumes 32 bit ino_t ..... */ + } + } + if (ino == 0 || ino == 1) { ino = (volume << 16) + vnode; } ino &= 0x7fffffff; /* Assumes 32 bit ino_t ..... */