1*2c2f96dcSApple OSS Distributions /* 2*2c2f96dcSApple OSS Distributions * Proof of Concept / Test Case 3*2c2f96dcSApple OSS Distributions * XNU: aio_work_thread use-after-free for AIO_FSYNC entries 4*2c2f96dcSApple OSS Distributions */ 5*2c2f96dcSApple OSS Distributions #include <err.h> 6*2c2f96dcSApple OSS Distributions #include <stdarg.h> 7*2c2f96dcSApple OSS Distributions #include <stdint.h> 8*2c2f96dcSApple OSS Distributions #include <stdio.h> 9*2c2f96dcSApple OSS Distributions #include <stdlib.h> 10*2c2f96dcSApple OSS Distributions #include <string.h> 11*2c2f96dcSApple OSS Distributions #include <strings.h> 12*2c2f96dcSApple OSS Distributions 13*2c2f96dcSApple OSS Distributions #include <sys/aio.h> 14*2c2f96dcSApple OSS Distributions #include <unistd.h> 15*2c2f96dcSApple OSS Distributions #include <darwintest.h> 16*2c2f96dcSApple OSS Distributions #include <time.h> 17*2c2f96dcSApple OSS Distributions 18*2c2f96dcSApple OSS Distributions T_GLOBAL_META( 19*2c2f96dcSApple OSS Distributions T_META_NAMESPACE("xnu.fd"), 20*2c2f96dcSApple OSS Distributions T_META_RUN_CONCURRENTLY(true)); 21*2c2f96dcSApple OSS Distributions 22*2c2f96dcSApple OSS Distributions #define NREQUESTS 8 23*2c2f96dcSApple OSS Distributions 24*2c2f96dcSApple OSS Distributions static void attempt(int fd)25*2c2f96dcSApple OSS Distributionsattempt(int fd) 26*2c2f96dcSApple OSS Distributions { 27*2c2f96dcSApple OSS Distributions struct aiocb ap[NREQUESTS]; 28*2c2f96dcSApple OSS Distributions size_t n; 29*2c2f96dcSApple OSS Distributions unsigned char c; 30*2c2f96dcSApple OSS Distributions 31*2c2f96dcSApple OSS Distributions for (n = 0; n < NREQUESTS; ++n) { 32*2c2f96dcSApple OSS Distributions ap[n].aio_fildes = fd; 33*2c2f96dcSApple OSS Distributions ap[n].aio_nbytes = 1; 34*2c2f96dcSApple OSS Distributions ap[n].aio_buf = &c; 35*2c2f96dcSApple OSS Distributions ap[n].aio_sigevent.sigev_notify = SIGEV_NONE; 36*2c2f96dcSApple OSS Distributions } 37*2c2f96dcSApple OSS Distributions 38*2c2f96dcSApple OSS Distributions /* 39*2c2f96dcSApple OSS Distributions * fire them off and exit. 40*2c2f96dcSApple OSS Distributions */ 41*2c2f96dcSApple OSS Distributions for (n = 0; n < NREQUESTS; ++n) { 42*2c2f96dcSApple OSS Distributions aio_fsync((n & 1) ? O_SYNC : O_DSYNC, &ap[n]); 43*2c2f96dcSApple OSS Distributions } 44*2c2f96dcSApple OSS Distributions 45*2c2f96dcSApple OSS Distributions exit(0); 46*2c2f96dcSApple OSS Distributions } 47*2c2f96dcSApple OSS Distributions 48*2c2f96dcSApple OSS Distributions T_DECL(lio_listio_race_63669270, "test for the lightspeed/unc0ver UaF") 49*2c2f96dcSApple OSS Distributions { 50*2c2f96dcSApple OSS Distributions pid_t child; 51*2c2f96dcSApple OSS Distributions int fd; 52*2c2f96dcSApple OSS Distributions char path[128]; 53*2c2f96dcSApple OSS Distributions uint64_t end = clock_gettime_nsec_np(CLOCK_UPTIME_RAW) + 10 * NSEC_PER_SEC; 54*2c2f96dcSApple OSS Distributions 55*2c2f96dcSApple OSS Distributions /* we need a valid fd: */ 56*2c2f96dcSApple OSS Distributions strcpy(path, "/tmp/aio_fsync_uaf.XXXXXX"); 57*2c2f96dcSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(fd = mkstemp(path), "mkstemp"); 58*2c2f96dcSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(unlink(path), "unlink"); 59*2c2f96dcSApple OSS Distributions 60*2c2f96dcSApple OSS Distributions T_LOG("starting..."); 61*2c2f96dcSApple OSS Distributions do { 62*2c2f96dcSApple OSS Distributions switch ((child = fork())) { 63*2c2f96dcSApple OSS Distributions case -1: T_FAIL("fork"); 64*2c2f96dcSApple OSS Distributions case 0: attempt(fd); 65*2c2f96dcSApple OSS Distributions } 66*2c2f96dcSApple OSS Distributions 67*2c2f96dcSApple OSS Distributions T_QUIET; T_EXPECT_POSIX_SUCCESS(waitpid(child, NULL, 0), "waitpid"); 68*2c2f96dcSApple OSS Distributions } while (clock_gettime_nsec_np(CLOCK_UPTIME_RAW) < end); 69*2c2f96dcSApple OSS Distributions 70*2c2f96dcSApple OSS Distributions T_PASS("the system didn't panic"); 71*2c2f96dcSApple OSS Distributions } 72