Page MenuHomeFreeBSD

D8110.id20909.diff
No OneTemporary

D8110.id20909.diff

Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c
+++ sys/kern/vfs_lookup.c
@@ -102,6 +102,7 @@
static void
namei_cleanup_cnp(struct componentname *cnp)
{
+
uma_zfree(namei_zone, cnp->cn_pnbuf);
#ifdef DIAGNOSTIC
cnp->cn_pnbuf = NULL;
@@ -158,12 +159,16 @@
char *cp; /* pointer into pathname argument */
struct vnode *dp; /* the directory we are searching */
struct iovec aiov; /* uio for reading symbolic links */
+ struct componentname *cnp;
+ struct thread *td;
+ struct proc *p;
+ cap_rights_t rights;
struct uio auio;
int error, linklen, startdir_used;
- struct componentname *cnp = &ndp->ni_cnd;
- struct thread *td = cnp->cn_thread;
- struct proc *p = td->td_proc;
+ cnp = &ndp->ni_cnd;
+ td = cnp->cn_thread;
+ p = td->td_proc;
ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred;
KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc"));
KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0,
@@ -200,9 +205,10 @@
#ifdef CAPABILITY_MODE
/*
- * In capability mode, lookups must be "strictly relative" (i.e.
- * not an absolute path, and not containing '..' components) to
+ * In capability mode, lookups must be "strictly relative" to
* a real file descriptor, not the pseudo-descriptor AT_FDCWD.
+ * We ensure that the passed path is not absolute, and all
+ * '..' components do not escape the relative root.
*/
if (error == 0 && IN_CAPABILITY_MODE(td) &&
(cnp->cn_flags & NOCAPCHECK) == 0) {
@@ -258,8 +264,6 @@
dp = fdp->fd_cdir;
VREF(dp);
} else {
- cap_rights_t rights;
-
rights = ndp->ni_rightsneeded;
cap_rights_set(&rights, CAP_LOOKUP);
@@ -299,6 +303,10 @@
}
SDT_PROBE3(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf,
cnp->cn_flags);
+ if (ndp->ni_strictrelative != 0) {
+ ndp->ni_capdir = dp;
+ vref(dp);
+ }
for (;;) {
ndp->ni_startdir = dp;
error = lookup(ndp);
@@ -386,6 +394,8 @@
vrele(ndp->ni_dvp);
out:
vrele(ndp->ni_rootdir);
+ if (ndp->ni_capdir != NULL)
+ vrele(ndp->ni_capdir);
namei_cleanup_cnp(cnp);
SDT_PROBE2(vfs, namei, lookup, return, error, NULL);
return (error);
@@ -618,9 +628,10 @@
/*
* Handle "..": five special cases.
- * 0. If doing a capability lookup, return ENOTCAPABLE (this is a
- * fairly conservative design choice, but it's the only one that we
- * are satisfied guarantees the property we're looking for).
+ * 0. If doing a capability lookup, return ENOTCAPABLE if the lookup
+ * would escape from the initial file descriptor directory.
+ * Checks are done before other verifications, to have
+ * cleaner semantic for e.g. jail roots or mp traversals.
* 1. Return an error if this is the last component of
* the name and the operation is DELETE or RENAME.
* 2. If at root directory (e.g. after chroot)
@@ -634,7 +645,7 @@
* the jail or chroot, don't let them out.
*/
if (cnp->cn_flags & ISDOTDOT) {
- if (ndp->ni_strictrelative != 0) {
+ if (ndp->ni_strictrelative != 0 && dp == ndp->ni_capdir) {
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
@@ -1082,6 +1093,7 @@
ndp->ni_dirfd = dirfd;
ndp->ni_startdir = startdir;
ndp->ni_strictrelative = 0;
+ ndp->ni_capdir = NULL;
if (rightsp != NULL)
ndp->ni_rightsneeded = *rightsp;
else
Index: sys/sys/namei.h
===================================================================
--- sys/sys/namei.h
+++ sys/sys/namei.h
@@ -71,6 +71,7 @@
struct vnode *ni_startdir; /* starting directory */
struct vnode *ni_rootdir; /* logical root directory */
struct vnode *ni_topdir; /* logical top directory */
+ struct vnode *ni_capdir; /* logical top dir for cap lookups */
int ni_dirfd; /* starting directory for *at functions */
int ni_strictrelative; /* relative lookup only; no '..' */
/*

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 14, 1:48 PM (5 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38911252
Default Alt Text
D8110.id20909.diff (3 KB)

Event Timeline