Allow cpuset_{get,set}affinity in capabilities mode

bhyve was recently sandboxed with capsicum, and needs to be able to
control the CPU sets of its vcpu threads

Reviewed by:	emaste, oshogbo, rwatson
MFC after:	2 weeks
Sponsored by:	ScaleEngine Inc.
Differential Revision:	https://reviews.freebsd.org/D10170
This commit is contained in:
Allan Jude 2017-05-24 00:58:30 +00:00
parent 7c0cad38c7
commit f299c47b52
5 changed files with 43 additions and 8 deletions

View File

@ -25,7 +25,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd June 2, 2016 .Dd May 23, 2017
.Dt CPUSET_GETAFFINITY 2 .Dt CPUSET_GETAFFINITY 2
.Os .Os
.Sh NAME .Sh NAME
@ -148,8 +148,14 @@ was either preposterously large or smaller than the kernel set size.
.It Bq Er EPERM .It Bq Er EPERM
The calling process did not have the credentials required to complete the The calling process did not have the credentials required to complete the
operation. operation.
.It Bq Er ECAPMODE
The calling process attempted to act on a process other than itself, while
in capability mode.
See
.Xr capsicum 4 .
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr capsicum 4 ,
.Xr cpuset 1 , .Xr cpuset 1 ,
.Xr cpuset 2 , .Xr cpuset 2 ,
.Xr cpuset_getid 2 , .Xr cpuset_getid 2 ,

View File

@ -26,7 +26,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd July 5, 2016 .Dd May 18, 2017
.Dt CAPSICUM 4 .Dt CAPSICUM 4
.Os .Os
.Sh NAME .Sh NAME
@ -88,6 +88,16 @@ An extension to the POSIX shared memory API to support anonymous swap objects
associated with file descriptors; described in greater detail in associated with file descriptors; described in greater detail in
.Xr shm_open 2 . .Xr shm_open 2 .
.El .El
.Pp
In some cases,
.Nm
limits the valid values of some parameters to traditional APIs in order to
restrict access to global namespaces:
.Bl -tag -width indent
.It process IDs
Processes can only act upon their own process ID with syscalls such as
.Xr cpuset_setaffinity 2 .
.El
.Sh SEE ALSO .Sh SEE ALSO
.Xr cap_enter 2 , .Xr cap_enter 2 ,
.Xr cap_fcntls_limit 2 , .Xr cap_fcntls_limit 2 ,

View File

@ -76,9 +76,9 @@ close
closefrom closefrom
connectat connectat
#cpuset #cpuset
#freebsd32_cpuset_getaffinity freebsd32_cpuset_getaffinity
#freebsd32_cpuset_getid #freebsd32_cpuset_getid
#freebsd32_cpuset_setaffinity freebsd32_cpuset_setaffinity
#freebsd32_cpuset_setid #freebsd32_cpuset_setid
dup dup
dup2 dup2

View File

@ -133,13 +133,12 @@ closefrom
connectat connectat
## ##
## cpuset(2) and related calls require scoping by process, but should ## cpuset(2) and related calls are limited to caller's own process/thread.
## eventually be allowed, at least in the current process case.
## ##
#cpuset #cpuset
#cpuset_getaffinity cpuset_getaffinity
#cpuset_getid #cpuset_getid
#cpuset_setaffinity cpuset_setaffinity
#cpuset_setid #cpuset_setid
## ##

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sched.h> #include <sys/sched.h>
#include <sys/smp.h> #include <sys/smp.h>
#include <sys/syscallsubr.h> #include <sys/syscallsubr.h>
#include <sys/capsicum.h>
#include <sys/cpuset.h> #include <sys/cpuset.h>
#include <sys/sx.h> #include <sys/sx.h>
#include <sys/queue.h> #include <sys/queue.h>
@ -522,6 +523,7 @@ cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask)
int threads; int threads;
int nfree; int nfree;
int error; int error;
/* /*
* The algorithm requires two passes due to locking considerations. * The algorithm requires two passes due to locking considerations.
* *
@ -1096,6 +1098,15 @@ kern_cpuset_getaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY) if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY)
return (ERANGE); return (ERANGE);
/* In Capability mode, you can only get your own CPU set. */
if (IN_CAPABILITY_MODE(td)) {
if (level != CPU_LEVEL_WHICH)
return (ECAPMODE);
if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
return (ECAPMODE);
if (id != -1)
return (ECAPMODE);
}
size = cpusetsize; size = cpusetsize;
mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO); mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
error = cpuset_which(which, id, &p, &ttd, &set); error = cpuset_which(which, id, &p, &ttd, &set);
@ -1204,6 +1215,15 @@ kern_cpuset_setaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY) if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY)
return (ERANGE); return (ERANGE);
/* In Capability mode, you can only set your own CPU set. */
if (IN_CAPABILITY_MODE(td)) {
if (level != CPU_LEVEL_WHICH)
return (ECAPMODE);
if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
return (ECAPMODE);
if (id != -1)
return (ECAPMODE);
}
mask = malloc(cpusetsize, M_TEMP, M_WAITOK | M_ZERO); mask = malloc(cpusetsize, M_TEMP, M_WAITOK | M_ZERO);
error = copyin(maskp, mask, cpusetsize); error = copyin(maskp, mask, cpusetsize);
if (error) if (error)