Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144323289
D25886.id77050.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D25886.id77050.diff
View Options
Index: lib/libc/sys/access.2
===================================================================
--- lib/libc/sys/access.2
+++ lib/libc/sys/access.2
@@ -127,6 +127,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
Even if a process's real or effective user has appropriate privileges
Index: lib/libc/sys/chflags.2
===================================================================
--- lib/libc/sys/chflags.2
+++ lib/libc/sys/chflags.2
@@ -102,6 +102,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/chmod.2
===================================================================
--- lib/libc/sys/chmod.2
+++ lib/libc/sys/chmod.2
@@ -109,6 +109,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/chown.2
===================================================================
--- lib/libc/sys/chown.2
+++ lib/libc/sys/chown.2
@@ -126,6 +126,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/fhlink.2
===================================================================
--- lib/libc/sys/fhlink.2
+++ lib/libc/sys/fhlink.2
@@ -113,6 +113,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/getfh.2
===================================================================
--- lib/libc/sys/getfh.2
+++ lib/libc/sys/getfh.2
@@ -112,6 +112,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/link.2
===================================================================
--- lib/libc/sys/link.2
+++ lib/libc/sys/link.2
@@ -122,6 +122,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/open.2
===================================================================
--- lib/libc/sys/open.2
+++ lib/libc/sys/open.2
@@ -117,6 +117,12 @@
a directory passed by the
.Fa fd
argument is used as the topping point for the resolution.
+When
+.Dv O_BENEATH
+is specified with a relative path, the
+.Fa fd
+argument is used both as the starting point, and as the topping point
+for the resolution.
See the definition of the
.Dv O_BENEATH
flag below.
@@ -183,7 +189,8 @@
O_DIRECTORY error if file is not a directory
O_CLOEXEC set FD_CLOEXEC upon open
O_VERIFY verify the contents of the file
-O_BENEATH require path to be strictly relative to topping directory
+O_BENEATH require resolved path to be strictly relative to topping directory
+O_RELATIVE_BENEATH require walked path to be strictly relative to topping directory
.Ed
.Pp
Opening a file with
@@ -311,8 +318,8 @@
.Dv O_BENEATH
returns
.Er ENOTCAPABLE
-if the specified relative path, after resolving all symlinks and ".."
-references, does not reside in the directory hierarchy of
+if the specified path, after resolving all symlinks and ".."
+references, does not end up with tail residing in the directory hierarchy of
children beneath the topping directory.
Topping directory is the process current directory if relative
.Fa path
@@ -322,11 +329,20 @@
.Fa fd
argument when using
.Fn openat .
-If the specified path is absolute,
.Dv O_BENEATH
allows arbitrary prefix that ends up at the topping directory,
after which all further resolved components must be under it.
.Pp
+.Dv O_RELATIVE_BENEATH
+returns
+.Er ENOTCAPABLE
+if any intermediate component of the specified relative path does not
+reside in the directory hierarchy beneath the topping directory.
+Comparing to
+.Dv O_BENEATH,
+absolute paths or even the temporal escape from beneath of the topping
+directory is not allowed.
+.Pp
When
.Fa fd
is opened with
@@ -540,6 +556,12 @@
.Dv O_EXEC
or
.Dv O_SEARCH .
+.It Bq Er EINVAL
+The
+.Dv O_RELATIVE_BENEATH
+flag is specified and
+.Dv path
+is absolute.
.It Bq Er EBADF
The
.Fa path
@@ -582,6 +604,12 @@
or the relative
.Fa path
escapes it.
+.It Bq Er ENOTCAPABLE
+The
+.Dv O_RELATIVE_BENEATH
+flag was provided, and the relative
+.Fa path
+escapes topping directory.
.El
.Sh SEE ALSO
.Xr chmod 2 ,
Index: lib/libc/sys/stat.2
===================================================================
--- lib/libc/sys/stat.2
+++ lib/libc/sys/stat.2
@@ -120,6 +120,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/unlink.2
===================================================================
--- lib/libc/sys/unlink.2
+++ lib/libc/sys/unlink.2
@@ -100,6 +100,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Pp
If
Index: lib/libc/sys/utimensat.2
===================================================================
--- lib/libc/sys/utimensat.2
+++ lib/libc/sys/utimensat.2
@@ -154,6 +154,13 @@
flag in the
.Xr open 2
manual page.
+.It Dv AT_RELATIVE_BENEATH
+Only walks paths below the topping directory.
+See the description of the
+.Dv O_RELATIVE_BENEATH
+flag in the
+.Xr open 2
+manual page.
.El
.Sh RETURN VALUES
.Rv -std
Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c
+++ sys/kern/vfs_lookup.c
@@ -178,11 +178,13 @@
nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp)
{
struct nameicap_tracker *nt;
+ struct componentname *cnp;
if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR)
return;
- if ((ndp->ni_lcf & (NI_LCF_BENEATH_ABS | NI_LCF_BENEATH_LATCHED)) ==
- NI_LCF_BENEATH_ABS) {
+ cnp = &ndp->ni_cnd;
+ if ((cnp->cn_flags & BENEATH) != 0 &&
+ (ndp->ni_lcf & NI_LCF_BENEATH_LATCHED) == 0) {
MPASS((ndp->ni_lcf & NI_LCF_LATCH) != 0);
if (dp != ndp->ni_beneath_latch)
return;
@@ -215,7 +217,11 @@
/*
* For dotdot lookups in capability mode, only allow the component
* lookup to succeed if the resulting directory was already traversed
- * during the operation. Also fail dotdot lookups for non-local
+ * during the operation. This catches situations where already
+ * traversed directory is moved to different parent, and then we walk
+ * over it with dotdots.
+ *
+ * Also allow to force failure of dotdot lookups for non-local
* filesystems, where external agents might assist local lookups to
* escape the compartment.
*/
@@ -234,14 +240,15 @@
return (ENOTCAPABLE);
TAILQ_FOREACH_REVERSE(nt, &ndp->ni_cap_tracker, nameicap_tracker_head,
nm_link) {
+ if ((ndp->ni_lcf & NI_LCF_LATCH) != 0 &&
+ ndp->ni_beneath_latch == nt->dp) {
+ ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED;
+ nameicap_cleanup(ndp, false);
+ return (0);
+ }
if (dp == nt->dp)
return (0);
}
- if ((ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) {
- ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED;
- nameicap_cleanup(ndp, false);
- return (0);
- }
return (ENOTCAPABLE);
}
@@ -318,6 +325,7 @@
*/
if (IN_CAPABILITY_MODE(td) && (cnp->cn_flags & NOCAPCHECK) == 0) {
ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
+ ndp->ni_resflags |= NIRES_STRICTREL;
if (ndp->ni_dirfd == AT_FDCWD) {
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
@@ -396,6 +404,7 @@
ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
ndp->ni_filecaps.fc_nioctls != -1) {
ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
+ ndp->ni_resflags |= NIRES_STRICTREL;
}
#endif
}
@@ -419,6 +428,16 @@
if (error == 0)
ndp->ni_lcf |= NI_LCF_LATCH;
}
+ if (error == 0 && (cnp->cn_flags & RBENEATH) != 0) {
+ if (cnp->cn_pnbuf[0] == '/' ||
+ (ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) {
+ error = EINVAL;
+ } else if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0) {
+ ndp->ni_lcf |= NI_LCF_STRICTRELATIVE |
+ NI_LCF_CAP_DOTDOT;
+ }
+ }
+
/*
* If we are auditing the kernel pathname, save the user pathname.
*/
@@ -586,8 +605,8 @@
namei_cleanup_cnp(cnp);
} else
cnp->cn_flags |= HASBUF;
- if ((ndp->ni_lcf & (NI_LCF_BENEATH_ABS |
- NI_LCF_BENEATH_LATCHED)) == NI_LCF_BENEATH_ABS) {
+ if ((ndp->ni_lcf & (NI_LCF_LATCH |
+ NI_LCF_BENEATH_LATCHED)) == NI_LCF_LATCH) {
NDFREE(ndp, 0);
error = ENOTCAPABLE;
}
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -112,6 +112,26 @@
static int kern_linkat_vp(struct thread *td, struct vnode *vp, int fd,
const char *path, enum uio_seg segflag);
+static uint64_t
+at2cnpflags(u_int at_flags, u_int mask)
+{
+ u_int64_t res;
+
+ res = 0;
+ at_flags &= mask;
+ if ((at_flags & AT_BENEATH) != 0)
+ res |= BENEATH;
+ if ((at_flags & AT_RESOLVE_BENEATH) != 0)
+ res |= RBENEATH;
+ /* FOLLOW is pseudo flag */
+ if ((at_flags & AT_SYMLINK_NOFOLLOW) != 0)
+ res |= NOFOLLOW;
+ if ((mask & AT_SYMLINK_FOLLOW) != 0 &&
+ (at_flags & AT_SYMLINK_FOLLOW) == 0)
+ res |= NOFOLLOW;
+ return (res);
+}
+
int
kern_sync(struct thread *td)
{
@@ -1136,7 +1156,7 @@
* understand exactly what would happen, and we don't think
* that it ever should.
*/
- if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) == 0 &&
+ if ((nd.ni_resflags & NIRES_STRICTREL) == 0 &&
(error == ENODEV || error == ENXIO) &&
td->td_dupfd >= 0) {
error = dupfdopen(td, fdp, td->td_dupfd, flags, error,
@@ -1183,7 +1203,7 @@
struct filecaps *fcaps;
#ifdef CAPABILITIES
- if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE) != 0)
+ if ((nd.ni_resflags & NIRES_STRICTREL) != 0)
fcaps = &nd.ni_filecaps;
else
#endif
@@ -1484,12 +1504,13 @@
int flag;
flag = uap->flag;
- if ((flag & ~(AT_SYMLINK_FOLLOW | AT_BENEATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_FOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2,
- UIO_USERSPACE, ((flag & AT_SYMLINK_FOLLOW) != 0 ? FOLLOW :
- NOFOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0)));
+ UIO_USERSPACE, at2cnpflags(flag, AT_SYMLINK_FOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)));
}
int hardlink_check_uid = 0;
@@ -1854,7 +1875,7 @@
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
- ((flag & AT_BENEATH) != 0 ? BENEATH : 0),
+ at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH),
pathseg, path, dfd, &cap_unlinkat_rights, td);
if ((error = namei(&nd)) != 0) {
if (error == EINVAL)
@@ -2057,7 +2078,7 @@
struct nameidata nd;
int error;
- if ((flag & ~(AT_EACCESS | AT_BENEATH)) != 0)
+ if ((flag & ~(AT_EACCESS | AT_BENEATH | AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
if (amode != F_OK && (amode & ~(R_OK | W_OK | X_OK)) != 0)
return (EINVAL);
@@ -2078,7 +2099,7 @@
usecred = cred;
AUDIT_ARG_VALUE(amode);
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1 | ((flag & AT_BENEATH) != 0 ? BENEATH : 0),
+ AUDITVNODE1 | at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH),
pathseg, path, fd, &cap_fstat_rights, td);
if ((error = namei(&nd)) != 0)
goto out;
@@ -2369,13 +2390,13 @@
struct nameidata nd;
int error;
- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
- NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) != 0 ?
- NOFOLLOW : FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) |
- LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,
- &cap_fstat_rights, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_BENEATH |
+ AT_RESOLVE_BENEATH | AT_SYMLINK_NOFOLLOW) | LOCKSHARED | LOCKLEAF |
+ AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2693,7 +2714,8 @@
sys_chflagsat(struct thread *td, struct chflagsat_args *uap)
{
- if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE,
@@ -2722,12 +2744,11 @@
enum uio_seg pathseg, u_long flags, int atflag)
{
struct nameidata nd;
- int error, follow;
+ int error;
AUDIT_ARG_FFLAGS(flags);
- follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- follow |= (atflag & AT_BENEATH) != 0 ? BENEATH : 0;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(atflag, AT_SYMLINK_NOFOLLOW |
+ AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
&cap_fchflags_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2822,7 +2843,8 @@
sys_fchmodat(struct thread *td, struct fchmodat_args *uap)
{
- if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE,
@@ -2851,12 +2873,11 @@
enum uio_seg pathseg, mode_t mode, int flag)
{
struct nameidata nd;
- int error, follow;
+ int error;
AUDIT_ARG_MODE(mode);
- follow = (flag & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW : FOLLOW;
- follow |= (flag & AT_BENEATH) != 0 ? BENEATH : 0;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
+ AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
&cap_fchmod_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2951,7 +2972,8 @@
sys_fchownat(struct thread *td, struct fchownat_args *uap)
{
- if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid,
@@ -2963,12 +2985,11 @@
enum uio_seg pathseg, int uid, int gid, int flag)
{
struct nameidata nd;
- int error, follow;
+ int error;
AUDIT_ARG_OWNER(uid, gid);
- follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- follow |= (flag & AT_BENEATH) != 0 ? BENEATH : 0;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
+ AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
&cap_fchown_rights, td);
if ((error = namei(&nd)) != 0)
@@ -3320,13 +3341,14 @@
struct timespec ts[2];
int error, flags;
- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0)
return (error);
- NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
- FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) | AUDITVNODE1,
+ NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
+ AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1,
pathseg, path, fd, &cap_futimes_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3821,7 +3843,7 @@
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
- ((flag & AT_BENEATH) != 0 ? BENEATH : 0),
+ at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH),
pathseg, path, dfd, &cap_unlinkat_rights, td);
if ((error = namei(&nd)) != 0)
goto fdout;
@@ -4307,7 +4329,8 @@
sys_getfhat(struct thread *td, struct getfhat_args *uap)
{
- if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH |
+ AT_RESOLVE_BENEATH)) != 0)
return (EINVAL);
return (kern_getfhat(td, uap->flags, uap->fd, uap->path, UIO_USERSPACE,
uap->fhp));
@@ -4325,9 +4348,9 @@
error = priv_check(td, PRIV_VFS_GETFH);
if (error != 0)
return (error);
- NDINIT_AT(&nd, LOOKUP, ((flags & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW :
- FOLLOW) | ((flags & AT_BENEATH) != 0 ? BENEATH : 0) | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, td);
+ NDINIT_AT(&nd, LOOKUP, at2cnpflags(flags, AT_SYMLINK_NOFOLLOW |
+ AT_BENEATH | AT_RESOLVE_BENEATH) | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, td);
error = namei(&nd);
if (error != 0)
return (error);
Index: sys/kern/vfs_vnops.c
===================================================================
--- sys/kern/vfs_vnops.c
+++ sys/kern/vfs_vnops.c
@@ -192,6 +192,23 @@
return (vn_open_cred(ndp, flagp, cmode, 0, td->td_ucred, fp));
}
+static uint64_t
+open2nameif(int fmode, u_int vn_open_flags)
+{
+ uint64_t res;
+
+ res = ISOPEN | LOCKLEAF;
+ if ((fmode & O_BENEATH) != 0)
+ res |= BENEATH;
+ if ((fmode & O_RESOLVE_BENEATH) != 0)
+ res |= RBENEATH;
+ if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0)
+ res |= AUDITVNODE1;
+ if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0)
+ res |= NOCAPCHECK;
+ return (res);
+}
+
/*
* Common code for vnode open operations via a name lookup.
* Lookup the vnode and invoke VOP_CREATE if needed.
@@ -218,19 +235,14 @@
return (EINVAL);
else if ((fmode & (O_CREAT | O_DIRECTORY)) == O_CREAT) {
ndp->ni_cnd.cn_nameiop = CREATE;
+ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags);
/*
* Set NOCACHE to avoid flushing the cache when
* rolling in many files at once.
*/
- ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | NOCACHE;
+ ndp->ni_cnd.cn_flags |= LOCKPARENT | NOCACHE;
if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
ndp->ni_cnd.cn_flags |= FOLLOW;
- if ((fmode & O_BENEATH) != 0)
- ndp->ni_cnd.cn_flags |= BENEATH;
- if (!(vn_open_flags & VN_OPEN_NOAUDIT))
- ndp->ni_cnd.cn_flags |= AUDITVNODE1;
- if (vn_open_flags & VN_OPEN_NOCAPCHECK)
- ndp->ni_cnd.cn_flags |= NOCAPCHECK;
if ((vn_open_flags & VN_OPEN_INVFS) == 0)
bwillwrite();
if ((error = namei(ndp)) != 0)
@@ -285,16 +297,11 @@
}
} else {
ndp->ni_cnd.cn_nameiop = LOOKUP;
- ndp->ni_cnd.cn_flags = ISOPEN |
- ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
- if (!(fmode & FWRITE))
+ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags);
+ ndp->ni_cnd.cn_flags |= (fmode & O_NOFOLLOW) ? NOFOLLOW :
+ FOLLOW;
+ if ((fmode & FWRITE) == 0)
ndp->ni_cnd.cn_flags |= LOCKSHARED;
- if ((fmode & O_BENEATH) != 0)
- ndp->ni_cnd.cn_flags |= BENEATH;
- if (!(vn_open_flags & VN_OPEN_NOAUDIT))
- ndp->ni_cnd.cn_flags |= AUDITVNODE1;
- if (vn_open_flags & VN_OPEN_NOCAPCHECK)
- ndp->ni_cnd.cn_flags |= NOCAPCHECK;
if ((error = namei(ndp)) != 0)
return (error);
vp = ndp->ni_vp;
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -136,6 +136,9 @@
#if __BSD_VISIBLE
#define O_VERIFY 0x00200000 /* open only after verification */
#define O_BENEATH 0x00400000 /* Fail if not under cwd */
+#define O_RESOLVE_BENEATH 0x00800000 /* As O_BENEATH, but do not allow
+ resolve to walk out of cwd even to
+ return back */
#endif
/*
@@ -215,6 +218,9 @@
#define AT_SYMLINK_FOLLOW 0x0400 /* Follow symbolic link */
#define AT_REMOVEDIR 0x0800 /* Remove directory instead of file */
#define AT_BENEATH 0x1000 /* Fail if not under dirfd */
+#define AT_RESOLVE_BENEATH 0x2000 /* As AT_BENEATH, but do not allow
+ resolve to walk out of dirfd even
+ to return back */
#endif
/*
Index: sys/sys/namei.h
===================================================================
--- sys/sys/namei.h
+++ sys/sys/namei.h
@@ -133,7 +133,8 @@
#define BENEATH 0x0080 /* No escape from the start dir */
#define LOCKSHARED 0x0100 /* Shared lock leaf */
#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */
-#define MODMASK 0x01fc /* mask of operational modifiers */
+#define RBENEATH 0x100000000ULL /* XXX */
+#define MODMASK 0xf000001fcULL /* mask of operational modifiers */
/*
* Namei parameter descriptors.
*
@@ -183,6 +184,7 @@
* Namei results flags
*/
#define NIRES_ABS 0x00000001 /* Path was absolute */
+#define NIRES_STRICTREL 0x00000002
/*
* Flags in ni_lcf, valid for the duration of the namei call.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 8, 8:33 PM (7 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28495168
Default Alt Text
D25886.id77050.diff (20 KB)
Attached To
Mode
D25886: Add O_RESOLVE_BENEATH and AT_RESOLVE_BENEATH to mimic Linux' RESOLVE_BENEATH
Attached
Detach File
Event Timeline
Log In to Comment