[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 | |
---|