xref: /xnu-8020.140.41/tests/flow_div_doubleconnect_55917185.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 #include <stdlib.h>
2 
3 #include <pthread.h>
4 #include <sys/kern_control.h>
5 #include <sys/socket.h>
6 #include <sys/sys_domain.h>
7 #include <unistd.h>
8 
9 #include <darwintest.h>
10 
11 /* we should win the race in this window: */
12 #define NTRIES 200000
13 
14 static void *
connect_race(void * data)15 connect_race(void *data)
16 {
17 	int *ps = data;
18 	struct sockaddr_ctl sc = {
19 		.sc_id = 1 /* com.apple.flow-divert */
20 	};
21 	int n;
22 
23 	for (n = 0; n < NTRIES; ++n) {
24 		connect(*ps, (const struct sockaddr *)&sc, sizeof(sc));
25 	}
26 
27 	return NULL;
28 }
29 
30 T_DECL(flow_div_doubleconnect_55917185, "Bad error path in double-connect for flow_divert_kctl_connect")
31 {
32 	int s = -1;
33 	int tmp_s;
34 	struct sockaddr_ctl sc = {
35 		.sc_id = 1 /* com.apple.flow-divert */
36 	};
37 	pthread_t t;
38 	int n;
39 
40 	T_SETUPBEGIN;
41 	T_ASSERT_POSIX_ZERO(pthread_create(&t, NULL, connect_race, &s), NULL);
42 	T_SETUPEND;
43 
44 	for (n = 0; n < NTRIES; ++n) {
45 		T_ASSERT_POSIX_SUCCESS(tmp_s = socket(AF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL);
46 
47 		/*
48 		 * this bind will fail, but that's ok because it initialises
49 		 * kctl:
50 		 */
51 		bind(tmp_s, (const struct sockaddr *)&sc, sizeof(sc));
52 
53 		/* this is what we're racing the other thread for: */
54 		s = tmp_s;
55 		connect(s, (const struct sockaddr *)&sc, sizeof(sc));
56 
57 		T_ASSERT_POSIX_SUCCESS(close(s), NULL);
58 		s = -1;
59 	}
60 
61 	T_ASSERT_POSIX_ZERO(pthread_join(t, NULL), NULL);
62 	T_PASS("flow_divert_kctl_connect race didn't trigger panic");
63 }
64