aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenlei Huang <zlei@FreeBSD.org>2025-01-30 18:20:41 +0000
committerZhenlei Huang <zlei@FreeBSD.org>2025-02-06 16:08:53 +0000
commit5b0a5d8c1ea33ae7afb56d6c452df7e90ed54e9e (patch)
tree926328beefd495fc316ee97f40ecf3aae1211b7f
parent73a516c6527c84701921c329d4f08da44522ccc4 (diff)
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) (cherry picked from commit 8d5d7e2ba3a685a9ebe7aa578c6b76adf8fe4c2e)
-rw-r--r--sbin/sysctl/Makefile6
-rw-r--r--sbin/sysctl/sysctl.812
-rw-r--r--sbin/sysctl/sysctl.c48
3 files changed, 61 insertions, 5 deletions
diff --git a/sbin/sysctl/Makefile b/sbin/sysctl/Makefile
index b6783833ce41..807d3573d2c3 100644
--- a/sbin/sysctl/Makefile
+++ b/sbin/sysctl/Makefile
@@ -1,4 +1,5 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
+.include <src.opts.mk>
PACKAGE=runtime
CONFS= sysctl.conf
@@ -6,4 +7,9 @@ PROG= sysctl
WARNS?= 3
MAN= sysctl.8
+.if ${MK_JAIL} != "no" && !defined(RESCUE)
+CFLAGS+= -DJAIL
+LIBADD+= jail
+.endif
+
.include <bsd.prog.mk>
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8
index a7af56720361..34f22fda7b70 100644
--- a/sbin/sysctl/sysctl.8
+++ b/sbin/sysctl/sysctl.8
@@ -27,7 +27,7 @@
.\"
.\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93
.\"
-.Dd January 23, 2025
+.Dd January 31, 2025
.Dt SYSCTL 8
.Os
.Sh NAME
@@ -35,12 +35,14 @@
.Nd get or set kernel state
.Sh SYNOPSIS
.Nm
+.Op Fl j Ar jail
.Op Fl bdehiJNnoqTtVWx
.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 bdehJNnoqTtVWx
.Op Fl B Ar bufsize
.Fl a
@@ -99,6 +101,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
@@ -109,6 +115,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 N
Show only variable names, not their values.
This is particularly useful with shells that offer programmable
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 41dcf3db9184..d12e30a537a3 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 Jflag, 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 [-bdehiJNnoqTtVWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
- " sysctl [-bdehJNnoqTtVWx] [ -B <bufsize> ] -a");
+ "usage: sysctl [-j jail] [-bdehiJNnoqTtVWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
+ " sysctl [-j jail] [-bdehJNnoqTtVWx] [ -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, "AabB:def:hiJNnoqtTVwWxX")) != -1) {
+ while ((ch = getopt(argc, argv, "AabB:def:hiJj:NnoqtTVwWxX")) != -1) {
switch (ch) {
case 'A':
/* compatibility */
@@ -171,6 +181,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 'N':
Nflag = 1;
break;
@@ -215,8 +233,10 @@ main(int argc, char **argv)
if (Nflag && nflag)
usage();
- if (aflag && argc == 0)
+ if (aflag && argc == 0) {
+ attach_jail();
exit(sysctl_all(NULL, 0));
+ }
if (argc == 0 && conffile == NULL)
usage();
@@ -225,6 +245,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);
}
@@ -235,6 +258,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