Page MenuHomeFreeBSD

D2808.id7189.diff
No OneTemporary

D2808.id7189.diff

Index: sys/fs/nfsserver/nfs_nfsdport.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdport.c
+++ sys/fs/nfsserver/nfs_nfsdport.c
@@ -349,7 +349,7 @@
*retdirp = NULL;
cnp->cn_nameptr = cnp->cn_pnbuf;
- ndp->ni_strictrelative = 0;
+ ndp->ni_nonrelativeerrno = 0;
/*
* Extract and set starting directory.
*/
Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c
+++ sys/kern/vfs_lookup.c
@@ -115,12 +115,12 @@
struct componentname *cnp;
cnp = &ndp->ni_cnd;
- if (ndp->ni_strictrelative != 0) {
+ if (ndp->ni_nonrelativeerrno != 0) {
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
#endif
- return (ENOTCAPABLE);
+ return (ndp->ni_nonrelativeerrno);
}
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
@@ -206,7 +206,8 @@
*/
if (error == 0 && IN_CAPABILITY_MODE(td) &&
(cnp->cn_flags & NOCAPCHECK) == 0) {
- ndp->ni_strictrelative = 1;
+ if (ndp->ni_nonrelativeerrno != EPERM)
+ ndp->ni_nonrelativeerrno = ENOTCAPABLE;
if (ndp->ni_dirfd == AT_FDCWD) {
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
@@ -274,14 +275,17 @@
* If file descriptor doesn't have all rights,
* all lookups relative to it must also be
* strictly relative.
+ *
+ * Don't overwrite a value of EPERM, however:
+ * we need to honour a user O_BENEATH request.
*/
CAP_ALL(&rights);
- if (!cap_rights_contains(&ndp->ni_filecaps.fc_rights,
- &rights) ||
- ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
- ndp->ni_filecaps.fc_nioctls != -1) {
- ndp->ni_strictrelative = 1;
- }
+ if ((!cap_rights_contains(&ndp->ni_filecaps.fc_rights,
+ &rights) ||
+ ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
+ ndp->ni_filecaps.fc_nioctls != -1) &&
+ ndp->ni_nonrelativeerrno != EPERM)
+ ndp->ni_nonrelativeerrno = ENOTCAPABLE;
#endif
}
if (error == 0 && dp->v_type != VDIR)
@@ -642,12 +646,21 @@
* the jail or chroot, don't let them out.
*/
if (cnp->cn_flags & ISDOTDOT) {
- if (ndp->ni_strictrelative != 0) {
#ifdef KTRACE
+ switch (ndp->ni_nonrelativeerrno) {
+ case EPERM:
+ if (KTRPOINT(curthread, KTR_NAMEI))
+ ktrnamei(cnp->cn_nameptr);
+ break;
+
+ case ENOTCAPABLE:
if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
+ break;
+ }
#endif
- error = ENOTCAPABLE;
+ if (ndp->ni_nonrelativeerrno != 0) {
+ error = ndp->ni_nonrelativeerrno;
goto bad;
}
if ((cnp->cn_flags & ISLASTCN) != 0 &&
@@ -1082,7 +1095,7 @@
ndp->ni_dirp = namep;
ndp->ni_dirfd = dirfd;
ndp->ni_startdir = startdir;
- ndp->ni_strictrelative = 0;
+ ndp->ni_nonrelativeerrno = 0;
if (rightsp != NULL)
ndp->ni_rightsneeded = *rightsp;
else
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -959,7 +959,7 @@
struct vnode *vp;
struct nameidata nd;
cap_rights_t rights;
- int cmode, error, indx;
+ int beneath, cmode, error, indx;
indx = -1;
@@ -968,6 +968,7 @@
/* XXX: audit dirfd */
cap_rights_init(&rights, CAP_LOOKUP);
flags_to_rights(flags, &rights);
+ beneath = ((flags & O_BENEATH) == O_BENEATH);
/*
* Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags
* may be specified.
@@ -996,6 +997,8 @@
cmode = ((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
&rights, td);
+ if (beneath)
+ nd.ni_nonrelativeerrno = EPERM;
td->td_dupfd = -1; /* XXX check for fdopen */
error = vn_open(&nd, &flags, cmode, fp);
if (error != 0) {
@@ -1010,11 +1013,13 @@
/*
* Handle special fdopen() case. bleh.
*
- * Don't do this for relative (capability) lookups; we don't
+ * Don't do this for capability or O_BENEATH lookups: we don't
* understand exactly what would happen, and we don't think
* that it ever should.
+ *
+ * XXXJA: can fdopen() ever be called with O_BENEATH?
*/
- if (nd.ni_strictrelative == 0 &&
+ if (nd.ni_nonrelativeerrno == 0 &&
(error == ENODEV || error == ENXIO) &&
td->td_dupfd >= 0) {
error = dupfdopen(td, fdp, td->td_dupfd, flags, error,
@@ -1060,7 +1065,8 @@
struct filecaps *fcaps;
#ifdef CAPABILITIES
- if (nd.ni_strictrelative == 1)
+ if (nd.ni_nonrelativeerrno != 0 &&
+ cap_rights_is_valid(&nd.ni_filecaps.fc_rights))
fcaps = &nd.ni_filecaps;
else
#endif
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -131,6 +131,7 @@
#if __BSD_VISIBLE
#define O_VERIFY 0x00200000 /* open only after verification */
+#define O_BENEATH 0x00400000 /* stay beneath a specified directory */
#endif
/*
Index: sys/sys/namei.h
===================================================================
--- sys/sys/namei.h
+++ sys/sys/namei.h
@@ -73,7 +73,7 @@
struct vnode *ni_rootdir; /* logical root directory */
struct vnode *ni_topdir; /* logical top directory */
int ni_dirfd; /* starting directory for *at functions */
- int ni_strictrelative; /* relative lookup only; no '..' */
+ int ni_nonrelativeerrno; /* errno for non-relative (..) lookup */
/*
* Results: returned from namei
*/

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 22, 12:49 PM (7 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24056706
Default Alt Text
D2808.id7189.diff (5 KB)

Event Timeline