xref: /xnu-11417.140.69/tests/uipc_uaf.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1*43a90889SApple OSS Distributions /*
2*43a90889SApple OSS Distributions  * Copyright (c) 2021 Apple Inc. All rights reserved.
3*43a90889SApple OSS Distributions  */
4*43a90889SApple OSS Distributions #include <stdio.h>
5*43a90889SApple OSS Distributions #include <errno.h>
6*43a90889SApple OSS Distributions #include <stdio.h>
7*43a90889SApple OSS Distributions #include <string.h>
8*43a90889SApple OSS Distributions #include <stdlib.h>
9*43a90889SApple OSS Distributions #include <unistd.h>
10*43a90889SApple OSS Distributions #include <arpa/inet.h>
11*43a90889SApple OSS Distributions #include <net/if_var.h>
12*43a90889SApple OSS Distributions #include <netinet/ip6.h>
13*43a90889SApple OSS Distributions #include <sys/sysctl.h>
14*43a90889SApple OSS Distributions #include <darwintest.h>
15*43a90889SApple OSS Distributions #include <TargetConditionals.h>
16*43a90889SApple OSS Distributions 
17*43a90889SApple OSS Distributions #define MAX_FDS ((MCLBYTES - sizeof(struct cmsghdr)) / sizeof(void *))
18*43a90889SApple OSS Distributions 
19*43a90889SApple OSS Distributions static bool running = false;
20*43a90889SApple OSS Distributions 
21*43a90889SApple OSS Distributions static void *
trigger_unp_gc(void * arg __unused)22*43a90889SApple OSS Distributions trigger_unp_gc(void *arg __unused)
23*43a90889SApple OSS Distributions {
24*43a90889SApple OSS Distributions 	int fd;
25*43a90889SApple OSS Distributions 	while (running) {
26*43a90889SApple OSS Distributions 		fd = socket(AF_UNIX, SOCK_STREAM, 0);
27*43a90889SApple OSS Distributions 		if (fd != -1) {
28*43a90889SApple OSS Distributions 			close(fd);
29*43a90889SApple OSS Distributions 		}
30*43a90889SApple OSS Distributions 	}
31*43a90889SApple OSS Distributions 	return NULL;
32*43a90889SApple OSS Distributions }
33*43a90889SApple OSS Distributions 
34*43a90889SApple OSS Distributions static void *
send_scm_rights(void * arg __unused)35*43a90889SApple OSS Distributions send_scm_rights(void *arg __unused)
36*43a90889SApple OSS Distributions {
37*43a90889SApple OSS Distributions 	struct iovec iov = {};
38*43a90889SApple OSS Distributions 	struct msghdr msg = {};
39*43a90889SApple OSS Distributions 	struct msg {
40*43a90889SApple OSS Distributions 		struct cmsghdr cmsg;
41*43a90889SApple OSS Distributions 		int fds[MAX_FDS];
42*43a90889SApple OSS Distributions 	};
43*43a90889SApple OSS Distributions 	struct msg ctrl_msg = {};
44*43a90889SApple OSS Distributions 
45*43a90889SApple OSS Distributions 	msg.msg_iov = &iov;
46*43a90889SApple OSS Distributions 	msg.msg_iovlen = 1;
47*43a90889SApple OSS Distributions 	msg.msg_control = &ctrl_msg;
48*43a90889SApple OSS Distributions 	msg.msg_controllen = sizeof(ctrl_msg) - ((MAX_FDS / 2) * sizeof(ctrl_msg.fds[0]));
49*43a90889SApple OSS Distributions 	ctrl_msg.cmsg.cmsg_type = SCM_RIGHTS;
50*43a90889SApple OSS Distributions 	ctrl_msg.cmsg.cmsg_level = SOL_SOCKET;
51*43a90889SApple OSS Distributions 	ctrl_msg.cmsg.cmsg_len = msg.msg_controllen;
52*43a90889SApple OSS Distributions 
53*43a90889SApple OSS Distributions 	struct msghdr overwrite_msg = {};
54*43a90889SApple OSS Distributions 	struct msg overwrite_ctrl_msg = {};
55*43a90889SApple OSS Distributions 
56*43a90889SApple OSS Distributions 	overwrite_msg.msg_iov = &iov;
57*43a90889SApple OSS Distributions 	overwrite_msg.msg_iovlen = 1;
58*43a90889SApple OSS Distributions 	overwrite_msg.msg_control = &overwrite_ctrl_msg;
59*43a90889SApple OSS Distributions 	overwrite_msg.msg_controllen = sizeof(overwrite_ctrl_msg);
60*43a90889SApple OSS Distributions 	overwrite_ctrl_msg.cmsg.cmsg_type = SCM_RIGHTS;
61*43a90889SApple OSS Distributions 	overwrite_ctrl_msg.cmsg.cmsg_level = SOL_SOCKET;
62*43a90889SApple OSS Distributions 	overwrite_ctrl_msg.cmsg.cmsg_len = msg.msg_controllen;
63*43a90889SApple OSS Distributions 
64*43a90889SApple OSS Distributions 	const uintptr_t invalid_ptr = 0x4141414141414141;
65*43a90889SApple OSS Distributions 	const uintptr_t *ptr = &invalid_ptr;
66*43a90889SApple OSS Distributions 	uintptr_t *overwrite_ctrl_msg_ptrs =
67*43a90889SApple OSS Distributions 	    (uintptr_t*)(void *)(&overwrite_ctrl_msg.fds[0]);
68*43a90889SApple OSS Distributions 	const int overwrite_ctrl_msg_ptrs_count =
69*43a90889SApple OSS Distributions 	    MAX_FDS / (sizeof(overwrite_ctrl_msg_ptrs[0]) / sizeof(overwrite_ctrl_msg.fds[0]));
70*43a90889SApple OSS Distributions 
71*43a90889SApple OSS Distributions 	for (int i = 0; i < overwrite_ctrl_msg_ptrs_count - 2; i++) {
72*43a90889SApple OSS Distributions 		overwrite_ctrl_msg_ptrs[i] = ptr[0];
73*43a90889SApple OSS Distributions 	}
74*43a90889SApple OSS Distributions 	memcpy(&(overwrite_ctrl_msg_ptrs[overwrite_ctrl_msg_ptrs_count - 2]),
75*43a90889SApple OSS Distributions 	    ptr,
76*43a90889SApple OSS Distributions 	    sizeof(ptr[0]));
77*43a90889SApple OSS Distributions 	while (running) {
78*43a90889SApple OSS Distributions 		int pair[2];
79*43a90889SApple OSS Distributions 
80*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), "socketpair");
81*43a90889SApple OSS Distributions 		for (unsigned i = 0; i < MAX_FDS / 2; i++) {
82*43a90889SApple OSS Distributions 			ctrl_msg.fds[i] = pair[1];
83*43a90889SApple OSS Distributions 		}
84*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(sendmsg(pair[1], &msg, 0), "sendmsg");
85*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(sendmsg(pair[0], &msg, 0), "sendmsg");
86*43a90889SApple OSS Distributions 		usleep(100);
87*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(shutdown(pair[1], SHUT_RD), "shutdown");
88*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_FAILURE(sendmsg(pair[0], &overwrite_msg, 0), EINVAL, "sendmsg");
89*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(close(pair[0]), "close");
90*43a90889SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(close(pair[1]), "close");
91*43a90889SApple OSS Distributions 	}
92*43a90889SApple OSS Distributions 
93*43a90889SApple OSS Distributions 	return NULL;
94*43a90889SApple OSS Distributions }
95*43a90889SApple OSS Distributions 
96*43a90889SApple OSS Distributions 
97*43a90889SApple OSS Distributions T_DECL(uipc_uaf, "Tests that the UNIX Domain Socket GC doesn't panic", T_META_CHECK_LEAKS(false), T_META_TAG_VM_PREFERRED)
98*43a90889SApple OSS Distributions {
99*43a90889SApple OSS Distributions #if TARGET_OS_WATCH
100*43a90889SApple OSS Distributions 	T_SKIP("test doesn't work on watchOS");
101*43a90889SApple OSS Distributions #endif
102*43a90889SApple OSS Distributions 	running = true;
103*43a90889SApple OSS Distributions 	pthread_t t1, t2;
104*43a90889SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(pthread_create(&t1, NULL, send_scm_rights, NULL), "pthread_create");
105*43a90889SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(pthread_create(&t2, NULL, send_scm_rights, NULL), "pthread_create");
106*43a90889SApple OSS Distributions 	pthread_t gc;
107*43a90889SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(pthread_create(&gc, NULL, trigger_unp_gc, NULL), "pthread_create");
108*43a90889SApple OSS Distributions 	sleep(59);
109*43a90889SApple OSS Distributions 	running = false;
110*43a90889SApple OSS Distributions 	sleep(1);
111*43a90889SApple OSS Distributions }
112