1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4 */
5
6 #include <linux/slab.h>
7 #include <linux/types.h>
8 #include <linux/list.h>
9 #include <kunit/test.h>
10 #include "policy.h"
11 struct policy_case {
12 const char *const policy;
13 int errno;
14 const char *const desc;
15 };
16
17 static const struct policy_case policy_cases[] = {
18 {
19 "policy_name=allowall policy_version=0.0.0\n"
20 "DEFAULT action=ALLOW",
21 0,
22 "basic",
23 },
24 {
25 "policy_name=trailing_comment policy_version=152.0.0 #This is comment\n"
26 "DEFAULT action=ALLOW",
27 0,
28 "trailing comment",
29 },
30 {
31 "policy_name=allowallnewline policy_version=0.2.0\n"
32 "DEFAULT action=ALLOW\n"
33 "\n",
34 0,
35 "trailing newline",
36 },
37 {
38 "policy_name=carriagereturnlinefeed policy_version=0.0.1\n"
39 "DEFAULT action=ALLOW\n"
40 "\r\n",
41 0,
42 "clrf newline",
43 },
44 {
45 "policy_name=whitespace policy_version=0.0.0\n"
46 "DEFAULT\taction=ALLOW\n"
47 " \t DEFAULT \t op=EXECUTE action=DENY\n"
48 "op=EXECUTE boot_verified=TRUE action=ALLOW\n"
49 "# this is a\tcomment\t\t\t\t\n"
50 "DEFAULT \t op=KMODULE\t\t\t action=DENY\r\n"
51 "op=KMODULE boot_verified=TRUE action=ALLOW\n",
52 0,
53 "various whitespaces and nested default",
54 },
55 {
56 "policy_name=boot_verified policy_version=-1236.0.0\n"
57 "DEFAULT\taction=ALLOW\n",
58 -EINVAL,
59 "negative version",
60 },
61 {
62 "policy_name=$@!*&^%%\\:;{}() policy_version=0.0.0\n"
63 "DEFAULT action=ALLOW",
64 0,
65 "special characters",
66 },
67 {
68 "policy_name=test policy_version=999999.0.0\n"
69 "DEFAULT action=ALLOW",
70 -ERANGE,
71 "overflow version",
72 },
73 {
74 "policy_name=test policy_version=255.0\n"
75 "DEFAULT action=ALLOW",
76 -EBADMSG,
77 "incomplete version",
78 },
79 {
80 "policy_name=test policy_version=111.0.0.0\n"
81 "DEFAULT action=ALLOW",
82 -EBADMSG,
83 "extra version",
84 },
85 {
86 "",
87 -EBADMSG,
88 "0-length policy",
89 },
90 {
91 "policy_name=test\0policy_version=0.0.0\n"
92 "DEFAULT action=ALLOW",
93 -EBADMSG,
94 "random null in header",
95 },
96 {
97 "policy_name=test policy_version=0.0.0\n"
98 "\0DEFAULT action=ALLOW",
99 -EBADMSG,
100 "incomplete policy from NULL",
101 },
102 {
103 "policy_name=test policy_version=0.0.0\n"
104 "DEFAULT action=DENY\n\0"
105 "op=EXECUTE dmverity_signature=TRUE action=ALLOW\n",
106 0,
107 "NULL truncates policy",
108 },
109 {
110 "policy_name=test policy_version=0.0.0\n"
111 "DEFAULT action=ALLOW\n"
112 "op=EXECUTE dmverity_signature=abc action=ALLOW",
113 -EBADMSG,
114 "invalid property type",
115 },
116 {
117 "DEFAULT action=ALLOW",
118 -EBADMSG,
119 "missing policy header",
120 },
121 {
122 "policy_name=test policy_version=0.0.0\n",
123 -EBADMSG,
124 "missing default definition",
125 },
126 {
127 "policy_name=test policy_version=0.0.0\n"
128 "DEFAULT action=ALLOW\n"
129 "dmverity_signature=TRUE op=EXECUTE action=ALLOW",
130 -EBADMSG,
131 "invalid rule ordering"
132 },
133 {
134 "policy_name=test policy_version=0.0.0\n"
135 "DEFAULT action=ALLOW\n"
136 "action=ALLOW op=EXECUTE dmverity_signature=TRUE",
137 -EBADMSG,
138 "invalid rule ordering (2)",
139 },
140 {
141 "policy_name=test policy_version=0.0\n"
142 "DEFAULT action=ALLOW\n"
143 "op=EXECUTE dmverity_signature=TRUE action=ALLOW",
144 -EBADMSG,
145 "invalid version",
146 },
147 {
148 "policy_name=test policy_version=0.0.0\n"
149 "DEFAULT action=ALLOW\n"
150 "op=UNKNOWN dmverity_signature=TRUE action=ALLOW",
151 -EBADMSG,
152 "unknown operation",
153 },
154 {
155 "policy_name=asdvpolicy_version=0.0.0\n"
156 "DEFAULT action=ALLOW\n",
157 -EBADMSG,
158 "missing space after policy name",
159 },
160 {
161 "policy_name=test\xFF\xEF policy_version=0.0.0\n"
162 "DEFAULT action=ALLOW\n"
163 "op=EXECUTE dmverity_signature=TRUE action=ALLOW",
164 0,
165 "expanded ascii",
166 },
167 {
168 "policy_name=test\xFF\xEF policy_version=0.0.0\n"
169 "DEFAULT action=ALLOW\n"
170 "op=EXECUTE dmverity_roothash=GOOD_DOG action=ALLOW",
171 -EBADMSG,
172 "invalid property value (2)",
173 },
174 {
175 "policy_name=test policy_version=0.0.0\n"
176 "policy_name=test policy_version=0.1.0\n"
177 "DEFAULT action=ALLOW",
178 -EBADMSG,
179 "double header"
180 },
181 {
182 "policy_name=test policy_version=0.0.0\n"
183 "DEFAULT action=ALLOW\n"
184 "DEFAULT action=ALLOW\n",
185 -EBADMSG,
186 "double default"
187 },
188 {
189 "policy_name=test policy_version=0.0.0\n"
190 "DEFAULT action=ALLOW\n"
191 "DEFAULT op=EXECUTE action=DENY\n"
192 "DEFAULT op=EXECUTE action=ALLOW\n",
193 -EBADMSG,
194 "double operation default"
195 },
196 {
197 "policy_name=test policy_version=0.0.0\n"
198 "DEFAULT action=ALLOW\n"
199 "DEFAULT op=EXECUTE action=DEN\n",
200 -EBADMSG,
201 "invalid action value"
202 },
203 {
204 "policy_name=test policy_version=0.0.0\n"
205 "DEFAULT action=ALLOW\n"
206 "DEFAULT op=EXECUTE action\n",
207 -EBADMSG,
208 "invalid action value (2)"
209 },
210 {
211 "policy_name=test policy_version=0.0.0\n"
212 "DEFAULT action=ALLOW\n"
213 "UNKNOWN value=true\n",
214 -EBADMSG,
215 "unrecognized statement"
216 },
217 {
218 "policy_name=test policy_version=0.0.0\n"
219 "DEFAULT action=ALLOW\n"
220 "op=EXECUTE dmverity_roothash=1c0d7ee1f8343b7fbe418378e8eb22c061d7dec7 action=DENY\n",
221 -EBADMSG,
222 "old-style digest"
223 },
224 {
225 "policy_name=test policy_version=0.0.0\n"
226 "DEFAULT action=ALLOW\n"
227 "op=EXECUTE fsverity_digest=1c0d7ee1f8343b7fbe418378e8eb22c061d7dec7 action=DENY\n",
228 -EBADMSG,
229 "old-style digest"
230 }
231 };
232
pol_to_desc(const struct policy_case * c,char * desc)233 static void pol_to_desc(const struct policy_case *c, char *desc)
234 {
235 strscpy(desc, c->desc, KUNIT_PARAM_DESC_SIZE);
236 }
237
238 KUNIT_ARRAY_PARAM(ipe_policies, policy_cases, pol_to_desc);
239
240 /**
241 * ipe_parser_unsigned_test - Test the parser by passing unsigned policies.
242 * @test: Supplies a pointer to a kunit structure.
243 *
244 * This is called by the kunit harness. This test does not check the correctness
245 * of the policy, but ensures that errors are handled correctly.
246 */
ipe_parser_unsigned_test(struct kunit * test)247 static void ipe_parser_unsigned_test(struct kunit *test)
248 {
249 const struct policy_case *p = test->param_value;
250 struct ipe_policy *pol;
251
252 pol = ipe_new_policy(p->policy, strlen(p->policy), NULL, 0);
253
254 if (p->errno) {
255 KUNIT_EXPECT_EQ(test, PTR_ERR(pol), p->errno);
256 return;
257 }
258
259 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pol);
260 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, pol->parsed);
261 KUNIT_EXPECT_STREQ(test, pol->text, p->policy);
262 KUNIT_EXPECT_PTR_EQ(test, NULL, pol->pkcs7);
263 KUNIT_EXPECT_EQ(test, 0, pol->pkcs7len);
264
265 ipe_free_policy(pol);
266 }
267
268 /**
269 * ipe_parser_widestring_test - Ensure parser fail on a wide string policy.
270 * @test: Supplies a pointer to a kunit structure.
271 *
272 * This is called by the kunit harness.
273 */
ipe_parser_widestring_test(struct kunit * test)274 static void ipe_parser_widestring_test(struct kunit *test)
275 {
276 const unsigned short policy[] = L"policy_name=Test policy_version=0.0.0\n"
277 L"DEFAULT action=ALLOW";
278 struct ipe_policy *pol = NULL;
279
280 pol = ipe_new_policy((const char *)policy, (ARRAY_SIZE(policy) - 1) * 2, NULL, 0);
281 KUNIT_EXPECT_TRUE(test, IS_ERR_OR_NULL(pol));
282
283 ipe_free_policy(pol);
284 }
285
286 static struct kunit_case ipe_parser_test_cases[] = {
287 KUNIT_CASE_PARAM(ipe_parser_unsigned_test, ipe_policies_gen_params),
288 KUNIT_CASE(ipe_parser_widestring_test),
289 { }
290 };
291
292 static struct kunit_suite ipe_parser_test_suite = {
293 .name = "ipe-parser",
294 .test_cases = ipe_parser_test_cases,
295 };
296
297 kunit_test_suite(ipe_parser_test_suite);
298