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