1 /* This tests thread_t uaf vulnerability in the XNU kernel due to
2 * a race condition in unp_connect
6 #include <sys/socket.h>
8 #include <sys/proc_info.h>
10 #include <darwintest.h>
19 server_thread1(char* path
)
21 struct sockaddr_un server_sockaddr
;
22 memset(&server_sockaddr
, 0, sizeof(struct sockaddr_un
));
23 server_sockaddr
.sun_family
= AF_UNIX
;
24 strcpy(server_sockaddr
.sun_path
, path
);
25 unlink(server_sockaddr
.sun_path
);
27 int server_sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
28 g_sever1
= server_sock
;
29 T_ASSERT_POSIX_SUCCESS(bind(server_sock
,
30 (struct sockaddr
*) &server_sockaddr
, sizeof(server_sockaddr
)), NULL
);
32 /*********************************/
33 /* Listen for any client sockets */
34 /*********************************/
35 T_ASSERT_POSIX_SUCCESS(listen(server_sock
, -1), NULL
);
41 server_thread2(char* path
)
43 struct sockaddr_un server_sockaddr
;
44 memset(&server_sockaddr
, 0, sizeof(struct sockaddr_un
));
45 server_sockaddr
.sun_family
= AF_UNIX
;
46 strcpy(server_sockaddr
.sun_path
, path
);
47 unlink(server_sockaddr
.sun_path
);
49 int server_sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
50 g_sever2
= server_sock
;
51 T_ASSERT_POSIX_SUCCESS(bind(server_sock
,
52 (struct sockaddr
*) &server_sockaddr
, sizeof(server_sockaddr
)), NULL
);
54 /*********************************/
55 /* Listen for any client sockets */
56 /*********************************/
57 T_ASSERT_POSIX_SUCCESS(listen(server_sock
, -1), NULL
);
63 try_to_connect(char* path
)
65 struct sockaddr_un server_sockaddr
;
66 memset(&server_sockaddr
, 0, sizeof(struct sockaddr_un
));
67 server_sockaddr
.sun_family
= AF_UNIX
;
68 strcpy(server_sockaddr
.sun_path
, path
);
69 //unlink(server_sockaddr.sun_path);
71 while (g_start
== 0) {
74 int ret
= connect(g_client
, (struct sockaddr
*)&server_sockaddr
,
75 sizeof(server_sockaddr
));
77 T_ASSERT_TRUE(ret
== 0 || errno
== EALREADY
|| errno
== EISCONN
,
78 "connect with ret: %d(%d)", ret
, errno
);
83 test_unp_connect_multithread()
86 char path
[] = "/tmp/";
91 strncpy(path1
, path
, 255);
93 strncpy(path2
, path
, 255);
95 strncpy(path3
, path
, 255);
99 for (int i
= 0; i
< 1024; i
++) {
101 server_thread1(path1
);
102 server_thread2(path2
);
103 T_ASSERT_POSIX_SUCCESS(client_sock
= socket(AF_UNIX
, SOCK_STREAM
, 0), NULL
);
106 struct sockaddr_un client_sockaddr
;
107 client_sockaddr
.sun_family
= AF_UNIX
;
108 strcpy(client_sockaddr
.sun_path
, path3
);
109 T_ASSERT_POSIX_SUCCESS(bind(client_sock
, (struct sockaddr
*)&client_sockaddr
,
110 sizeof(client_sockaddr
)), NULL
);
112 g_client
= client_sock
;
116 if (pthread_create(&runner1
, 0, (void*)try_to_connect
, path1
)) {
117 T_ASSERT_FAIL("pthread_create failed");
120 if (pthread_create(&runner2
, 0, (void*)try_to_connect
, path2
)) {
121 T_ASSERT_FAIL("pthread_create failed");
125 pthread_join(runner1
, 0);
126 pthread_join(runner2
, 0);
130 struct socket_fdinfo si_1
= {0};
131 proc_pidfdinfo(getpid(), g_sever1
, PROC_PIDFDSOCKETINFO
, &si_1
,
133 struct socket_fdinfo si_2
= {0};
134 proc_pidfdinfo(getpid(), g_sever2
, PROC_PIDFDSOCKETINFO
, &si_2
,
136 if (si_1
.psi
.soi_incqlen
|| si_2
.psi
.soi_incqlen
) {
146 T_DECL(unp_connect_thread_uaf
, "Uaf due to multithreaded unp_connect")
148 test_unp_connect_multithread();