diff options
Diffstat (limited to 'sys/kern')
| -rw-r--r-- | sys/kern/kern_descrip.c | 57 | ||||
| -rw-r--r-- | sys/kern/sys_procdesc.c | 5 | ||||
| -rw-r--r-- | sys/kern/uipc_mqueue.c | 8 | ||||
| -rw-r--r-- | sys/kern/uipc_sem.c | 6 | ||||
| -rw-r--r-- | sys/kern/uipc_syscalls.c | 4 | ||||
| -rw-r--r-- | sys/kern/vfs_cache.c | 19 | ||||
| -rw-r--r-- | sys/kern/vfs_lookup.c | 46 | ||||
| -rw-r--r-- | sys/kern/vfs_syscalls.c | 5 | ||||
| -rw-r--r-- | sys/kern/vfs_vnops.c | 22 |
9 files changed, 97 insertions, 75 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index f51a1092114d..f073fc64e0bc 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -114,7 +114,8 @@ static void fdgrowtable_exp(struct filedesc *fdp, int nfd); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); static int fget_unlocked_seq(struct filedesc *fdp, int fd, - cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp); + const cap_rights_t *needrightsp, struct file **fpp, + seqc_t *seqp); static int getmaxfd(struct thread *td); static u_long *filecaps_copy_prep(const struct filecaps *src); static void filecaps_copy_finish(const struct filecaps *src, @@ -2978,7 +2979,7 @@ finit_vnode(struct file *fp, u_int flag, void *data, struct fileops *ops) } int -fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +fget_cap_locked(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, struct file **fpp, struct filecaps *havecapsp) { struct filedescent *fde; @@ -3010,7 +3011,7 @@ out: } int -fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, struct file **fpp, struct filecaps *havecapsp) { struct filedesc *fdp = td->td_proc->p_fd; @@ -3256,7 +3257,7 @@ out_free: } static int -fget_unlocked_seq(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +fget_unlocked_seq(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp) { #ifdef CAPABILITIES @@ -3339,7 +3340,7 @@ fget_unlocked_seq(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, * racing with itself. */ int -fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +fget_unlocked(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, struct file **fpp) { #ifdef CAPABILITIES @@ -3406,7 +3407,7 @@ out_fallback: */ #ifdef CAPABILITIES int -fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, struct file **fpp) { const struct filedescent *fde; @@ -3436,7 +3437,7 @@ fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, } #else int -fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, struct file **fpp) { struct file *fp; @@ -3472,7 +3473,7 @@ fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, */ static __inline int _fget(struct thread *td, int fd, struct file **fpp, int flags, - cap_rights_t *needrightsp) + const cap_rights_t *needrightsp) { struct filedesc *fdp; struct file *fp; @@ -3520,15 +3521,15 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, } int -fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) +fget(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp) { return (_fget(td, fd, fpp, 0, rightsp)); } int -fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, - struct file **fpp) +fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, + vm_prot_t *maxprotp, struct file **fpp) { int error; #ifndef CAPABILITIES @@ -3571,22 +3572,24 @@ fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, } int -fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) +fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp) { return (_fget(td, fd, fpp, FREAD, rightsp)); } int -fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) +fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp) { return (_fget(td, fd, fpp, FWRITE, rightsp)); } int -fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl, - struct file **fpp) +fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, + int needfcntl, struct file **fpp) { struct filedesc *fdp = td->td_proc->p_fd; #ifndef CAPABILITIES @@ -3624,7 +3627,7 @@ fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl, * XXX: what about the unused flags ? */ static __inline int -_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, +_fgetvp(struct thread *td, int fd, int flags, const cap_rights_t *needrightsp, struct vnode **vpp) { struct file *fp; @@ -3646,14 +3649,15 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, } int -fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) +fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp) { return (_fgetvp(td, fd, 0, rightsp, vpp)); } int -fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, +fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, struct filecaps *havecaps, struct vnode **vpp) { struct filecaps caps; @@ -3685,14 +3689,16 @@ out: } int -fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) +fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp) { return (_fgetvp(td, fd, FREAD, rightsp, vpp)); } int -fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) +fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp) { return (_fgetvp(td, fd, FEXEC, rightsp, vpp)); @@ -3700,7 +3706,7 @@ fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp #ifdef notyet int -fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, +fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, struct vnode **vpp) { @@ -3718,13 +3724,10 @@ int __noinline _fdrop(struct file *fp, struct thread *td) { int error; -#ifdef INVARIANTS - int count; - count = refcount_load(&fp->f_count); - if (count != 0) - panic("fdrop: fp %p count %d", fp, count); -#endif + KASSERT(refcount_load(&fp->f_count) == 0, + ("fdrop: fp %p count %d", fp, refcount_load(&fp->f_count))); + error = fo_close(fp, td); atomic_subtract_int(&openfiles, 1); crfree(fp->f_cred); diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index aab7b1616594..4665dc2c0421 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -121,7 +121,7 @@ static struct fileops procdesc_ops = { * died. */ int -procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp, +procdesc_find(struct thread *td, int fd, const cap_rights_t *rightsp, struct proc **p) { struct procdesc *pd; @@ -168,7 +168,8 @@ procdesc_pid(struct file *fp_procdesc) * Retrieve the PID associated with a process descriptor. */ int -kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp) +kern_pdgetpid(struct thread *td, int fd, const cap_rights_t *rightsp, + pid_t *pidp) { struct file *fp; int error; diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index be3e3fefa749..926a9d311b67 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -846,7 +846,8 @@ mqfs_lookupx(struct vop_cachedlookup_args *ap) struct mqfs_node *pd; struct mqfs_node *pn; struct mqfs_info *mqfs; - int nameiop, flags, error, namelen; + uint64_t flags; + int nameiop, error, namelen; char *pname; struct thread *td; @@ -2159,13 +2160,14 @@ sys_kmq_unlink(struct thread *td, struct kmq_unlink_args *uap) return (error); } -typedef int (*_fgetf)(struct thread *, int, cap_rights_t *, struct file **); +typedef int (*_fgetf)(struct thread *, int, const cap_rights_t *, + struct file **); /* * Get message queue by giving file slot */ static int -_getmq(struct thread *td, int fd, cap_rights_t *rightsp, _fgetf func, +_getmq(struct thread *td, int fd, const cap_rights_t *rightsp, _fgetf func, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { struct mqfs_node *pn; diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 7cb25749ad9c..9871c0528338 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -123,8 +123,8 @@ static int ksem_create(struct thread *td, const char *path, semid_t *semidp, mode_t mode, unsigned int value, int flags, int compat32); static void ksem_drop(struct ksem *ks); -static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, - struct file **fpp); +static int ksem_get(struct thread *td, semid_t id, + const cap_rights_t *rightsp, struct file **fpp); static struct ksem *ksem_hold(struct ksem *ks); static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks); static struct ksem *ksem_lookup(char *path, Fnv32_t fnv); @@ -588,7 +588,7 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, } static int -ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, +ksem_get(struct thread *td, semid_t id, const cap_rights_t *rightsp, struct file **fpp) { struct ksem *ks; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index ef3ebeb58176..336a0dd77d5c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -91,7 +91,7 @@ static int sockargs(struct mbuf **, char *, socklen_t, int); * A reference on the file entry is held upon returning. */ int -getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, +getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp, u_int *fflagp, struct filecaps *havecapsp) { struct file *fp; @@ -727,7 +727,7 @@ kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, struct uio auio; struct iovec *iov; struct socket *so; - cap_rights_t *rights; + const cap_rights_t *rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index aacbd43403e1..e6cf39c09f19 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -4006,7 +4006,7 @@ SYSCTL_PROC(_vfs_cache_param, OID_AUTO, fast_lookup, CTLTYPE_INT|CTLFLAG_RW|CTLF */ struct nameidata_outer { size_t ni_pathlen; - int cn_flags; + uint64_t cn_flags; }; struct nameidata_saved { @@ -4292,7 +4292,7 @@ cache_fpl_terminated(struct cache_fpl *fpl) (NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \ FAILIFEXISTS | FOLLOW | EMPTYPATH | LOCKSHARED | SAVENAME | SAVESTART | \ WILLBEDIR | ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK | \ - WANTIOCTLCAPS) + WANTIOCTLCAPS | NAMEILOOKUP) #define CACHE_FPL_INTERNAL_CN_FLAGS \ (ISDOTDOT | MAKEENTRY | ISLASTCN) @@ -5126,30 +5126,19 @@ static int __noinline cache_fplookup_dotdot(struct cache_fpl *fpl) { struct nameidata *ndp; - struct componentname *cnp; struct namecache *ncp; struct vnode *dvp; - struct prison *pr; u_char nc_flag; ndp = fpl->ndp; - cnp = fpl->cnp; dvp = fpl->dvp; - MPASS(cache_fpl_isdotdot(cnp)); + MPASS(cache_fpl_isdotdot(fpl->cnp)); /* * XXX this is racy the same way regular lookup is */ - for (pr = cnp->cn_cred->cr_prison; pr != NULL; - pr = pr->pr_parent) - if (dvp == pr->pr_root) - break; - - if (dvp == ndp->ni_rootdir || - dvp == ndp->ni_topdir || - dvp == rootvnode || - pr != NULL) { + if (lookup_isroot(ndp, dvp)) { fpl->tvp = dvp; fpl->tvp_seqc = vn_seqc_read_any(dvp); if (seqc_in_modify(fpl->tvp_seqc)) { diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index cb013eb7ff83..dc8b7b92ccd4 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -530,12 +530,12 @@ namei(struct nameidata *ndp) cnp->cn_origflags = cnp->cn_flags; #endif ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; - KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n", + KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x", __func__, ndp->ni_resflags)); KASSERT(cnp->cn_cred && td->td_proc, ("namei: bad cred/proc")); KASSERT((cnp->cn_flags & NAMEI_INTERNAL_FLAGS) == 0, - ("namei: unexpected flags: %" PRIx64 "\n", - cnp->cn_flags & NAMEI_INTERNAL_FLAGS)); + ("namei: unexpected flags: %#jx", + (uintmax_t)(cnp->cn_flags & NAMEI_INTERNAL_FLAGS))); if (cnp->cn_flags & NOCACHE) KASSERT(cnp->cn_nameiop != LOOKUP, ("%s: NOCACHE passed with LOOKUP", __func__)); @@ -761,6 +761,31 @@ needs_exclusive_leaf(struct mount *mp, int flags) _Static_assert(MAXNAMLEN == NAME_MAX, "MAXNAMLEN and NAME_MAX have different values"); + +struct nameidata * +lookup_nameidata(struct componentname *cnp) +{ + if ((cnp->cn_flags & NAMEILOOKUP) == 0) + return (NULL); + return (__containerof(cnp, struct nameidata, ni_cnd)); +} + +/* + * Would a dotdot lookup relative to dvp cause this lookup to cross a jail or + * chroot boundary? + */ +bool +lookup_isroot(struct nameidata *ndp, struct vnode *dvp) +{ + for (struct prison *pr = ndp->ni_cnd.cn_cred->cr_prison; pr != NULL; + pr = pr->pr_parent) { + if (dvp == pr->pr_root) + return (true); + } + return (dvp == ndp->ni_rootdir || dvp == ndp->ni_topdir || + dvp == rootvnode); +} + /* * Search a pathname. * This is a very central and rather complicated routine. @@ -808,7 +833,6 @@ lookup(struct nameidata *ndp) struct vnode *dp = NULL; /* the directory we are searching */ struct vnode *tdp; /* saved dp */ struct mount *mp; /* mount table entry */ - struct prison *pr; size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */ int docache; /* == 0 do not cache last component */ int wantparent; /* 1 => wantparent or lockparent flag */ @@ -1008,15 +1032,11 @@ dirloop: goto bad; } for (;;) { - for (pr = cnp->cn_cred->cr_prison; pr != NULL; - pr = pr->pr_parent) - if (dp == pr->pr_root) - break; - bool isroot = dp == ndp->ni_rootdir || - dp == ndp->ni_topdir || dp == rootvnode || - pr != NULL; - if (isroot && (ndp->ni_lcf & - NI_LCF_STRICTRELATIVE) != 0) { + bool isroot; + + isroot = lookup_isroot(ndp, dp); + if (__predict_false(isroot && (ndp->ni_lcf & + NI_LCF_STRICTRELATIVE) != 0)) { error = ENOTCAPABLE; goto capdotdot; } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 7dcdaa66adb8..51f26b843c45 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -4315,7 +4315,7 @@ out: * semantics. */ int -getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, +getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp) { struct file *fp; @@ -4353,7 +4353,8 @@ getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, * A reference on the file entry is held upon returning. */ int -getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) +getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp) { int error; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 6591b543ddea..e685d581733b 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -195,21 +195,26 @@ vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp) } static uint64_t -open2nameif(int fmode, u_int vn_open_flags) +open2nameif(int fmode, u_int vn_open_flags, uint64_t cn_flags) { uint64_t res; - res = ISOPEN | LOCKLEAF; + res = ISOPEN | LOCKLEAF | cn_flags; if ((fmode & O_RESOLVE_BENEATH) != 0) res |= RBENEATH; if ((fmode & O_EMPTY_PATH) != 0) res |= EMPTYPATH; + if ((fmode & O_NOFOLLOW) != 0) + res &= ~FOLLOW; if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) res |= AUDITVNODE1; + else + res &= ~AUDITVNODE1; if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0) res |= NOCAPCHECK; if ((vn_open_flags & VN_OPEN_WANTIOCTLCAPS) != 0) res |= WANTIOCTLCAPS; + return (res); } @@ -242,7 +247,9 @@ restart: 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); + ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, + ndp->ni_cnd.cn_flags); + /* * Set NOCACHE to avoid flushing the cache when * rolling in many files at once. @@ -251,8 +258,8 @@ restart: * exist despite NOCACHE. */ ndp->ni_cnd.cn_flags |= LOCKPARENT | NOCACHE | NC_KEEPPOSENTRY; - if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) - ndp->ni_cnd.cn_flags |= FOLLOW; + if ((fmode & O_EXCL) != 0) + ndp->ni_cnd.cn_flags &= ~FOLLOW; if ((vn_open_flags & VN_OPEN_INVFS) == 0) bwillwrite(); if ((error = namei(ndp)) != 0) @@ -320,9 +327,8 @@ restart: } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; - ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); - ndp->ni_cnd.cn_flags |= (fmode & O_NOFOLLOW) != 0 ? NOFOLLOW : - FOLLOW; + ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, + ndp->ni_cnd.cn_flags); if ((fmode & FWRITE) == 0) ndp->ni_cnd.cn_flags |= LOCKSHARED; if ((error = namei(ndp)) != 0) |
