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