@expo/build-tools 24.3.0 → 24.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ // Host-runnable tests for the guard's policy and formatting. Build and run
2
+ // with tests/run-policy-tests.sh; every failure prints the failing line.
3
+ #include "../policy.h"
4
+
5
+ #include <arpa/inet.h>
6
+ #include <netinet/in.h>
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #include <sys/un.h>
10
+
11
+ static int failures = 0;
12
+ #define CHECK(cond) \
13
+ do { \
14
+ if (!(cond)) { \
15
+ failures++; \
16
+ fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
17
+ } \
18
+ } while (0)
19
+
20
+ static struct sockaddr_in v4(const char *ip, int port) {
21
+ struct sockaddr_in a; memset(&a, 0, sizeof a);
22
+ a.sin_family = AF_INET; a.sin_len = sizeof a; a.sin_port = htons(port);
23
+ inet_pton(AF_INET, ip, &a.sin_addr);
24
+ return a;
25
+ }
26
+ static struct sockaddr_in6 v6(const char *ip, int port) {
27
+ struct sockaddr_in6 a; memset(&a, 0, sizeof a);
28
+ a.sin6_family = AF_INET6; a.sin6_len = sizeof a; a.sin6_port = htons(port);
29
+ inet_pton(AF_INET6, ip, &a.sin6_addr);
30
+ return a;
31
+ }
32
+
33
+ static void test_classify(void) {
34
+ struct sockaddr_in a4; struct sockaddr_in6 a6; struct sockaddr_un un;
35
+
36
+ a4 = v4("127.0.0.1", 8899); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_LOOPBACK);
37
+ a4 = v4("127.42.0.9", 80); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_LOOPBACK);
38
+ a4 = v4("0.0.0.0", 80); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_LOOPBACK);
39
+ a4 = v4("93.184.216.34", 443); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_REMOTE);
40
+ a4 = v4("192.168.1.10", 8081); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_REMOTE);
41
+ a4 = v4("169.254.1.1", 80); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_REMOTE);
42
+ a4 = v4("224.0.0.251", 5353); CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_REMOTE);
43
+
44
+ a6 = v6("::1", 8899); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_LOOPBACK);
45
+ a6 = v6("::", 80); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_LOOPBACK);
46
+ a6 = v6("::ffff:127.0.0.1", 8899); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_LOOPBACK);
47
+ a6 = v6("::ffff:93.184.216.34", 443); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_REMOTE);
48
+ a6 = v6("2606:4700::1", 443); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_REMOTE);
49
+ a6 = v6("fe80::1", 443); CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_REMOTE);
50
+
51
+ memset(&un, 0, sizeof un); un.sun_family = AF_UNIX; strcpy(un.sun_path, "/var/run/mDNSResponder");
52
+ CHECK(eg_classify((struct sockaddr *)&un, sizeof un) == EG_PASSTHROUGH);
53
+ CHECK(eg_classify(NULL, 0) == EG_PASSTHROUGH);
54
+ a4 = v4("93.184.216.34", 443); CHECK(eg_classify((struct sockaddr *)&a4, 4) == EG_PASSTHROUGH); // too short to read
55
+
56
+ // AF_UNSPEC is what the kernel makes of it: the family the exact length implies.
57
+ a4 = v4("93.184.216.34", 443); a4.sin_family = AF_UNSPEC;
58
+ CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_REMOTE);
59
+ CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4 + 8) == EG_PASSTHROUGH); // kernel: EINVAL
60
+ a4 = v4("127.0.0.1", 8899); a4.sin_family = AF_UNSPEC;
61
+ CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_LOOPBACK);
62
+ a4 = v4("0.0.0.0", 0); a4.sin_family = AF_UNSPEC;
63
+ CHECK(eg_classify((struct sockaddr *)&a4, sizeof a4) == EG_LOOPBACK); // UDP disconnect shape
64
+ a6 = v6("2606:4700::1", 443); a6.sin6_family = AF_UNSPEC;
65
+ CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_REMOTE);
66
+ a6 = v6("::ffff:93.184.216.34", 443); a6.sin6_family = AF_UNSPEC;
67
+ CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_REMOTE);
68
+ a6 = v6("::1", 443); a6.sin6_family = AF_UNSPEC;
69
+ CHECK(eg_classify((struct sockaddr *)&a6, sizeof a6) == EG_LOOPBACK);
70
+ memset(&un, 0, sizeof un); un.sun_family = AF_UNSPEC;
71
+ CHECK(eg_classify((struct sockaddr *)&un, sizeof un) == EG_PASSTHROUGH);
72
+ }
73
+
74
+ static void test_mode(void) {
75
+ CHECK(eg_parse_mode(NULL) == EG_MODE_BLOCK);
76
+ CHECK(eg_parse_mode("") == EG_MODE_BLOCK);
77
+ CHECK(eg_parse_mode("block") == EG_MODE_BLOCK);
78
+ CHECK(eg_parse_mode("log") == EG_MODE_LOG);
79
+ CHECK(eg_parse_mode("LOG") == EG_MODE_BLOCK);
80
+ CHECK(eg_parse_mode("permissive") == EG_MODE_BLOCK);
81
+
82
+ CHECK(eg_should_deny(EG_MODE_BLOCK, EG_REMOTE) == 1);
83
+ CHECK(eg_should_deny(EG_MODE_BLOCK, EG_LOOPBACK) == 0);
84
+ CHECK(eg_should_deny(EG_MODE_BLOCK, EG_PASSTHROUGH) == 0);
85
+ CHECK(eg_should_deny(EG_MODE_LOG, EG_REMOTE) == 0);
86
+ }
87
+
88
+ static void test_format_peer(void) {
89
+ char out[64];
90
+ struct sockaddr_in a4 = v4("93.184.216.34", 443);
91
+ CHECK(eg_format_peer((struct sockaddr *)&a4, sizeof a4, out, sizeof out) == 0);
92
+ CHECK(strcmp(out, "93.184.216.34:443") == 0);
93
+ struct sockaddr_in6 a6 = v6("2606:4700::1", 443);
94
+ CHECK(eg_format_peer((struct sockaddr *)&a6, sizeof a6, out, sizeof out) == 0);
95
+ CHECK(strcmp(out, "[2606:4700::1]:443") == 0);
96
+ CHECK(eg_format_peer((struct sockaddr *)&a4, sizeof a4, out, 8) != 0);
97
+ struct sockaddr_un un; memset(&un, 0, sizeof un); un.sun_family = AF_UNIX;
98
+ CHECK(eg_format_peer((struct sockaddr *)&un, sizeof un, out, sizeof out) != 0);
99
+ a4.sin_family = AF_UNSPEC;
100
+ CHECK(eg_format_peer((struct sockaddr *)&a4, sizeof a4, out, sizeof out) == 0);
101
+ CHECK(strcmp(out, "93.184.216.34:443") == 0);
102
+ a6.sin6_family = AF_UNSPEC;
103
+ CHECK(eg_format_peer((struct sockaddr *)&a6, sizeof a6, out, sizeof out) == 0);
104
+ CHECK(strcmp(out, "[2606:4700::1]:443") == 0);
105
+ }
106
+
107
+ static void test_seen(void) {
108
+ static eg_seen_t seen; memset(&seen, 0, sizeof seen);
109
+ CHECK(eg_seen_insert(&seen, "connect 1.1.1.1:443") == 1);
110
+ CHECK(eg_seen_insert(&seen, "connect 1.1.1.1:443") == 0);
111
+ CHECK(eg_seen_insert(&seen, "sendto 1.1.1.1:443") == 1);
112
+ CHECK(seen.count == 2);
113
+ char key[64];
114
+ for (int i = 0; i < EG_SEEN_CAPACITY + 5; i++) { snprintf(key, sizeof key, "k%d", i); eg_seen_insert(&seen, key); }
115
+ CHECK(seen.count == EG_SEEN_CAPACITY);
116
+ CHECK(seen.overflow == 7); // 2 + 128 + 5 attempts, 128 fit
117
+ CHECK(eg_seen_insert(&seen, "k0") == 0); // still remembered
118
+ }
119
+
120
+ static void test_format_event(void) {
121
+ char out[512];
122
+ const char *callers[] = {"Network", "CFNetwork", "MyApp"};
123
+ int n = eg_format_event(out, sizeof out, "MyApp", 4242, "connect", "blocked", "93.184.216.34:443", callers, 3);
124
+ CHECK(n > 0);
125
+ CHECK(strcmp(out, "eas-egress-guard\tMyApp\t4242\tconnect\tblocked\t93.184.216.34:443\tNetwork,CFNetwork,MyApp\n") == 0);
126
+
127
+ const char *tabbed[] = {"a\tb"};
128
+ n = eg_format_event(out, sizeof out, "we\nird\tname", 1, "sendto", "logged", "1.2.3.4:53", tabbed, 1);
129
+ CHECK(n > 0);
130
+ CHECK(strcmp(out, "eas-egress-guard\twe ird name\t1\tsendto\tlogged\t1.2.3.4:53\ta b\n") == 0);
131
+
132
+ n = eg_format_event(out, sizeof out, "NoCallers", 7, "connectx", "blocked", "[::2]:80", NULL, 0);
133
+ CHECK(n > 0 && strcmp(out, "eas-egress-guard\tNoCallers\t7\tconnectx\tblocked\t[::2]:80\t\n") == 0);
134
+
135
+ CHECK(eg_format_event(out, 16, "MyApp", 4242, "connect", "blocked", "93.184.216.34:443", callers, 3) == -1);
136
+ }
137
+
138
+ int main(void) {
139
+ test_classify(); test_mode(); test_format_peer(); test_seen(); test_format_event();
140
+ if (failures) { fprintf(stderr, "%d failure(s)\n", failures); return 1; }
141
+ printf("egress-guard policy tests: all passed\n");
142
+ return 0;
143
+ }
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ # Builds the guard for the host (macOS) and runs the guard tests against it:
3
+ # white-box lock schedules with guard.c compiled in, and black-box cases with
4
+ # the built library inserted the way the simulator inserts it. No socket is
5
+ # ever opened to a non-loopback address.
6
+ set -euo pipefail
7
+ cd "$(dirname "$0")/.."
8
+ out=$(mktemp -d)
9
+ trap 'rm -rf "$out"' EXIT
10
+
11
+ clang -std=c11 -Wall -Wextra -Werror -O2 -dynamiclib policy.c guard.c -o "$out/egress-guard.dylib"
12
+ clang -std=c11 -Wall -Wextra -Werror -O2 -pthread policy.c tests/guard_test.c -o "$out/guard-test"
13
+ clang -std=c11 -Wall -Wextra -Werror -O2 tests/guard_insert_test.c -o "$out/guard-insert-test"
14
+
15
+ failures=0
16
+ report() {
17
+ if [[ $2 -eq 0 ]]; then
18
+ echo "ok $1"
19
+ else
20
+ echo "FAIL $1 (exit $2)"
21
+ failures=$((failures + 1))
22
+ fi
23
+ }
24
+
25
+ # White-box: guard.c compiled into the test, lock schedules forced.
26
+ for name in signal fork contention; do
27
+ status=0
28
+ : > "$out/$name.log"
29
+ EAS_EGRESS_GUARD_MODE=block EAS_EGRESS_GUARD_LOG="$out/$name.log" \
30
+ "$out/guard-test" "$name" || status=$?
31
+ report "$name" "$status"
32
+ done
33
+
34
+ # Black-box: the built library inserted into a plain process.
35
+ export DYLD_INSERT_LIBRARIES="$out/egress-guard.dylib"
36
+ export EAS_EGRESS_GUARD_MODE=block
37
+
38
+ status=0
39
+ : > "$out/fd-reuse.log"
40
+ EAS_EGRESS_GUARD_LOG="$out/fd-reuse.log" \
41
+ "$out/guard-insert-test" fd-reuse "$out/fd-reuse.log" "$out/application-file" || status=$?
42
+ report fd-reuse "$status"
43
+
44
+ status=0
45
+ : > "$out/low-fd.log"
46
+ EAS_EGRESS_GUARD_LOG="$out/low-fd.log" \
47
+ "$out/guard-insert-test" low-fd "$out/low-fd.log" 1>&- || status=$?
48
+ report low-fd "$status"
49
+
50
+ for name in nocancel unspec udp-disconnect callers overflow; do
51
+ status=0
52
+ : > "$out/$name.log"
53
+ EAS_EGRESS_GUARD_LOG="$out/$name.log" \
54
+ "$out/guard-insert-test" "$name" "$out/$name.log" || status=$?
55
+ report "$name" "$status"
56
+ done
57
+
58
+ if [[ $failures -ne 0 ]]; then
59
+ echo "egress-guard guard tests: $failures failure(s)"
60
+ exit 1
61
+ fi
62
+ echo "egress-guard guard tests: all passed"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ # Builds the policy unit tests for the host (macOS) and runs them.
3
+ set -euo pipefail
4
+ cd "$(dirname "$0")/.."
5
+ out=$(mktemp -d)
6
+ clang -std=c11 -Wall -Wextra -Werror -o "$out/policy_test" policy.c tests/policy_test.c
7
+ "$out/policy_test"