Page MenuHomeFreeBSD

D2808.id6215.diff
No OneTemporary

D2808.id6215.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
@@ -182,7 +182,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))
@@ -242,14 +243,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 != NULL) {
@@ -281,13 +285,13 @@
cnp->cn_nameptr = cnp->cn_pnbuf;
if (*(cnp->cn_nameptr) == '/') {
vrele(dp);
- if (ndp->ni_strictrelative != 0) {
+ if (ndp->ni_nonrelativeerrno != 0) {
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
#endif
namei_cleanup_cnp(cnp);
- return (ENOTCAPABLE);
+ return (ndp->ni_nonrelativeerrno);
}
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
@@ -622,12 +626,12 @@
* the jail or chroot, don't let them out.
*/
if (cnp->cn_flags & ISDOTDOT) {
- if (ndp->ni_strictrelative != 0) {
+ if (ndp->ni_nonrelativeerrno != 0) {
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
#endif
- error = ENOTCAPABLE;
+ error = ndp->ni_nonrelativeerrno;
goto bad;
}
if ((cnp->cn_flags & ISLASTCN) != 0 &&
@@ -1062,7 +1066,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
@@ -1049,7 +1049,7 @@
struct vnode *vp;
struct nameidata nd;
cap_rights_t rights;
- int cmode, error, indx;
+ int beneath, cmode, error, indx;
indx = -1;
@@ -1058,6 +1058,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.
@@ -1086,6 +1087,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) {
@@ -1100,11 +1103,11 @@
/*
* 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.
*/
- 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,
@@ -1150,7 +1153,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
Fri, Dec 12, 2:12 PM (2 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26897643
Default Alt Text
D2808.id6215.diff (5 KB)

Event Timeline