git: b18029bc59d2 - main - unionfs_lookup(): fix wild accesses to vnode private data
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 09 Apr 2024 22:38:02 UTC
The branch main has been updated by jah:
URL: https://cgit.FreeBSD.org/src/commit/?id=b18029bc59d2ed6b0eeeb233189cf713b34b467c
commit b18029bc59d2ed6b0eeeb233189cf713b34b467c
Author: Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2024-02-18 00:19:32 +0000
Commit: Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2024-04-09 22:36:59 +0000
unionfs_lookup(): fix wild accesses to vnode private data
There are a few spots in which unionfs_lookup() accesses unionfs vnode
private data without holding the corresponding vnode lock or interlock.
Reviewed by: kib, olce
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D44601
---
sys/fs/unionfs/union_vnops.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 3e8853baeb4d..187d0513da25 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -79,7 +79,7 @@
static int
unionfs_lookup(struct vop_cachedlookup_args *ap)
{
- struct unionfs_node *dunp;
+ struct unionfs_node *dunp, *unp;
struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp;
struct vattr va;
struct componentname *cnp;
@@ -139,6 +139,9 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)
if (dtmpvp == udvp && ldvp != NULLVP) {
VOP_UNLOCK(udvp);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+ dunp = VTOUNIONFS(dvp);
+ if (error == 0 && dunp == NULL)
+ error = ENOENT;
}
if (error == 0) {
@@ -152,14 +155,15 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)
VOP_UNLOCK(vp);
vrele(vp);
+ dtmpvp = dunp->un_dvp;
+ vref(dtmpvp);
VOP_UNLOCK(dvp);
- *(ap->a_vpp) = dunp->un_dvp;
- vref(dunp->un_dvp);
+ *(ap->a_vpp) = dtmpvp;
if (nameiop == DELETE || nameiop == RENAME)
- vn_lock(dunp->un_dvp, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(dtmpvp, LK_EXCLUSIVE | LK_RETRY);
else if (cnp->cn_lkflags & LK_TYPE_MASK)
- vn_lock(dunp->un_dvp, cnp->cn_lkflags |
+ vn_lock(dtmpvp, cnp->cn_lkflags |
LK_RETRY);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
@@ -272,8 +276,12 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
lockflag = 1;
}
- error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount),
- udvp, VTOUNIONFS(vp), cnp, td);
+ unp = VTOUNIONFS(vp);
+ if (unp == NULL)
+ error = ENOENT;
+ else
+ error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount),
+ udvp, unp, cnp, td);
if (lockflag != 0)
VOP_UNLOCK(vp);
if (error != 0) {