Skip to content

Commit

Permalink
sysctl: Teach sysctl to attach and run itself in a jail
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gmshake committed Jan 30, 2025
1 parent 6193855 commit 08aa712
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
5 changes: 5 additions & 0 deletions sbin/sysctl/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,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

Expand Down
12 changes: 11 additions & 1 deletion sbin/sysctl/sysctl.8
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,22 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd January 23, 2025
.Dd January 31, 2025
.Dt SYSCTL 8
.Os
.Sh NAME
.Nm sysctl
.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
Expand Down Expand Up @@ -103,6 +105,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
Expand All @@ -113,6 +119,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
Expand Down
48 changes: 44 additions & 4 deletions sbin/sysctl/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,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>
Expand All @@ -51,6 +54,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>
Expand All @@ -59,12 +65,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);
Expand Down Expand Up @@ -121,8 +131,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);
}

Expand All @@ -137,7 +147,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 */
Expand Down Expand Up @@ -173,6 +183,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;
Expand Down Expand Up @@ -222,15 +240,20 @@ 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();

if (conffile != NULL) {
file = fopen(conffile, "r");
if (file == NULL)
err(EX_NOINPUT, "%s", conffile);
}
attach_jail();
if (file != NULL) {
warncount += parsefile(file);
fclose(file);
}
Expand All @@ -241,6 +264,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
Expand Down

0 comments on commit 08aa712

Please sign in to comment.