diff options
Diffstat (limited to 'sys/fs/unionfs/union_vnops.c')
| -rw-r--r-- | sys/fs/unionfs/union_vnops.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index cd57a5cae459..aaff77dcb13d 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -76,14 +76,30 @@ KASSERT(((vp)->v_op == &unionfs_vnodeops), \ ("unionfs: it is not unionfs-vnode")) +static bool +unionfs_lookup_isroot(struct componentname *cnp, struct vnode *dvp) +{ + struct nameidata *ndp; + + if (dvp == NULL) + return (false); + if ((dvp->v_vflag & VV_ROOT) != 0) + return (true); + ndp = lookup_nameidata(cnp); + if (ndp == NULL) + return (false); + return (lookup_isroot(ndp, dvp)); +} + static int unionfs_lookup(struct vop_cachedlookup_args *ap) { int iswhiteout; int lockflag; int error , uerror, lerror; + uint64_t cnflags; u_long nameiop; - u_long cnflags, cnflagsbk; + u_long cnflagsbk; struct unionfs_node *dunp; struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp; struct vattr va; @@ -124,6 +140,10 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) if (LOOKUP != nameiop && udvp == NULLVP) return (EROFS); + if (unionfs_lookup_isroot(cnp, udvp) || + unionfs_lookup_isroot(cnp, ldvp)) + return (ENOENT); + if (udvp != NULLVP) { dtmpvp = udvp; if (ldvp != NULLVP) |
