Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Dec 2020 03:30:06 +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: r368779 - head/sys/kern
Message-ID:  <202012190330.0BJ3U6b1068131@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sat Dec 19 03:30:06 2020
New Revision: 368779
URL: https://svnweb.freebsd.org/changeset/base/368779

Log:
  kern: cpuset: allow jails to modify child jails' roots
  
  This partially lifts a restriction imposed by r191639 ("Prevent a superuser
  inside a jail from modifying the dedicated root cpuset of that jail") that's
  perhaps beneficial after r192895 ("Add hierarchical jails."). Jails still
  cannot modify their own cpuset, but they can modify child jails' roots to
  further restrict them or widen them back to the modifying jails' own mask.
  
  As a side effect of this, the system root may once again widen the mask of
  jails as long as they're still using a subset of the parent jails' mask.
  This was previously prevented by the fact that cpuset_getroot of a root set
  will return that root, rather than the root's parent -- cpuset_modify uses
  cpuset_getroot since it was introduced in r327895, previously it was just
  validating against set->cs_parent which allowed the system root to widen
  jail masks.
  
  Reviewed by:	jamie
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D27352

Modified:
  head/sys/kern/kern_cpuset.c

Modified: head/sys/kern/kern_cpuset.c
==============================================================================
--- head/sys/kern/kern_cpuset.c	Sat Dec 19 03:07:38 2020	(r368778)
+++ head/sys/kern/kern_cpuset.c	Sat Dec 19 03:30:06 2020	(r368779)
@@ -688,19 +688,34 @@ cpuset_modify(struct cpuset *set, cpuset_t *mask)
 	if (error)
 		return (error);
 	/*
-	 * In case we are called from within the jail
+	 * In case we are called from within the jail,
 	 * we do not allow modifying the dedicated root
 	 * cpuset of the jail but may still allow to
-	 * change child sets.
+	 * change child sets, including subordinate jails'
+	 * roots.
 	 */
-	if (jailed(curthread->td_ucred) &&
-	    set->cs_flags & CPU_SET_ROOT)
+	if ((set->cs_flags & CPU_SET_ROOT) != 0 &&
+	    jailed(curthread->td_ucred) &&
+	    set == curthread->td_ucred->cr_prison->pr_cpuset)
 		return (EPERM);
 	/*
 	 * Verify that we have access to this set of
 	 * cpus.
 	 */
-	root = cpuset_getroot(set);
+	if ((set->cs_flags & (CPU_SET_ROOT | CPU_SET_RDONLY)) == CPU_SET_ROOT) {
+		KASSERT(set->cs_parent != NULL,
+		    ("jail.cpuset=%d is not a proper child of parent jail's root.",
+		    set->cs_id));
+
+		/*
+		 * cpuset_getroot() cannot work here due to how top-level jail
+		 * roots are constructed.  Top-level jails are parented to
+		 * thread0's cpuset (i.e. cpuset 1) rather than the system root.
+		 */
+		root = set->cs_parent;
+	} else {
+		root = cpuset_getroot(set);
+	}
 	mtx_lock_spin(&cpuset_lock);
 	if (root && !CPU_SUBSET(&root->cs_mask, mask)) {
 		error = EINVAL;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012190330.0BJ3U6b1068131>