1*d4514f0bSApple OSS Distributions /* This tests thread_t uaf vulnerability in the XNU kernel due to
2*d4514f0bSApple OSS Distributions * a race condition in unp_connect
3*d4514f0bSApple OSS Distributions */
4*d4514f0bSApple OSS Distributions
5*d4514f0bSApple OSS Distributions #include <sys/un.h>
6*d4514f0bSApple OSS Distributions #include <sys/socket.h>
7*d4514f0bSApple OSS Distributions #include <pthread.h>
8*d4514f0bSApple OSS Distributions #include <sys/proc_info.h>
9*d4514f0bSApple OSS Distributions #include <libproc.h>
10*d4514f0bSApple OSS Distributions #include <darwintest.h>
11*d4514f0bSApple OSS Distributions #include <unistd.h>
12*d4514f0bSApple OSS Distributions
13*d4514f0bSApple OSS Distributions int g_start = 0;
14*d4514f0bSApple OSS Distributions int g_client = 0;
15*d4514f0bSApple OSS Distributions int g_sever1 = 0;
16*d4514f0bSApple OSS Distributions int g_sever2 = 0;
17*d4514f0bSApple OSS Distributions
18*d4514f0bSApple OSS Distributions static void
server_thread1(char * path)19*d4514f0bSApple OSS Distributions server_thread1(char* path)
20*d4514f0bSApple OSS Distributions {
21*d4514f0bSApple OSS Distributions struct sockaddr_un server_sockaddr;
22*d4514f0bSApple OSS Distributions memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
23*d4514f0bSApple OSS Distributions server_sockaddr.sun_family = AF_UNIX;
24*d4514f0bSApple OSS Distributions strcpy(server_sockaddr.sun_path, path);
25*d4514f0bSApple OSS Distributions unlink(server_sockaddr.sun_path);
26*d4514f0bSApple OSS Distributions
27*d4514f0bSApple OSS Distributions int server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
28*d4514f0bSApple OSS Distributions g_sever1 = server_sock;
29*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bind(server_sock,
30*d4514f0bSApple OSS Distributions (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)), NULL);
31*d4514f0bSApple OSS Distributions
32*d4514f0bSApple OSS Distributions /*********************************/
33*d4514f0bSApple OSS Distributions /* Listen for any client sockets */
34*d4514f0bSApple OSS Distributions /*********************************/
35*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(listen(server_sock, -1), NULL);
36*d4514f0bSApple OSS Distributions
37*d4514f0bSApple OSS Distributions return;
38*d4514f0bSApple OSS Distributions }
39*d4514f0bSApple OSS Distributions
40*d4514f0bSApple OSS Distributions static void
server_thread2(char * path)41*d4514f0bSApple OSS Distributions server_thread2(char* path)
42*d4514f0bSApple OSS Distributions {
43*d4514f0bSApple OSS Distributions struct sockaddr_un server_sockaddr;
44*d4514f0bSApple OSS Distributions memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
45*d4514f0bSApple OSS Distributions server_sockaddr.sun_family = AF_UNIX;
46*d4514f0bSApple OSS Distributions strcpy(server_sockaddr.sun_path, path);
47*d4514f0bSApple OSS Distributions unlink(server_sockaddr.sun_path);
48*d4514f0bSApple OSS Distributions
49*d4514f0bSApple OSS Distributions int server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
50*d4514f0bSApple OSS Distributions g_sever2 = server_sock;
51*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bind(server_sock,
52*d4514f0bSApple OSS Distributions (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)), NULL);
53*d4514f0bSApple OSS Distributions
54*d4514f0bSApple OSS Distributions /*********************************/
55*d4514f0bSApple OSS Distributions /* Listen for any client sockets */
56*d4514f0bSApple OSS Distributions /*********************************/
57*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(listen(server_sock, -1), NULL);
58*d4514f0bSApple OSS Distributions
59*d4514f0bSApple OSS Distributions return;
60*d4514f0bSApple OSS Distributions }
61*d4514f0bSApple OSS Distributions
62*d4514f0bSApple OSS Distributions static void
try_to_connect(char * path)63*d4514f0bSApple OSS Distributions try_to_connect(char* path)
64*d4514f0bSApple OSS Distributions {
65*d4514f0bSApple OSS Distributions struct sockaddr_un server_sockaddr;
66*d4514f0bSApple OSS Distributions memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
67*d4514f0bSApple OSS Distributions server_sockaddr.sun_family = AF_UNIX;
68*d4514f0bSApple OSS Distributions strcpy(server_sockaddr.sun_path, path);
69*d4514f0bSApple OSS Distributions //unlink(server_sockaddr.sun_path);
70*d4514f0bSApple OSS Distributions
71*d4514f0bSApple OSS Distributions while (g_start == 0) {
72*d4514f0bSApple OSS Distributions usleep(100);
73*d4514f0bSApple OSS Distributions }
74*d4514f0bSApple OSS Distributions int ret = connect(g_client, (struct sockaddr *)&server_sockaddr,
75*d4514f0bSApple OSS Distributions sizeof(server_sockaddr));
76*d4514f0bSApple OSS Distributions
77*d4514f0bSApple OSS Distributions T_ASSERT_TRUE(ret == 0 || errno == EALREADY || errno == EISCONN,
78*d4514f0bSApple OSS Distributions "connect with ret: %d(%d)", ret, errno);
79*d4514f0bSApple OSS Distributions }
80*d4514f0bSApple OSS Distributions
81*d4514f0bSApple OSS Distributions
82*d4514f0bSApple OSS Distributions static void
test_unp_connect_multithread()83*d4514f0bSApple OSS Distributions test_unp_connect_multithread()
84*d4514f0bSApple OSS Distributions {
85*d4514f0bSApple OSS Distributions int client_sock;
86*d4514f0bSApple OSS Distributions char path[] = "/tmp/";
87*d4514f0bSApple OSS Distributions char path1[256];
88*d4514f0bSApple OSS Distributions char path2[256];
89*d4514f0bSApple OSS Distributions char path3[256];
90*d4514f0bSApple OSS Distributions
91*d4514f0bSApple OSS Distributions strncpy(path1, path, 255);
92*d4514f0bSApple OSS Distributions strcat(path1, "/1");
93*d4514f0bSApple OSS Distributions strncpy(path2, path, 255);
94*d4514f0bSApple OSS Distributions strcat(path2, "/2");
95*d4514f0bSApple OSS Distributions strncpy(path3, path, 255);
96*d4514f0bSApple OSS Distributions strcat(path3, "/3");
97*d4514f0bSApple OSS Distributions
98*d4514f0bSApple OSS Distributions
99*d4514f0bSApple OSS Distributions for (int i = 0; i < 1024; i++) {
100*d4514f0bSApple OSS Distributions T_SETUPBEGIN;
101*d4514f0bSApple OSS Distributions server_thread1(path1);
102*d4514f0bSApple OSS Distributions server_thread2(path2);
103*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(client_sock = socket(AF_UNIX, SOCK_STREAM, 0), NULL);
104*d4514f0bSApple OSS Distributions
105*d4514f0bSApple OSS Distributions unlink(path3);
106*d4514f0bSApple OSS Distributions struct sockaddr_un client_sockaddr;
107*d4514f0bSApple OSS Distributions client_sockaddr.sun_family = AF_UNIX;
108*d4514f0bSApple OSS Distributions strcpy(client_sockaddr.sun_path, path3);
109*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bind(client_sock, (struct sockaddr *)&client_sockaddr,
110*d4514f0bSApple OSS Distributions sizeof(client_sockaddr)), NULL);
111*d4514f0bSApple OSS Distributions T_SETUPEND;
112*d4514f0bSApple OSS Distributions g_client = client_sock;
113*d4514f0bSApple OSS Distributions g_start = 0;
114*d4514f0bSApple OSS Distributions pthread_t runner1;
115*d4514f0bSApple OSS Distributions pthread_t runner2;
116*d4514f0bSApple OSS Distributions if (pthread_create(&runner1, 0, (void*)try_to_connect, path1)) {
117*d4514f0bSApple OSS Distributions T_ASSERT_FAIL("pthread_create failed");
118*d4514f0bSApple OSS Distributions }
119*d4514f0bSApple OSS Distributions
120*d4514f0bSApple OSS Distributions if (pthread_create(&runner2, 0, (void*)try_to_connect, path2)) {
121*d4514f0bSApple OSS Distributions T_ASSERT_FAIL("pthread_create failed");
122*d4514f0bSApple OSS Distributions }
123*d4514f0bSApple OSS Distributions usleep(300);
124*d4514f0bSApple OSS Distributions g_start = 1;
125*d4514f0bSApple OSS Distributions pthread_join(runner1, 0);
126*d4514f0bSApple OSS Distributions pthread_join(runner2, 0);
127*d4514f0bSApple OSS Distributions
128*d4514f0bSApple OSS Distributions usleep(3000);
129*d4514f0bSApple OSS Distributions
130*d4514f0bSApple OSS Distributions struct socket_fdinfo si_1 = {0};
131*d4514f0bSApple OSS Distributions proc_pidfdinfo(getpid(), g_sever1, PROC_PIDFDSOCKETINFO, &si_1,
132*d4514f0bSApple OSS Distributions sizeof(si_1));
133*d4514f0bSApple OSS Distributions struct socket_fdinfo si_2 = {0};
134*d4514f0bSApple OSS Distributions proc_pidfdinfo(getpid(), g_sever2, PROC_PIDFDSOCKETINFO, &si_2,
135*d4514f0bSApple OSS Distributions sizeof(si_2));
136*d4514f0bSApple OSS Distributions if (si_1.psi.soi_incqlen || si_2.psi.soi_incqlen) {
137*d4514f0bSApple OSS Distributions close(g_sever2);
138*d4514f0bSApple OSS Distributions close(g_sever1);
139*d4514f0bSApple OSS Distributions }
140*d4514f0bSApple OSS Distributions close(client_sock);
141*d4514f0bSApple OSS Distributions close(g_sever2);
142*d4514f0bSApple OSS Distributions close(g_sever1);
143*d4514f0bSApple OSS Distributions }
144*d4514f0bSApple OSS Distributions }
145*d4514f0bSApple OSS Distributions
146*d4514f0bSApple OSS Distributions T_DECL(unp_connect_thread_uaf, "Uaf due to multithreaded unp_connect", T_META_TAG_VM_PREFERRED)
147*d4514f0bSApple OSS Distributions {
148*d4514f0bSApple OSS Distributions test_unp_connect_multithread();
149*d4514f0bSApple OSS Distributions }
150