1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <sys/ioctl.h>
7 #include <sys/socket.h>
8 #include <sys/sys_domain.h>
9 #include <sys/kern_control.h>
10 
11 #include <darwintest.h>
12 
13 #define RVI_CONTROL_NAME          "com.apple.net.rvi_control"
14 #define RVI_COMMAND_GET_INTERFACE 0x20
15 
16 T_GLOBAL_META(
17 	T_META_NAMESPACE("xnu.net"),
18 	T_META_RADAR_COMPONENT_NAME("xnu"),
19 	T_META_RADAR_COMPONENT_VERSION("networking"),
20 	T_META_ENABLED(TARGET_OS_OSX),
21 	T_META_ASROOT_(1)
22 	);
23 
24 T_DECL(rvi_control_get_interface, "getsockopt on RVI control-socket triggering out-of-bounds memory access", T_META_TAG_VM_PREFERRED)
25 {
26 	int fd;
27 
28 	T_ASSERT_POSIX_SUCCESS(fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL);
29 
30 	struct ctl_info ctl_info = {
31 		.ctl_name = RVI_CONTROL_NAME
32 	};
33 	T_ASSERT_POSIX_SUCCESS(ioctl(fd, CTLIOCGINFO, &ctl_info), NULL);
34 
35 	struct sockaddr_ctl sockaddr_ctl = {
36 		.sc_len = sizeof(struct sockaddr_ctl),
37 		.sc_family = AF_SYSTEM,
38 		.ss_sysaddr = AF_SYS_CONTROL,
39 		.sc_id = ctl_info.ctl_id,
40 		.sc_unit = 0
41 	};
42 	T_ASSERT_POSIX_SUCCESS(connect(fd, (const struct sockaddr *)&sockaddr_ctl, sizeof(struct sockaddr_ctl)), NULL);
43 
44 	char data[10];
45 	socklen_t data_len = 1;
46 	T_ASSERT_POSIX_SUCCESS(getsockopt(fd, SYSPROTO_CONTROL, RVI_COMMAND_GET_INTERFACE, &data, &data_len), NULL);
47 
48 	data_len = 5;
49 	T_ASSERT_POSIX_SUCCESS(getsockopt(fd, SYSPROTO_CONTROL, RVI_COMMAND_GET_INTERFACE, &data, &data_len), NULL);
50 	T_ASSERT_EQ(data_len, 5, "data_len == 5", NULL);
51 
52 	data_len = 10;
53 	T_ASSERT_POSIX_SUCCESS(getsockopt(fd, SYSPROTO_CONTROL, RVI_COMMAND_GET_INTERFACE, &data, &data_len), NULL);
54 	T_ASSERT_EQ(data_len, 5, "data_len == 5", NULL);
55 
56 	T_PASS("success");
57 }
58