]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afs: Ensure afs_calc_inum yields nonzero ino
authorAndrew Deason <adeason@sinenomine.net>
Wed, 22 Jun 2011 18:44:38 +0000 (13:44 -0500)
committerDerrick Brashear <shadow@dementix.org>
Wed, 25 Apr 2012 10:38:38 +0000 (03:38 -0700)
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 <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 39083fe1edab784fcd75eacbdaaf7f6affa14c9f)

Change-Id: I3d06a4b5dc76934b24ced883b1985bced35c893a
Reviewed-on: http://gerrit.openafs.org/7276
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
src/afs/afs_util.c

index 2b20a94bac008ac1fb6744671f6c905b8f9957e3..daf86ff4c25d6cc2daeab19b4d3799a1e0e6643e 100644 (file)
@@ -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 ..... */