]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
LINUX: Avoid mvid NULL deref in check_bad_parent
authorAndrew Deason <adeason@sinenomine.net>
Mon, 1 Dec 2014 16:23:23 +0000 (10:23 -0600)
committerStephan Wiesand <stephan.wiesand@desy.de>
Fri, 6 Feb 2015 10:02:40 +0000 (05:02 -0500)
check_bad_parent dereferences vcp->mvid, assuming it is not NULL (vcp
is a root vcache here, so mvid refers to the parent fid). However, in
some situations, vcp->mvid can be NULL.

When we first afs_GetVCache the fid, we try to set mvid by setting
mvid to the 'dotdot' structure in the volume struct. But we get that
volume struct from afs_GetVolume, which can fail (at the very least,
this can fail on network failure when looking up vldb information). If
it fails, then we do not set the mvid parent. On future lookups for
the fid, afs_GetVCache will return early for a fastpath, if the vcache
is already in memory. So, mvid will never get set in such a situation.

We also set the mvid parent fid in afs_lookup if we resolved a
mountpoint to the root vcache. However, this is skipped if CMValid is
not set on the vcache, so if CMValid is cleared right after resolving
the mountpoint (say, perhaps done by some other thread e.g. a callback
break or other reasons), then the mvid parent fid will not be set.

To avoid crashing in these situations, if vcp->mvid is NULL in
check_bad_parent, don't check the mvid, and assume it does not match
(since we don't know what it is).

This is a 1.6-only change. On the master branch, the problem is
addressed by commit 69e84bd8a2ccc6065c3a06b7239c855207b92e4d .

Change-Id: I3550cf5a01811ede17d74770161326667a6e8628
Reviewed-on: http://gerrit.openafs.org/11616
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
src/afs/LINUX/osi_vnodeops.c

index 9a164ea0158be1f96f63001a805a9e450179be23..959e3209ce4da351f01c70aff0923c058bbe989f 100644 (file)
@@ -949,7 +949,7 @@ check_bad_parent(struct dentry *dp)
     parent = dget_parent(dp);
     pvc = VTOAFS(parent->d_inode);
 
-    if (vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {      /* bad parent */
+    if (!vcp->mvid || vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {        /* bad parent */
        credp = crref();
 
        /* force a lookup, so vcp->mvid is fixed up */