Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Feb 2025 15:38:54 GMT
From:      Zhenlei Huang <zlei@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 8d5d7e2ba3a6 - stable/14 - sysctl: Teach sysctl to attach and run itself in a jail
Message-ID:  <202502061538.516FcsuL002467@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=8d5d7e2ba3a685a9ebe7aa578c6b76adf8fe4c2e

commit 8d5d7e2ba3a685a9ebe7aa578c6b76adf8fe4c2e
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2025-01-30 18:20:41 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2025-02-06 15:38:04 +0000

    sysctl: Teach sysctl to attach and run itself in a jail
    
    This allows the parent jail to retrieve or set kernel state when child
    does not have sysctl(8) installed (e.g. light weighted OCI containers
    or slim jails).
    
    This is especially useful when manipulating jail prison or vnet sysctls.
    For example, `sysctl -j foo -Ja` or `sysctl -j foo net.fibs=2`.
    
    Reviewed by:    dfr (previous version), markj
    MFC after:      1 week
    Relnotes:       yes
    Differential Revision:  https://reviews.freebsd.org/D48618
    
    (cherry picked from commit 08aa7128dea4d14811ae4a0225d7c678869cfe62)
---
 sbin/sysctl/Makefile |  5 +++++
 sbin/sysctl/sysctl.8 | 12 +++++++++++-
 sbin/sysctl/sysctl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/sbin/sysctl/Makefile b/sbin/sysctl/Makefile
index e5455568223c..b6a595186676 100644
--- a/sbin/sysctl/Makefile
+++ b/sbin/sysctl/Makefile
@@ -8,6 +8,11 @@ PROG=	sysctl
 WARNS?=	3
 MAN=	sysctl.8
 
+.if ${MK_JAIL} != "no" && !defined(RESCUE)
+CFLAGS+=	-DJAIL
+LIBADD+=	jail
+.endif
+
 HAS_TESTS=
 SUBDIR.${MK_TESTS}+=	tests
 
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8
index aee66173fdea..398af7c36646 100644
--- a/sbin/sysctl/sysctl.8
+++ b/sbin/sysctl/sysctl.8
@@ -30,7 +30,7 @@
 .\"
 .\"	From: @(#)sysctl.8	8.1 (Berkeley) 6/6/93
 .\"
-.Dd January 23, 2025
+.Dd January 31, 2025
 .Dt SYSCTL 8
 .Os
 .Sh NAME
@@ -38,12 +38,14 @@
 .Nd get or set kernel state
 .Sh SYNOPSIS
 .Nm
+.Op Fl j Ar jail
 .Op Fl bdeFhiJlNnoqTtVWx
 .Op Fl B Ar bufsize
 .Op Fl f Ar filename
 .Ar name Ns Op = Ns Ar value Ns Op , Ns Ar value
 .Ar ...
 .Nm
+.Op Fl j Ar jail
 .Op Fl bdeFhJlNnoqTtVWx
 .Op Fl B Ar bufsize
 .Fl a
@@ -105,6 +107,10 @@ Specify a file which contains a pair of name and value in each line.
 .Nm
 reads and processes the specified file first and then processes the name
 and value pairs in the command line argument.
+Note that when the
+.Fl j Ar jail
+option is specified, the file will be opened before attaching to the jail and
+then be processed inside the jail.
 .It Fl h
 Format output for human, rather than machine, readability.
 .It Fl i
@@ -115,6 +121,10 @@ for collecting data from a variety of machines (not all of which
 are necessarily running exactly the same software) easier.
 .It Fl J
 Display only jail prision sysctl variables (CTLFLAG_PRISON).
+.It Fl j Ar jail
+Perform the actions inside the
+.Ar jail
+(by jail id or jail name).
 .It Fl l
 Show the length of variables along with their values.
 This option cannot be combined with the
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 883923b4a50f..6f5450a0a9f9 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -34,6 +34,9 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
+#ifdef JAIL
+#include <sys/jail.h>
+#endif
 #include <sys/sysctl.h>
 #include <sys/vmmeter.h>
 #include <dev/evdev/input.h>
@@ -52,6 +55,9 @@
 #include <err.h>
 #include <errno.h>
 #include <inttypes.h>
+#ifdef JAIL
+#include <jail.h>
+#endif
 #include <locale.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -60,12 +66,16 @@
 #include <sysexits.h>
 #include <unistd.h>
 
+#ifdef JAIL
+static const char *jailname;
+#endif
 static const char *conffile;
 
 static int	aflag, bflag, Bflag, dflag, eflag, hflag, iflag;
 static int	Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag;
 static bool	Fflag, Jflag, lflag, Vflag;
 
+static void	attach_jail(void);
 static int	oidfmt(int *, int, char *, u_int *);
 static int	parsefile(FILE *);
 static int	parse(const char *, int);
@@ -122,8 +132,8 @@ usage(void)
 {
 
 	(void)fprintf(stderr, "%s\n%s\n",
-	    "usage: sysctl [-bdeFhiJlNnoqTtVWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
-	    "       sysctl [-bdeFhJlNnoqTtVWx] [ -B <bufsize> ] -a");
+	    "usage: sysctl [-j jail] [-bdeFhiJlNnoqTtVWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
+	    "       sysctl [-j jail] [-bdeFhJlNnoqTtVWx] [ -B <bufsize> ] -a");
 	exit(1);
 }
 
@@ -138,7 +148,7 @@ main(int argc, char **argv)
 	setbuf(stdout,0);
 	setbuf(stderr,0);
 
-	while ((ch = getopt(argc, argv, "AaB:bdeFf:hiJlNnoqTtVWwXx")) != -1) {
+	while ((ch = getopt(argc, argv, "AaB:bdeFf:hiJj:lNnoqTtVWwXx")) != -1) {
 		switch (ch) {
 		case 'A':
 			/* compatibility */
@@ -174,6 +184,14 @@ main(int argc, char **argv)
 		case 'J':
 			Jflag = true;
 			break;
+		case 'j':
+#ifdef JAIL
+			if ((jailname = optarg) == NULL)
+				usage();
+#else
+			errx(1, "not built with jail support");
+#endif
+			break;
 		case 'l':
 			lflag = true;
 			break;
@@ -223,8 +241,10 @@ main(int argc, char **argv)
 	/* TODO: few other combinations do not make sense but come back later */
 	if (Nflag && (lflag || nflag))
 		usage();
-	if (aflag && argc == 0)
+	if (aflag && argc == 0) {
+		attach_jail();
 		exit(sysctl_all(NULL, 0));
+	}
 	if (argc == 0 && conffile == NULL)
 		usage();
 
@@ -232,6 +252,9 @@ main(int argc, char **argv)
 		file = fopen(conffile, "r");
 		if (file == NULL)
 			err(EX_NOINPUT, "%s", conffile);
+	}
+	attach_jail();
+	if (file != NULL) {
 		warncount += parsefile(file);
 		fclose(file);
 	}
@@ -242,6 +265,23 @@ main(int argc, char **argv)
 	return (warncount);
 }
 
+static void
+attach_jail(void)
+{
+#ifdef JAIL
+	int jid;
+
+	if (jailname == NULL)
+		return;
+
+	jid = jail_getid(jailname);
+	if (jid == -1)
+		errx(1, "jail not found");
+	if (jail_attach(jid) != 0)
+		errx(1, "cannot attach to jail");
+#endif
+}
+
 /*
  * Parse a single numeric value, append it to 'newbuf', and update
  * 'newsize'.  Returns true if the value was parsed and false if the



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