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