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