Date: Wed, 25 Sep 2019 17:35:03 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r352697 - in head/sys: compat/cloudabi kern sys Message-ID: <201909251735.x8PHZ34q064707@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Wed Sep 25 17:35:03 2019 New Revision: 352697 URL: https://svnweb.freebsd.org/changeset/base/352697 Log: [2/3] Add an initial seal argument to kern_shm_open() Now that flags may be set on posixshm, add an argument to kern_shm_open() for the initial seals. To maintain past behavior where callers of shm_open(2) are guaranteed to not have any seals applied to the fd they're given, apply F_SEAL_SEAL for existing callers of kern_shm_open. A special flag could be opened later for shm_open(2) to indicate that sealing should be allowed. We currently restrict initial seals to F_SEAL_SEAL. We cannot error out if F_SEAL_SEAL is re-applied, as this would easily break shm_open() twice to a shmfd that already existed. A note's been added about the assumptions we've made here as a hint towards anyone wanting to allow other seals to be applied at creation. Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D21392 Modified: head/sys/compat/cloudabi/cloudabi_fd.c head/sys/kern/uipc_shm.c head/sys/sys/syscallsubr.h Modified: head/sys/compat/cloudabi/cloudabi_fd.c ============================================================================== --- head/sys/compat/cloudabi/cloudabi_fd.c Wed Sep 25 17:33:12 2019 (r352696) +++ head/sys/compat/cloudabi/cloudabi_fd.c Wed Sep 25 17:35:03 2019 (r352697) @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/capsicum.h> +#include <sys/fcntl.h> #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/mman.h> @@ -95,7 +96,7 @@ cloudabi_sys_fd_create1(struct thread *td, cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_FTRUNCATE, CAP_MMAP_RWX); return (kern_shm_open(td, SHM_ANON, O_RDWR | O_CLOEXEC, 0, - &fcaps)); + &fcaps, F_SEAL_SEAL)); default: return (EINVAL); } Modified: head/sys/kern/uipc_shm.c ============================================================================== --- head/sys/kern/uipc_shm.c Wed Sep 25 17:33:12 2019 (r352696) +++ head/sys/kern/uipc_shm.c Wed Sep 25 17:35:03 2019 (r352697) @@ -701,13 +701,14 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucre int kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, - struct filecaps *fcaps) + struct filecaps *fcaps, int initial_seals) { struct filedesc *fdp; struct shmfd *shmfd; struct file *fp; char *path; const char *pr_path; + void *rl_cookie; size_t pr_pathlen; Fnv32_t fnv; mode_t cmode; @@ -730,6 +731,17 @@ kern_shm_open(struct thread *td, const char *userpath, if ((flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0) return (EINVAL); + /* + * Currently only F_SEAL_SEAL may be set when creating or opening shmfd. + * If the decision is made later to allow additional seals, care must be + * taken below to ensure that the seals are properly set if the shmfd + * already existed -- this currently assumes that only F_SEAL_SEAL can + * be set and doesn't take further precautions to ensure the validity of + * the seals being added with respect to current mappings. + */ + if ((initial_seals & ~F_SEAL_SEAL) != 0) + return (EINVAL); + fdp = td->td_proc->p_fd; cmode = (mode & ~fdp->fd_cmask) & ACCESSPERMS; @@ -753,6 +765,7 @@ kern_shm_open(struct thread *td, const char *userpath, return (EINVAL); } shmfd = shm_alloc(td->td_ucred, cmode); + shmfd->shm_seals = initial_seals; } else { path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); pr_path = td->td_ucred->cr_prison->pr_path; @@ -789,6 +802,7 @@ kern_shm_open(struct thread *td, const char *userpath, if (error == 0) { #endif shmfd = shm_alloc(td->td_ucred, cmode); + shmfd->shm_seals = initial_seals; shm_insert(path, fnv, shmfd); #ifdef MAC } @@ -798,12 +812,39 @@ kern_shm_open(struct thread *td, const char *userpath, error = ENOENT; } } else { + rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, + &shmfd->shm_mtx); + /* + * kern_shm_open() likely shouldn't ever error out on + * trying to set a seal that already exists, unlike + * F_ADD_SEALS. This would break terribly as + * shm_open(2) actually sets F_SEAL_SEAL to maintain + * historical behavior where the underlying file could + * not be sealed. + */ + initial_seals &= ~shmfd->shm_seals; + + /* * Object already exists, obtain a new * reference if requested and permitted. */ free(path, M_SHMFD); - if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + + /* + * initial_seals can't set additional seals if we've + * already been set F_SEAL_SEAL. If F_SEAL_SEAL is set, + * then we've already removed that one from + * initial_seals. This is currently redundant as we + * only allow setting F_SEAL_SEAL at creation time, but + * it's cheap to check and decreases the effort required + * to allow additional seals. + */ + if ((shmfd->shm_seals & F_SEAL_SEAL) != 0 && + initial_seals != 0) + error = EPERM; + else if ((flags & (O_CREAT | O_EXCL)) == + (O_CREAT | O_EXCL)) error = EEXIST; else { #ifdef MAC @@ -823,15 +864,27 @@ kern_shm_open(struct thread *td, const char *userpath, if (error == 0 && (flags & (O_ACCMODE | O_TRUNC)) == (O_RDWR | O_TRUNC)) { + VM_OBJECT_WLOCK(shmfd->shm_object); #ifdef MAC error = mac_posixshm_check_truncate( td->td_ucred, fp->f_cred, shmfd); if (error == 0) #endif - shm_dotruncate(shmfd, 0); + error = shm_dotruncate_locked(shmfd, 0, + rl_cookie); + VM_OBJECT_WUNLOCK(shmfd->shm_object); } - if (error == 0) + if (error == 0) { + /* + * Currently we only allow F_SEAL_SEAL to be + * set initially. As noted above, this would + * need to be reworked should that change. + */ + shmfd->shm_seals |= initial_seals; shm_hold(shmfd); + } + rangelock_unlock(&shmfd->shm_rl, rl_cookie, + &shmfd->shm_mtx); } sx_xunlock(&shm_dict_lock); @@ -856,7 +909,7 @@ sys_shm_open(struct thread *td, struct shm_open_args * { return (kern_shm_open(td, uap->path, uap->flags | O_CLOEXEC, uap->mode, - NULL)); + NULL, F_SEAL_SEAL)); } int Modified: head/sys/sys/syscallsubr.h ============================================================================== --- head/sys/sys/syscallsubr.h Wed Sep 25 17:33:12 2019 (r352696) +++ head/sys/sys/syscallsubr.h Wed Sep 25 17:35:03 2019 (r352697) @@ -250,7 +250,7 @@ int kern_setsockopt(struct thread *td, int s, int leve int kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp); int kern_shm_open(struct thread *td, const char *userpath, int flags, - mode_t mode, struct filecaps *fcaps); + mode_t mode, struct filecaps *fcaps, int initial_seals); int kern_shmat(struct thread *td, int shmid, const void *shmaddr, int shmflg); int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909251735.x8PHZ34q064707>