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