From: Benjamin Kaduk Date: Fri, 13 Apr 2018 13:07:59 +0000 (-0500) Subject: BSD: Work around panic in FlushVCache X-Git-Tag: upstream/1.8.1_pre2^2~47 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=c80af69e04bb39b0aa3d1b6705034fd26358f7c7;p=packages%2Fo%2Fopenafs.git BSD: Work around panic in FlushVCache 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 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk (cherry picked from commit 54e84a98f9747bb5bb2ad4b8031115ad7684c914) Change-Id: I810f72e0be8ab98ea6b4ac05c23bc0cb44e4da3a Reviewed-on: https://gerrit.openafs.org/13113 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk --- diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 36334c0ae..5b98a73cb 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -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);