diff options
author | Mark Johnston <markj@FreeBSD.org> | 2020-03-19 15:39:45 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2020-03-19 15:39:45 +0000 |
commit | 2d896b816b7a55f8093cd3959c231c2bd549cc94 (patch) | |
tree | 485e123d4bc1420d15fb1e1e7dea94c59fefe1b5 /sys | |
parent | 42078d5adaa657518c962019b7f181378b08b486 (diff) | |
download | src-2d896b816b7a55f8093cd3959c231c2bd549cc94.tar.gz src-2d896b816b7a55f8093cd3959c231c2bd549cc94.zip |
Enter a write sequence when updating rights.
The Capsicum system calls modify file descriptor table entries. To
ensure that readers observe a consistent snapshot of descriptor writes,
the system calls need to signal to unlocked readers that an update is
pending.
Note that ioctl rights are always checked with the descriptor table lock
held, so it is not strictly necessary to signal unlocked readers.
However, we probably want to enable lockless ioctl checks eventually, so
use seqc_write_begin() in kern_cap_ioctls_limit() too.
Reviewed by: kib
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D24119
Notes
Notes:
svn path=/head/; revision=359132
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/sys_capability.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index e1eb0faf29a3..6f97b74a0a53 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -234,6 +234,7 @@ kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights) { struct filedesc *fdp; struct filedescent *fdep; + u_long *ioctls; int error; fdp = td->td_proc->p_fd; @@ -243,18 +244,22 @@ kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights) FILEDESC_XUNLOCK(fdp); return (EBADF); } + ioctls = NULL; error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE); if (error == 0) { + seqc_write_begin(&fdep->fde_seqc); fdep->fde_rights = *rights; if (!cap_rights_is_set(rights, CAP_IOCTL)) { - free(fdep->fde_ioctls, M_FILECAPS); + ioctls = fdep->fde_ioctls; fdep->fde_ioctls = NULL; fdep->fde_nioctls = 0; } if (!cap_rights_is_set(rights, CAP_FCNTL)) fdep->fde_fcntls = 0; + seqc_write_end(&fdep->fde_seqc); } FILEDESC_XUNLOCK(fdp); + free(ioctls, M_FILECAPS); return (error); } @@ -439,8 +444,10 @@ kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds) goto out; ocmds = fdep->fde_ioctls; + seqc_write_begin(&fdep->fde_seqc); fdep->fde_ioctls = cmds; fdep->fde_nioctls = ncmds; + seqc_write_end(&fdep->fde_seqc); cmds = ocmds; error = 0; @@ -597,7 +604,9 @@ sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap) return (ENOTCAPABLE); } + seqc_write_begin(&fdep->fde_seqc); fdep->fde_fcntls = fcntlrights; + seqc_write_end(&fdep->fde_seqc); FILEDESC_XUNLOCK(fdp); return (0); |