Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Mar 2021 19:24:56 GMT
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 7a1f6858dabf - releng/13.0 - jail(8): reset to root cpuset before attaching to run commands
Message-ID:  <202103111924.12BJOubr097755@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch releng/13.0 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=7a1f6858dabfdb24d9f58a52fd5e6e1fe0ceead1

commit 7a1f6858dabfdb24d9f58a52fd5e6e1fe0ceead1
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2021-03-04 19:28:53 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2021-03-11 19:24:28 +0000

    jail(8): reset to root cpuset before attaching to run commands
    
    Recent changes have made it such that attaching to a jail will augment
    the attaching process' cpu mask with the jail's cpuset. While this is
    convenient for allowing the administrator to cpuset arbitrary programs
    that will attach to a jail, this is decidedly not convenient for
    executing long-running daemons during jail creation.
    
    This change inserts a reset of the process cpuset to the root cpuset
    between the fork and attach to execute a command. This allows commands
    executed to have the widest mask possible, and the administrator can
    cpuset(1) it back down inside the jail as needed.
    
    With this applied, one should be able to change a jail's cpuset at
    exec.poststart in addition to exec.created.  The former was made
    difficult if jail(8) itself was running with a constrained set, as then
    some processes may have been spawned inside the jail with a non-root
    set.  The latter is the preferred option so that processes starting in
    the jail are constrained appropriately up front.
    
    Note that all system commands are still run with the process' initial
    cpuset applied.
    
    PR:             253724
    Approved by:    re (gjb)
    
    (cherry picked from commit 466df976babed65f8a8de9e36d7f016a444609af)
    (cherry picked from commit bdd61b6914f1f961b5f414b2d5cc623a5a829b89)
---
 usr.sbin/jail/command.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c
index a5c1839849fd..c1d418d6cc69 100644
--- a/usr.sbin/jail/command.c
+++ b/usr.sbin/jail/command.c
@@ -30,6 +30,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <sys/cpuset.h>
 #include <sys/event.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
@@ -84,6 +85,20 @@ static struct cfstring dummystring = { .len = 1 };
 static struct phhead phash[PHASH_SIZE];
 static int kq;
 
+static cpusetid_t
+root_cpuset_id(void)
+{
+	static cpusetid_t setid = CPUSET_INVALID;
+	static int error;
+
+	/* Only try to get the cpuset once. */
+	if (error == 0 && setid == CPUSET_INVALID)
+		error = cpuset_getid(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, &setid);
+	if (error != 0)
+		return (CPUSET_INVALID);
+	return (setid);
+}
+
 /*
  * Run the next command associated with a jail.
  */
@@ -283,6 +298,7 @@ run_command(struct cfjail *j)
 	enum intparam comparam;
 	size_t comlen;
 	pid_t pid;
+	cpusetid_t setid;
 	int argc, bg, clean, consfd, down, fib, i, injail, sjuser, timeout;
 #if defined(INET) || defined(INET6)
 	char *addr, *extrap, *p, *val;
@@ -632,6 +648,10 @@ run_command(struct cfjail *j)
 
 	injail = comparam == IP_EXEC_START || comparam == IP_COMMAND ||
 	    comparam == IP_EXEC_STOP;
+	if (injail)
+		setid = root_cpuset_id();
+	else
+		setid = CPUSET_INVALID;
 	clean = bool_param(j->intparams[IP_EXEC_CLEAN]);
 	username = string_param(j->intparams[injail
 	    ? IP_EXEC_JAIL_USER : IP_EXEC_SYSTEM_USER]);
@@ -700,6 +720,19 @@ run_command(struct cfjail *j)
 			jail_warnx(j, "setfib: %s", strerror(errno));
 			exit(1);
 		}
+
+		/*
+		 * We wouldn't have specialized our affinity, so just setid to
+		 * root.  We do this prior to attaching to avoid the kernel
+		 * having to create a transient cpuset that we'll promptly
+		 * free up with a reset to the jail's cpuset.
+		 *
+		 * This is just a best-effort to use as wide of mask as
+		 * possible.
+		 */
+		if (setid != CPUSET_INVALID)
+			(void)cpuset_setid(CPU_WHICH_PID, -1, setid);
+
 		if (jail_attach(j->jid) < 0) {
 			jail_warnx(j, "jail_attach: %s", strerror(errno));
 			exit(1);



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