Index: sys/kern/kern_cpuset.c =================================================================== --- sys/kern/kern_cpuset.c +++ sys/kern/kern_cpuset.c @@ -1259,14 +1259,22 @@ if (set != NULL && rebase && nroot != tdroot) { cpusetid_t base_id, root_id; - root_id = td->td_ucred->cr_prison->pr_cpuset->cs_id; - base_id = cpuset_getbase(td->td_cpuset)->cs_id; - - if (base_id != root_id) { - error = cpuset_setproc_newbase(td, set, nroot, &base, - &freelist, &domainlist); - if (error != 0) - goto unlock_out; + /* + * For management purposes, we'll allow the system root to + * entirely replace its cpuset with a jail's, as they may have + * completely disjoint sets. + */ + error = priv_check(td, PRIV_JAIL_CPUSET); + if (error != 0) { + root_id = td->td_ucred->cr_prison->pr_cpuset->cs_id; + base_id = cpuset_getbase(td->td_cpuset)->cs_id; + + if (base_id != root_id) { + error = cpuset_setproc_newbase(td, set, nroot, + &base, &freelist, &domainlist); + if (error != 0) + goto unlock_out; + } } } Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c +++ sys/kern/kern_jail.c @@ -3572,6 +3572,7 @@ case PRIV_JAIL_ATTACH: case PRIV_JAIL_SET: case PRIV_JAIL_REMOVE: + case PRIV_JAIL_CPUSET: /* * Jail implements its own inter-process limits, so allow Index: sys/sys/priv.h =================================================================== --- sys/sys/priv.h +++ sys/sys/priv.h @@ -136,6 +136,13 @@ #define PRIV_JAIL_SET 111 /* Set jail parameters. */ #define PRIV_JAIL_REMOVE 112 /* Remove a jail. */ +/* + * The default behavior is for jail attachment to augment the user's current + * cpuset, rather than replace it. The system root is allowed to replace its + * cpuset entirely with a jail's when attaching to it, for management purposes. + */ +#define PRIV_JAIL_CPUSET 113 + /* * Kernel environment privileges. */