1*5c2921b0SApple OSS Distributions #include <darwintest.h>
2*5c2921b0SApple OSS Distributions #include <stdint.h>
3*5c2921b0SApple OSS Distributions #include <bsm/libbsm.h>
4*5c2921b0SApple OSS Distributions #include <System/sys/codesign.h>
5*5c2921b0SApple OSS Distributions #include <sys/errno.h>
6*5c2921b0SApple OSS Distributions #include <stdio.h>
7*5c2921b0SApple OSS Distributions #include <unistd.h>
8*5c2921b0SApple OSS Distributions
9*5c2921b0SApple OSS Distributions #define MAXBUFLEN 1024 * 1024
10*5c2921b0SApple OSS Distributions
11*5c2921b0SApple OSS Distributions T_GLOBAL_META(
12*5c2921b0SApple OSS Distributions T_META_NAMESPACE("xnu.codesigning"),
13*5c2921b0SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
14*5c2921b0SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("codesigning"),
15*5c2921b0SApple OSS Distributions T_META_OWNER("rkendallkuppe"));
16*5c2921b0SApple OSS Distributions
17*5c2921b0SApple OSS Distributions int
get_blob(pid_t pid,int op)18*5c2921b0SApple OSS Distributions get_blob(pid_t pid, int op)
19*5c2921b0SApple OSS Distributions {
20*5c2921b0SApple OSS Distributions uint8_t header[8];
21*5c2921b0SApple OSS Distributions unsigned int cnt;
22*5c2921b0SApple OSS Distributions int rcent;
23*5c2921b0SApple OSS Distributions
24*5c2921b0SApple OSS Distributions for (cnt = 0; cnt < sizeof(header); cnt++) {
25*5c2921b0SApple OSS Distributions rcent = csops(pid, op, header, cnt);
26*5c2921b0SApple OSS Distributions if (rcent != -1 && errno != ERANGE) {
27*5c2921b0SApple OSS Distributions T_ASSERT_FAIL("errno != ERANGE for short header");
28*5c2921b0SApple OSS Distributions }
29*5c2921b0SApple OSS Distributions }
30*5c2921b0SApple OSS Distributions
31*5c2921b0SApple OSS Distributions rcent = csops(pid, op, header, sizeof(header));
32*5c2921b0SApple OSS Distributions if (rcent == -1 && errno == ERANGE) {
33*5c2921b0SApple OSS Distributions uint32_t len, bufferlen, bufferlen2;
34*5c2921b0SApple OSS Distributions
35*5c2921b0SApple OSS Distributions memcpy(&len, &header[4], 4);
36*5c2921b0SApple OSS Distributions bufferlen = ntohl(len);
37*5c2921b0SApple OSS Distributions
38*5c2921b0SApple OSS Distributions T_LOG("Checking bufferlen on blob from kernel for csop %d", op);
39*5c2921b0SApple OSS Distributions T_ASSERT_LE_INT(bufferlen, MAXBUFLEN, "Buffer length %zu on blob from kernel can't exceed %zu",
40*5c2921b0SApple OSS Distributions (size_t)bufferlen, MAXBUFLEN);
41*5c2921b0SApple OSS Distributions T_ASSERT_NE_INT(bufferlen, 0, "Buffer length %zu on blob from kernel can't be zero",
42*5c2921b0SApple OSS Distributions (size_t)bufferlen);
43*5c2921b0SApple OSS Distributions T_ASSERT_GE_INT(bufferlen, 8, "Buffer length %zu on blob from kernel can't be less than a byte",
44*5c2921b0SApple OSS Distributions (size_t)bufferlen);
45*5c2921b0SApple OSS Distributions
46*5c2921b0SApple OSS Distributions uint8_t buffer[bufferlen + 1];
47*5c2921b0SApple OSS Distributions
48*5c2921b0SApple OSS Distributions rcent = csops(pid, op, buffer, bufferlen - 1);
49*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(errno, ERANGE, "Performing CS OPS csops with a full buffer - 1");
50*5c2921b0SApple OSS Distributions
51*5c2921b0SApple OSS Distributions rcent = csops(pid, op, buffer, bufferlen);
52*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Performing CS OPS with full buffer.");
53*5c2921b0SApple OSS Distributions
54*5c2921b0SApple OSS Distributions memcpy(&len, &buffer[4], 4);
55*5c2921b0SApple OSS Distributions bufferlen2 = ntohl(len);
56*5c2921b0SApple OSS Distributions
57*5c2921b0SApple OSS Distributions if (op == CS_OPS_BLOB) {
58*5c2921b0SApple OSS Distributions T_ASSERT_LE_INT(bufferlen2, bufferlen, "Checking %zu is %zu larger on second try",
59*5c2921b0SApple OSS Distributions (size_t)bufferlen2, (size_t)bufferlen);
60*5c2921b0SApple OSS Distributions
61*5c2921b0SApple OSS Distributions /*
62*5c2921b0SApple OSS Distributions * CS_OPS_BLOB may want a bigger buffer than the size
63*5c2921b0SApple OSS Distributions * of the actual blob. If the blob came in through a
64*5c2921b0SApple OSS Distributions * load command for example, then CS_OPS_BLOB will
65*5c2921b0SApple OSS Distributions * want to copy out the whole buffer that the load
66*5c2921b0SApple OSS Distributions * command points to, which is usually an estimated
67*5c2921b0SApple OSS Distributions * size. The actual blob, and therefore the size in
68*5c2921b0SApple OSS Distributions * the blob's header, may be smaller.
69*5c2921b0SApple OSS Distributions */
70*5c2921b0SApple OSS Distributions T_LOG("Blob is smaller (%zu) than expected (%zu). This is fine.",
71*5c2921b0SApple OSS Distributions (size_t)bufferlen2, (size_t)bufferlen);
72*5c2921b0SApple OSS Distributions } else {
73*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(bufferlen2, bufferlen, "Checking bufferlen sizes are different");
74*5c2921b0SApple OSS Distributions }
75*5c2921b0SApple OSS Distributions
76*5c2921b0SApple OSS Distributions rcent = csops(pid, op, buffer, bufferlen + 1);
77*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Performing CS OPS with a full buffer + 1");
78*5c2921b0SApple OSS Distributions
79*5c2921b0SApple OSS Distributions return 0;
80*5c2921b0SApple OSS Distributions } else if (rcent == 0) {
81*5c2921b0SApple OSS Distributions return 0;
82*5c2921b0SApple OSS Distributions } else {
83*5c2921b0SApple OSS Distributions return 1;
84*5c2921b0SApple OSS Distributions }
85*5c2921b0SApple OSS Distributions }
86*5c2921b0SApple OSS Distributions
87*5c2921b0SApple OSS Distributions /*
88*5c2921b0SApple OSS Distributions * This source is compiled with different names and build flags.
89*5c2921b0SApple OSS Distributions * Makefile has the detail of the TESTNAME.
90*5c2921b0SApple OSS Distributions */
91*5c2921b0SApple OSS Distributions
92*5c2921b0SApple OSS Distributions T_DECL(TESTNAME, "CS OP, code sign operations test")
93*5c2921b0SApple OSS Distributions {
94*5c2921b0SApple OSS Distributions uint32_t status;
95*5c2921b0SApple OSS Distributions int rcent;
96*5c2921b0SApple OSS Distributions pid_t pid;
97*5c2921b0SApple OSS Distributions
98*5c2921b0SApple OSS Distributions pid = getpid();
99*5c2921b0SApple OSS Distributions
100*5c2921b0SApple OSS Distributions
101*5c2921b0SApple OSS Distributions rcent = get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB);
102*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS entitlements blob");
103*5c2921b0SApple OSS Distributions
104*5c2921b0SApple OSS Distributions rcent = get_blob(0, CS_OPS_ENTITLEMENTS_BLOB);
105*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS entitlements blob");
106*5c2921b0SApple OSS Distributions
107*5c2921b0SApple OSS Distributions rcent = get_blob(pid, CS_OPS_BLOB);
108*5c2921b0SApple OSS Distributions
109*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS blob");
110*5c2921b0SApple OSS Distributions
111*5c2921b0SApple OSS Distributions rcent = get_blob(0, CS_OPS_BLOB);
112*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPS blob");
113*5c2921b0SApple OSS Distributions
114*5c2921b0SApple OSS Distributions rcent = get_blob(pid, CS_OPS_IDENTITY);
115*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs identity");
116*5c2921b0SApple OSS Distributions
117*5c2921b0SApple OSS Distributions rcent = get_blob(0, CS_OPS_IDENTITY);
118*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs identity");
119*5c2921b0SApple OSS Distributions
120*5c2921b0SApple OSS Distributions rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status) - 1);
121*5c2921b0SApple OSS Distributions T_ASSERT_NE_INT(rcent, 0, "Checking CS OPs set status by setting buffer to (status - 1)");
122*5c2921b0SApple OSS Distributions
123*5c2921b0SApple OSS Distributions status = CS_RESTRICT;
124*5c2921b0SApple OSS Distributions rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
125*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Checking CS OPs set status by setting proc RESTRICTED");
126*5c2921b0SApple OSS Distributions
127*5c2921b0SApple OSS Distributions rcent = csops(pid, CS_OPS_STATUS, &status, sizeof(status));
128*5c2921b0SApple OSS Distributions T_ASSERT_EQ_INT(rcent, 0, "Getting CS OPs status of process");
129*5c2921b0SApple OSS Distributions
130*5c2921b0SApple OSS Distributions /*
131*5c2921b0SApple OSS Distributions * Only run the folling tests if not HARD since otherwise
132*5c2921b0SApple OSS Distributions * we'll just die when marking ourself invalid.
133*5c2921b0SApple OSS Distributions */
134*5c2921b0SApple OSS Distributions
135*5c2921b0SApple OSS Distributions if ((status & CS_KILL) == 0) {
136*5c2921b0SApple OSS Distributions rcent = csops(pid, CS_OPS_MARKINVALID, NULL, 0);
137*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ZERO(rcent, 0, "Setting CS OPs mark proc invalid");
138*5c2921b0SApple OSS Distributions
139*5c2921b0SApple OSS Distributions status = CS_ENFORCEMENT;
140*5c2921b0SApple OSS Distributions rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
141*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(rcent, -1, "Managed to set flags on an INVALID proc");
142*5c2921b0SApple OSS Distributions
143*5c2921b0SApple OSS Distributions rcent = get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB);
144*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(rcent, 1, "Got entitlements while invalid");
145*5c2921b0SApple OSS Distributions
146*5c2921b0SApple OSS Distributions rcent = get_blob(pid, CS_OPS_IDENTITY);
147*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(rcent, 1, "Getting CS OPS identity");
148*5c2921b0SApple OSS Distributions
149*5c2921b0SApple OSS Distributions rcent = get_blob(0, CS_OPS_IDENTITY);
150*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(rcent, 1, "Getting CS OPS identity");
151*5c2921b0SApple OSS Distributions
152*5c2921b0SApple OSS Distributions rcent = get_blob(0, CS_OPS_BLOB);
153*5c2921b0SApple OSS Distributions T_ASSERT_POSIX_ERROR(rcent, 1, "Geting CS OPS blob");
154*5c2921b0SApple OSS Distributions }
155*5c2921b0SApple OSS Distributions }
156