]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
BSD: Work around panic in FlushVCache
authorBenjamin Kaduk <kaduk@mit.edu>
Fri, 13 Apr 2018 13:07:59 +0000 (08:07 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Thu, 7 Jun 2018 23:05:01 +0000 (19:05 -0400)
Commit 64cc7f0ca7a44bb214396c829268a541ab286c69 created the very useful
afs_StaleVCache() helper function, but unfortunately it also introduced
a subtle change into how we check for whether a vcache may be a directory.
Previously, we just used the low bit of the Fid's Vnode number, since files
have an even number and non-files an odd number.  The new version uses
that check but also explicitly checks `vType(avc)` against VDIR, and this new
check involves consulting information stored in the associated vnode entry,
not the vcache directly.  The afs_FlushVCache() implementation for
XBSD and DARWIN NULLs removes the cross-linkage between vcache and vnode,
so that AFSTOV(avc) becomes NULL.  Just a few lines later, it calls
afs_StaleVCacheFlags(), at which point vType() dereferences a bad pointer
(offset from a NULL pointer) and panics.  This would happen during shutdown,
or other periodic reclaim/flush events that can be scheduled.

Reviewed-on: https://gerrit.openafs.org/13014
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 54e84a98f9747bb5bb2ad4b8031115ad7684c914)

Change-Id: I810f72e0be8ab98ea6b4ac05c23bc0cb44e4da3a
Reviewed-on: https://gerrit.openafs.org/13113
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
src/afs/afs_vcache.c

index 36334c0aea354e8c66ec09c48190dfe0ce7ea1ab..5b98a73cb657069eb209bcc91fc007c9f6fe0307 100644 (file)
@@ -3252,7 +3252,8 @@ afs_StaleVCacheFlags(struct vcache *avc, afs_stalevc_flags_t flags,
     }
 
     if (do_dnlc) {
-       if ((avc->f.fid.Fid.Vnode & 1) || vType(avc) == VDIR ||
+       if ((avc->f.fid.Fid.Vnode & 1) ||
+           AFSTOV(avc) == NULL || vType(avc) == VDIR ||
            (avc->f.states & CForeign)) {
            /* This vcache is (or could be) a directory. */
            osi_dnlc_purgedp(avc);