Page MenuHomeFreeBSD

D50418.id155860.diff
No OneTemporary

D50418.id155860.diff

diff --git a/share/man/man9/namei.9 b/share/man/man9/namei.9
--- a/share/man/man9/namei.9
+++ b/share/man/man9/namei.9
@@ -281,6 +281,15 @@
.Dv O_RESOLVE_BENEATH
flag for
.Xr openat 2 .
+.It Dv NAMEILOOKUP
+The component is embedded in a
+.Nm
+lookup structure, and the
+.Fn vfs_lookup_nameidata
+function can be used to obtain that structure.
+This can be useful in
+.Xr VOP_LOOKUP 9
+implementations which need to obtain extra lookup metadata.
.El
.Sh PARAMETERS DESCRIPTORS FLAGS
These flags are used for several purposes.
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -403,17 +403,25 @@
/*
* Renames in the lower mounts might create an inconsistent
- * configuration where lower vnode is moved out of the
- * directory tree remounted by our null mount. Do not try to
- * handle it fancy, just avoid VOP_LOOKUP() with DOTDOT name
- * which cannot be handled by VOP, at least passing over lower
- * root.
+ * configuration where lower vnode is moved out of the directory tree
+ * remounted by our null mount.
+ *
+ * Do not try to handle it fancy, just avoid VOP_LOOKUP() with DOTDOT
+ * name which cannot be handled by the VOP.
*/
- if ((ldvp->v_vflag & VV_ROOT) != 0 && (flags & ISDOTDOT) != 0) {
- KASSERT((dvp->v_vflag & VV_ROOT) == 0,
- ("ldvp %p fl %#x dvp %p fl %#x flags %#jx",
- ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, (uintmax_t)flags));
- return (ENOENT);
+ if ((flags & ISDOTDOT) != 0) {
+ struct nameidata *ndp;
+
+ if ((ldvp->v_vflag & VV_ROOT) != 0) {
+ KASSERT((dvp->v_vflag & VV_ROOT) == 0,
+ ("ldvp %p fl %#x dvp %p fl %#x flags %#jx",
+ ldvp, ldvp->v_vflag, dvp, dvp->v_vflag,
+ (uintmax_t)flags));
+ return (ENOENT);
+ }
+ ndp = vfs_lookup_nameidata(cnp);
+ if (ndp != NULL && vfs_lookup_isroot(ndp, ldvp))
+ return (ENOENT);
}
/*
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -76,6 +76,21 @@
VNASSERT(((vp)->v_op == &unionfs_vnodeops), vp, \
("%s: non-unionfs vnode", __func__))
+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 = vfs_lookup_nameidata(cnp);
+ if (ndp == NULL)
+ return (false);
+ return (vfs_lookup_isroot(ndp, dvp));
+}
+
static int
unionfs_lookup(struct vop_cachedlookup_args *ap)
{
@@ -149,6 +164,12 @@
goto unionfs_lookup_return;
}
+ if (unionfs_lookup_isroot(cnp, udvp) ||
+ unionfs_lookup_isroot(cnp, ldvp)) {
+ error = ENOENT;
+ goto unionfs_lookup_return;
+ }
+
if (udvp != NULLVP)
dtmpvp = udvp;
else
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -5276,7 +5276,6 @@
struct componentname *cnp;
struct namecache *ncp;
struct vnode *dvp;
- struct prison *pr;
u_char nc_flag;
ndp = fpl->ndp;
@@ -5288,15 +5287,7 @@
/*
* XXX this is racy the same way regular lookup is
*/
- for (pr = cnp->cn_cred->cr_prison; pr != NULL;
- pr = pr->pr_parent)
- if (dvp == pr->pr_root)
- break;
-
- if (dvp == ndp->ni_rootdir ||
- dvp == ndp->ni_topdir ||
- dvp == rootvnode ||
- pr != NULL) {
+ if (vfs_lookup_isroot(ndp, dvp)) {
fpl->tvp = dvp;
fpl->tvp_seqc = vn_seqc_read_any(dvp);
if (seqc_in_modify(fpl->tvp_seqc)) {
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -611,12 +611,12 @@
}
#endif
ndp->ni_cnd.cn_cred = td->td_ucred;
- KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n",
+ KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x",
__func__, ndp->ni_resflags));
KASSERT(cnp->cn_cred && td->td_proc, ("namei: bad cred/proc"));
KASSERT((cnp->cn_flags & NAMEI_INTERNAL_FLAGS) == 0,
- ("namei: unexpected flags: %" PRIx64 "\n",
- cnp->cn_flags & NAMEI_INTERNAL_FLAGS));
+ ("namei: unexpected flags: %#jx",
+ (uintmax_t)(cnp->cn_flags & NAMEI_INTERNAL_FLAGS)));
if (cnp->cn_flags & NOCACHE)
KASSERT(cnp->cn_nameiop != LOOKUP,
("%s: NOCACHE passed with LOOKUP", __func__));
@@ -862,6 +862,30 @@
return (error);
}
+struct nameidata *
+vfs_lookup_nameidata(struct componentname *cnp)
+{
+ if ((cnp->cn_flags & NAMEILOOKUP) == 0)
+ return (NULL);
+ return (__containerof(cnp, struct nameidata, ni_cnd));
+}
+
+/*
+ * Would a dotdot lookup relative to dvp cause this lookup to cross a jail or
+ * chroot boundary?
+ */
+bool
+vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp)
+{
+ for (struct prison *pr = ndp->ni_cnd.cn_cred->cr_prison; pr != NULL;
+ pr = pr->pr_parent) {
+ if (dvp == pr->pr_root)
+ return (true);
+ }
+ return (dvp == ndp->ni_rootdir || dvp == ndp->ni_topdir ||
+ dvp == rootvnode);
+}
+
/*
* FAILIFEXISTS handling.
*
@@ -1020,7 +1044,6 @@
char *lastchar; /* location of the last character */
struct vnode *dp = NULL; /* the directory we are searching */
struct vnode *tdp; /* saved dp */
- struct prison *pr;
size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */
int docache; /* == 0 do not cache last component */
int wantparent; /* 1 => wantparent or lockparent flag */
@@ -1206,13 +1229,9 @@
goto bad;
}
for (;;) {
- for (pr = cnp->cn_cred->cr_prison; pr != NULL;
- pr = pr->pr_parent)
- if (dp == pr->pr_root)
- break;
- bool isroot = dp == ndp->ni_rootdir ||
- dp == ndp->ni_topdir || dp == rootvnode ||
- pr != NULL;
+ bool isroot;
+
+ isroot = vfs_lookup_isroot(ndp, dp);
if (__predict_false(isroot && (ndp->ni_lcf &
(NI_LCF_STRICTREL | NI_LCF_STRICTREL_KTR)) != 0)) {
if ((ndp->ni_lcf & NI_LCF_STRICTREL_KTR) != 0)
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -152,6 +152,7 @@
#define LOCKSHARED 0x0100 /* Shared lock leaf */
#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */
#define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */
+#define NAMEILOOKUP 0x200000000ULL /* cnp is embedded in nameidata */
#define MODMASK 0xf000001ffULL /* mask of operational modifiers */
/*
@@ -249,7 +250,7 @@
NDINIT_PREFILL(_ndp); \
NDINIT_DBG(_ndp); \
_ndp->ni_cnd.cn_nameiop = op; \
- _ndp->ni_cnd.cn_flags = flags; \
+ _ndp->ni_cnd.cn_flags = (flags) | NAMEILOOKUP; \
_ndp->ni_segflg = segflg; \
_ndp->ni_dirp = namep; \
_ndp->ni_dirfd = dirfd; \
@@ -286,6 +287,8 @@
int namei(struct nameidata *ndp);
int vfs_lookup(struct nameidata *ndp);
+bool vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp);
+struct nameidata *vfs_lookup_nameidata(struct componentname *cnp);
int vfs_relookup(struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp, bool refstart);

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 4, 6:03 AM (5 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29230602
Default Alt Text
D50418.id155860.diff (6 KB)

Event Timeline