aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/sys_capability.c
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2020-03-19 15:39:45 +0000
committerMark Johnston <markj@FreeBSD.org>2020-03-19 15:39:45 +0000
commit2d896b816b7a55f8093cd3959c231c2bd549cc94 (patch)
tree485e123d4bc1420d15fb1e1e7dea94c59fefe1b5 /sys/kern/sys_capability.c
parent42078d5adaa657518c962019b7f181378b08b486 (diff)
downloadsrc-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/kern/sys_capability.c')
-rw-r--r--sys/kern/sys_capability.c11
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);