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