⬢ DragonFlyBSD Kernel Audit
DF-5746 / trigger_benign.c
← back to finding ↓ download raw
/* DF-5746 control — FULL well-formed xlat16 table must keep working
 * (no-regression control for the fix; also demonstrates in-bounds
 * behaviour differs from the OOB leak).
 *
 * Table: index[0x2E,'A'..'P',0x6B] -> 18 data blocks of 0x80 uint32,
 * datalen = 4096 + 18*512 = 13312 == exactly what the layout requires.
 * Block for rank r maps every input char to code 0x4200 | r, so each
 * converted char prints as 'B' followed by the block rank byte.
 *
 * Build: cc -O0 -g -I/usr/src/sys -o trigger_benign trigger_benign.c
 * Run:   ./trigger_benign <suffix> <dev> <mountpoint>
 */
#include "common_kiconv.h"
#include <dirent.h>

#define IDX_BYTES	(0x200 * 8)
#define BLK_BYTES	(0x80 * 4)
#define NSLOTS		18

static void
dump_dir(const char *dir)
{
	char buf[32768];
	long base = 0;
	int fd, n;

	fd = open(dir, O_RDONLY);
	if (fd < 0)
		err(1, "open %s", dir);
	while ((n = getdirentries(fd, buf, sizeof(buf), &base)) > 0) {
		char *p = buf, *end = buf + n;
		while (p < end) {
			struct dirent *d = (struct dirent *)p;
			printf("--- dirent namlen=%d: ", d->d_namlen);
			for (int i = 0; i < d->d_namlen; i++) {
				unsigned char c = (unsigned char)d->d_name[i];
				if (c >= 0x20 && c < 0x7f)
					printf("%c", c);
				else
					printf("\\x%02x", c);
			}
			printf("\n");
			p += _DIRENT_DIRSIZ(d);
		}
	}
	close(fd);
}

int
main(int argc, char **argv)
{
	char name[64], from[64];
	static uint8_t tab[IDX_BYTES + NSLOTS * BLK_BYTES];
	uint64_t *idx = (uint64_t *)tab;
	uint32_t *blk;
	const char *sfx, *dev, *dir;
	int rank = 0;

	if (argc != 4) {
		fprintf(stderr, "usage: %s <suffix> <dev> <mountpoint>\n",
		    argv[0]);
		return (2);
	}
	sfx = argv[1];
	dev = argv[2];
	dir = argv[3];

	/* full, well-formed table: index slots + one 512B block each */
	idx['.'] = 1;
	for (int c = 'A'; c <= 'P'; c++)
		idx[c] = 1;
	idx['k'] = 1;
	for (int c = 0; c < 0x200; c++) {
		if (idx[c] == 0)
			continue;
		blk = (uint32_t *)(tab + IDX_BYTES + rank * BLK_BYTES);
		for (int j = 0; j < 0x80; j++)
			blk[j] = 0x4200 | rank;
		rank++;
	}

	snprintf(name, sizeof(name), "BEN%s", sfx);
	if (reg_pair("xlat16", name, "UTF-16BE", tab, sizeof(tab)) < 0)
		errx(1, "benign registration failed");
	snprintf(from, sizeof(from), "BND%s", sfx);
	reg_pair("xlat16", "UTF-16BE", name, tab, sizeof(tab));
	reg_pair("xlat16", from, name, tab, sizeof(tab));
	reg_pair("xlat16", name, from, tab, sizeof(tab));

	if (mount_kiconv(dev, dir, name, from) < 0)
		errx(1, "mount failed (regression!)");
	fflush(stdout);
	dump_dir(dir);
	unmount(dir, 0);
	printf("[+] benign control done\n");
	return (0);
}