Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146508363
D50418.id155860.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D50418.id155860.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D50418: namei: Make stackable filesystems check harder for jail roots
Attached
Detach File
Event Timeline
Log In to Comment