| [2644] | 1 | From 97ca2bad9577380b10e7179ebecfc2dfa3fe4626 Mon Sep 17 00:00:00 2001 | 
|---|
|  | 2 | From: Andrew Deason <adeason@sinenomine.net> | 
|---|
|  | 3 | Date: Mon, 1 Dec 2014 10:23:23 -0600 | 
|---|
|  | 4 | Subject: [PATCH] Do not submit: LINUX: Avoid mvid NULL deref in | 
|---|
|  | 5 | check_bad_parent | 
|---|
|  | 6 |  | 
|---|
|  | 7 | check_bad_parent dereferences vcp->mvid, assuming it is not NULL (vcp | 
|---|
|  | 8 | is a root vcache here, so mvid refers to the parent fid). However, in | 
|---|
|  | 9 | some situations, vcp->mvid can be NULL. | 
|---|
|  | 10 |  | 
|---|
|  | 11 | When we first afs_GetVCache the fid, we try to set mvid by setting | 
|---|
|  | 12 | mvid to the 'dotdot' structure in the volume struct. But we get that | 
|---|
|  | 13 | volume struct from afs_GetVolume, which can fail (at the very least, | 
|---|
|  | 14 | this can fail on network failure when looking up vldb information). If | 
|---|
|  | 15 | it fails, then we do not set the mvid parent. On future lookups for | 
|---|
|  | 16 | the fid, afs_GetVCache will return early for a fastpath, if the vcache | 
|---|
|  | 17 | is already in memory. So, mvid will never get set in such a situation. | 
|---|
|  | 18 |  | 
|---|
|  | 19 | We also set the mvid parent fid in afs_lookup if we resolved a | 
|---|
|  | 20 | mountpoint to the root vcache. However, this is skipped if CMValid is | 
|---|
|  | 21 | not set on the vcache, so if CMValid is cleared right after resolving | 
|---|
|  | 22 | the mountpoint (say, perhaps done by some other thread e.g. a callback | 
|---|
|  | 23 | break or other reasons), then the mvid parent fid will not be set. | 
|---|
|  | 24 |  | 
|---|
|  | 25 | To avoid crashing in these situations, if vcp->mvid is NULL in | 
|---|
|  | 26 | check_bad_parent, don't check the mvid, and assume it does not match | 
|---|
|  | 27 | (since we don't know what it is). | 
|---|
|  | 28 |  | 
|---|
|  | 29 | FIXES 131967 | 
|---|
|  | 30 |  | 
|---|
|  | 31 | Change-Id: I3550cf5a01811ede17d74770161326667a6e8628 | 
|---|
|  | 32 | --- | 
|---|
|  | 33 | src/afs/LINUX/osi_vnodeops.c | 2 +- | 
|---|
|  | 34 | 1 file changed, 1 insertion(+), 1 deletion(-) | 
|---|
|  | 35 |  | 
|---|
|  | 36 | diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c | 
|---|
|  | 37 | index 9a164ea..959e320 100644 | 
|---|
|  | 38 | --- a/src/afs/LINUX/osi_vnodeops.c | 
|---|
|  | 39 | +++ b/src/afs/LINUX/osi_vnodeops.c | 
|---|
|  | 40 | @@ -949,7 +949,7 @@ check_bad_parent(struct dentry *dp) | 
|---|
|  | 41 | parent = dget_parent(dp); | 
|---|
|  | 42 | pvc = VTOAFS(parent->d_inode); | 
|---|
|  | 43 |  | 
|---|
|  | 44 | -    if (vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {      /* bad parent */ | 
|---|
|  | 45 | +    if (!vcp->mvid || vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {        /* bad parent */ | 
|---|
|  | 46 | credp = crref(); | 
|---|
|  | 47 |  | 
|---|
|  | 48 | /* force a lookup, so vcp->mvid is fixed up */ | 
|---|
|  | 49 | -- | 
|---|
|  | 50 | 2.2.0 | 
|---|
|  | 51 |  | 
|---|