diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2018-10-25 22:16:34 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2018-10-25 22:16:34 +0000 |
| commit | 4f77f4888465e376b93ae660ae8f19b6aeebecbe (patch) | |
| tree | 4bfdb7fc4aed141758cfd1ffd7a1180d3e1cfc5a /sys | |
| parent | 2b2135b8b55637077a8c6b1a9a491facb5f0471f (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/cddl/compat/opensolaris/sys/vnode.h | 2 | ||||
| -rw-r--r-- | sys/compat/cloudabi/cloudabi_file.c | 4 | ||||
| -rw-r--r-- | sys/compat/linux/linux_file.c | 8 | ||||
| -rw-r--r-- | sys/kern/vfs_lookup.c | 9 | ||||
| -rw-r--r-- | sys/kern/vfs_mountroot.c | 2 | ||||
| -rw-r--r-- | sys/kern/vfs_syscalls.c | 83 | ||||
| -rw-r--r-- | sys/kern/vfs_vnops.c | 4 | ||||
| -rw-r--r-- | sys/sys/fcntl.h | 11 | ||||
| -rw-r--r-- | sys/sys/namei.h | 1 | ||||
| -rw-r--r-- | sys/sys/syscallsubr.h | 4 | ||||
| -rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 2 |
11 files changed, 72 insertions, 58 deletions
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h index d15cd88c193a..54e78f2ffe9f 100644 --- a/sys/cddl/compat/opensolaris/sys/vnode.h +++ b/sys/cddl/compat/opensolaris/sys/vnode.h @@ -278,7 +278,7 @@ vn_remove(char *fnamep, enum uio_seg seg, enum rm dirflag) ASSERT(seg == UIO_SYSSPACE); ASSERT(dirflag == RMFILE); - return (kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0)); + return (kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0, 0)); } #endif /* _KERNEL */ diff --git a/sys/compat/cloudabi/cloudabi_file.c b/sys/compat/cloudabi/cloudabi_file.c index 19f13570b77d..602ae5042962 100644 --- a/sys/compat/cloudabi/cloudabi_file.c +++ b/sys/compat/cloudabi/cloudabi_file.c @@ -752,9 +752,9 @@ cloudabi_sys_file_unlink(struct thread *td, return (error); if (uap->flags & CLOUDABI_UNLINK_REMOVEDIR) - error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE); + error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE, 0); else - error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0, 0); cloudabi_freestr(path); return (error); } diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 017e947cb23a..ecc95370d4c1 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -590,7 +590,7 @@ linux_unlink(struct thread *td, struct linux_unlink_args *args) printf(ARGS(unlink, "%s"), path); #endif - error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0, 0); if (error == EPERM) { /* Introduce POSIX noncompliant behaviour of Linux */ if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, @@ -623,9 +623,9 @@ linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args) #endif if (args->flag & LINUX_AT_REMOVEDIR) - error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE); + error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE, 0); else - error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0, 0); if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) { /* Introduce POSIX noncompliant behaviour of Linux */ if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path, @@ -741,7 +741,7 @@ linux_rmdir(struct thread *td, struct linux_rmdir_args *args) if (ldebug(rmdir)) printf(ARGS(rmdir, "%s"), path); #endif - error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE); + error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE, 0); LFREEPATH(path); return (error); } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 675c0aa02ac3..496a4e6f5a68 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -242,7 +242,8 @@ namei_handle_root(struct nameidata *ndp, struct vnode **dpp) struct componentname *cnp; cnp = &ndp->ni_cnd; - if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0) { + if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 || + (cnp->cn_flags & BENEATH) != 0) { #ifdef KTRACE if (KTRPOINT(curthread, KTR_CAPFAIL)) ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); @@ -434,8 +435,10 @@ namei(struct nameidata *ndp) vrele(dp); goto out; } - if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && - lookup_cap_dotdot != 0) + if (((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && + lookup_cap_dotdot != 0) || + ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0 && + (cnp->cn_flags & BENEATH) != 0)) ndp->ni_lcf |= NI_LCF_CAP_DOTDOT; SDT_PROBE3(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf, cnp->cn_flags); diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c index 0c46d68e6409..babcf5a77732 100644 --- a/sys/kern/vfs_mountroot.c +++ b/sys/kern/vfs_mountroot.c @@ -389,7 +389,7 @@ vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) vfs_unbusy(mpdevfs); /* Unlink the no longer needed /dev/dev -> / symlink */ error = kern_unlinkat(td, AT_FDCWD, "/dev/dev", - UIO_SYSSPACE, 0); + UIO_SYSSPACE, 0, 0); if (error) printf("mountroot: unable to unlink /dev/dev " "(error %d)\n", error); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index a0ddefaa15df..a54e8bc1b2cc 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1443,11 +1443,12 @@ sys_linkat(struct thread *td, struct linkat_args *uap) int flag; flag = uap->flag; - if (flag & ~AT_SYMLINK_FOLLOW) + if ((flag & ~(AT_SYMLINK_FOLLOW | AT_BENEATH)) != 0) return (EINVAL); return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2, - UIO_USERSPACE, (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : NOFOLLOW)); + UIO_USERSPACE, ((flag & AT_SYMLINK_FOLLOW) != 0 ? FOLLOW : + NOFOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0))); } int hardlink_check_uid = 0; @@ -1731,7 +1732,7 @@ int sys_unlink(struct thread *td, struct unlink_args *uap) { - return (kern_unlinkat(td, AT_FDCWD, uap->path, UIO_USERSPACE, 0)); + return (kern_unlinkat(td, AT_FDCWD, uap->path, UIO_USERSPACE, 0, 0)); } #ifndef _SYS_SYSPROTO_H_ @@ -1744,22 +1745,25 @@ struct unlinkat_args { int sys_unlinkat(struct thread *td, struct unlinkat_args *uap) { - int flag = uap->flag; - int fd = uap->fd; - char *path = uap->path; + int fd, flag; + char *path; + + flag = uap->flag; + fd = uap->fd; + path = uap->path; - if (flag & ~AT_REMOVEDIR) + if ((flag & ~(AT_REMOVEDIR | AT_BENEATH)) != 0) return (EINVAL); - if (flag & AT_REMOVEDIR) - return (kern_rmdirat(td, fd, path, UIO_USERSPACE)); + if ((uap->flag & AT_REMOVEDIR) != 0) + return (kern_rmdirat(td, fd, path, UIO_USERSPACE, flag)); else - return (kern_unlinkat(td, fd, path, UIO_USERSPACE, 0)); + return (kern_unlinkat(td, fd, path, UIO_USERSPACE, flag, 0)); } int kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, - ino_t oldinum) + int flag, ino_t oldinum) { struct mount *mp; struct vnode *vp; @@ -1769,7 +1773,8 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1, + NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 | + ((flag & AT_BENEATH) != 0 ? BENEATH : 0), pathseg, path, fd, &cap_unlinkat_rights, td); if ((error = namei(&nd)) != 0) return (error == EINVAL ? EPERM : error); @@ -1960,7 +1965,7 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct nameidata nd; int error; - if (flag & ~AT_EACCESS) + if ((flag & ~(AT_EACCESS | AT_BENEATH)) != 0) return (EINVAL); if (amode != F_OK && (amode & ~(R_OK | W_OK | X_OK)) != 0) return (EINVAL); @@ -1981,8 +1986,8 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, usecred = cred; AUDIT_ARG_VALUE(amode); NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | - AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights, - td); + AUDITVNODE1 | ((flag & AT_BENEATH) != 0 ? BENEATH : 0), + pathseg, path, fd, &cap_fstat_rights, td); if ((error = namei(&nd)) != 0) goto out; vp = nd.ni_vp; @@ -2273,11 +2278,12 @@ kern_statat(struct thread *td, int flag, int fd, char *path, struct stat sb; int error; - if (flag & ~AT_SYMLINK_NOFOLLOW) + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0) return (EINVAL); - NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : - FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd, + 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); if ((error = namei(&nd)) != 0) @@ -2588,15 +2594,12 @@ struct chflagsat_args { int sys_chflagsat(struct thread *td, struct chflagsat_args *uap) { - int fd = uap->fd; - const char *path = uap->path; - u_long flags = uap->flags; - int atflag = uap->atflag; - if (atflag & ~AT_SYMLINK_NOFOLLOW) + if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0) return (EINVAL); - return (kern_chflagsat(td, fd, path, UIO_USERSPACE, flags, atflag)); + return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->flags, uap->atflag)); } /* @@ -2625,6 +2628,7 @@ kern_chflagsat(struct thread *td, int fd, const char *path, 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, &cap_fchflags_rights, td); if ((error = namei(&nd)) != 0) @@ -2719,15 +2723,12 @@ struct fchmodat_args { int sys_fchmodat(struct thread *td, struct fchmodat_args *uap) { - int flag = uap->flag; - int fd = uap->fd; - char *path = uap->path; - mode_t mode = uap->mode; - if (flag & ~AT_SYMLINK_NOFOLLOW) + if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0) return (EINVAL); - return (kern_fchmodat(td, fd, path, UIO_USERSPACE, mode, flag)); + return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->mode, uap->flag)); } /* @@ -2755,7 +2756,8 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, int error, follow; AUDIT_ARG_MODE(mode); - follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; + follow = (flag & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW : FOLLOW; + follow |= (flag & AT_BENEATH) != 0 ? BENEATH : 0; NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd, &cap_fchmod_rights, td); if ((error = namei(&nd)) != 0) @@ -2850,10 +2852,8 @@ struct fchownat_args { int sys_fchownat(struct thread *td, struct fchownat_args *uap) { - int flag; - flag = uap->flag; - if (flag & ~AT_SYMLINK_NOFOLLOW) + if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0) return (EINVAL); return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid, @@ -2869,6 +2869,7 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg, 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, &cap_fchown_rights, td); @@ -3220,14 +3221,14 @@ kern_utimensat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct timespec ts[2]; int error, flags; - if (flag & ~AT_SYMLINK_NOFOLLOW) + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0) return (EINVAL); if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0) return (error); NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : - FOLLOW) | AUDITVNODE1, pathseg, path, fd, - &cap_futimes_rights, td); + FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) | AUDITVNODE1, + pathseg, path, fd, &cap_futimes_rights, td); if ((error = namei(&nd)) != 0) return (error); /* @@ -3671,11 +3672,12 @@ int sys_rmdir(struct thread *td, struct rmdir_args *uap) { - return (kern_rmdirat(td, AT_FDCWD, uap->path, UIO_USERSPACE)); + return (kern_rmdirat(td, AT_FDCWD, uap->path, UIO_USERSPACE, 0)); } int -kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg) +kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int flag) { struct mount *mp; struct vnode *vp; @@ -3684,7 +3686,8 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg) restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1, + NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 | + ((flag & AT_BENEATH) != 0 ? BENEATH : 0), pathseg, path, fd, &cap_unlinkat_rights, td); if ((error = namei(&nd)) != 0) return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 00392ee3a072..9c7280125deb 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -212,6 +212,8 @@ restart: ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | 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) @@ -269,6 +271,8 @@ restart: ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF; if (!(fmode & FWRITE)) 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) diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index cce169b4e4a1..04eab5e27ed1 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -133,6 +133,7 @@ typedef __pid_t pid_t; #if __BSD_VISIBLE #define O_VERIFY 0x00200000 /* open only after verification */ +#define O_BENEATH 0x00400000 /* Fail if not under cwd */ #endif /* @@ -206,10 +207,12 @@ typedef __pid_t pid_t; /* * Miscellaneous flags for the *at() syscalls. */ -#define AT_EACCESS 0x100 /* Check access using effective user and group ID */ -#define AT_SYMLINK_NOFOLLOW 0x200 /* Do not follow symbolic links */ -#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic link */ -#define AT_REMOVEDIR 0x800 /* Remove directory instead of file */ +#define AT_EACCESS 0x0100 /* Check access using effective user + and group ID */ +#define AT_SYMLINK_NOFOLLOW 0x0200 /* Do not follow symbolic links */ +#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 */ #endif /* diff --git a/sys/sys/namei.h b/sys/sys/namei.h index f2c2f7543741..3d2a0bc2c002 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -119,6 +119,7 @@ struct nameidata { #define WANTPARENT 0x0010 /* want parent vnode returned unlocked */ #define NOCACHE 0x0020 /* name must not be left in cache */ #define FOLLOW 0x0040 /* follow symbolic links */ +#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 */ diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 5ec4fa33f534..20e4cb39770e 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -219,7 +219,7 @@ int kern_recvit(struct thread *td, int s, struct msghdr *mp, int kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, enum uio_seg pathseg); int kern_rmdirat(struct thread *td, int fd, char *path, - enum uio_seg pathseg); + enum uio_seg pathseg, int flag); int kern_sched_getparam(struct thread *td, struct thread *targettd, struct sched_param *param); int kern_sched_getscheduler(struct thread *td, struct thread *targettd, @@ -286,7 +286,7 @@ int kern_thr_suspend(struct thread *td, struct timespec *tsp); int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length); int kern_unlinkat(struct thread *td, int fd, char *path, - enum uio_seg pathseg, ino_t oldinum); + enum uio_seg pathseg, int flag, ino_t oldinum); int kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); int kern_utimensat(struct thread *td, int fd, char *path, diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 636e8e67257e..e82605af09e4 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -3399,7 +3399,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) vn_finished_write(mp); mp = NULL; error = kern_unlinkat(td, AT_FDCWD, (char *)(intptr_t)cmd.value, - UIO_USERSPACE, (ino_t)cmd.size); + UIO_USERSPACE, 0, (ino_t)cmd.size); break; case FFS_SET_INODE: |
