diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2020-10-05 19:38:51 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2020-10-05 19:38:51 +0000 |
commit | 4e2266100dbec41e02e4d5df61173a634394456b (patch) | |
tree | 4e348b9a8c3501456eb405f8be020edaa203c7a8 /sys/kern/kern_descrip.c | |
parent | 9e9be081d8a6a3ded373db51c8bd13189c979979 (diff) | |
download | src-4e2266100dbec41e02e4d5df61173a634394456b.tar.gz src-4e2266100dbec41e02e4d5df61173a634394456b.zip |
cache: fix pwd use-after-free in setting up fallback
Since the code exits smr section prior to calling pwd_hold, the used
pwd can be freed and a new one allocated with the same address, making
the comparison erroneously true.
Note it is very unlikely anyone ran into it.
Notes
Notes:
svn path=/head/; revision=366462
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 6d67f9ce2e51..c533e714ce52 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -3344,6 +3344,17 @@ pwd_hold_filedesc(struct filedesc *fdp) return (pwd); } +bool +pwd_hold_smr(struct pwd *pwd) +{ + + MPASS(pwd != NULL); + if (__predict_true(refcount_acquire_if_not_zero(&pwd->pwd_refcount))) { + return (true); + } + return (false); +} + struct pwd * pwd_hold(struct thread *td) { @@ -3354,8 +3365,7 @@ pwd_hold(struct thread *td) vfs_smr_enter(); pwd = vfs_smr_entered_load(&fdp->fd_pwd); - MPASS(pwd != NULL); - if (__predict_true(refcount_acquire_if_not_zero(&pwd->pwd_refcount))) { + if (pwd_hold_smr(pwd)) { vfs_smr_exit(); return (pwd); } |