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