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