Loading...
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
5 *
6 * Author: Roberto Sassu <roberto.sassu@huawei.com>
7 */
8
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <endian.h>
14#include <limits.h>
15#include <sys/stat.h>
16#include <sys/wait.h>
17#include <sys/mman.h>
18#include <linux/keyctl.h>
19#include <sys/xattr.h>
20#include <linux/fsverity.h>
21#include <test_progs.h>
22
23#include "test_verify_pkcs7_sig.skel.h"
24#include "test_sig_in_xattr.skel.h"
25
26#define MAX_DATA_SIZE (1024 * 1024)
27#define MAX_SIG_SIZE 1024
28
29#define VERIFY_USE_SECONDARY_KEYRING (1UL)
30#define VERIFY_USE_PLATFORM_KEYRING (2UL)
31
32#ifndef SHA256_DIGEST_SIZE
33#define SHA256_DIGEST_SIZE 32
34#endif
35
36/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
37#define MODULE_SIG_STRING "~Module signature appended~\n"
38
39/*
40 * Module signature information block.
41 *
42 * The constituents of the signature section are, in order:
43 *
44 * - Signer's name
45 * - Key identifier
46 * - Signature data
47 * - Information block
48 */
49struct module_signature {
50 __u8 algo; /* Public-key crypto algorithm [0] */
51 __u8 hash; /* Digest algorithm [0] */
52 __u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
53 __u8 signer_len; /* Length of signer's name [0] */
54 __u8 key_id_len; /* Length of key identifier [0] */
55 __u8 __pad[3];
56 __be32 sig_len; /* Length of signature data */
57};
58
59struct data {
60 __u8 data[MAX_DATA_SIZE];
61 __u32 data_len;
62 __u8 sig[MAX_SIG_SIZE];
63 __u32 sig_len;
64};
65
66static bool kfunc_not_supported;
67
68static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt,
69 va_list args)
70{
71 if (level == LIBBPF_WARN)
72 vprintf(fmt, args);
73
74 if (strcmp(fmt, "libbpf: extern (func ksym) '%s': not found in kernel or module BTFs\n"))
75 return 0;
76
77 if (strcmp(va_arg(args, char *), "bpf_verify_pkcs7_signature"))
78 return 0;
79
80 kfunc_not_supported = true;
81 return 0;
82}
83
84static int _run_setup_process(const char *setup_dir, const char *cmd)
85{
86 int child_pid, child_status;
87
88 child_pid = fork();
89 if (child_pid == 0) {
90 execlp("./verify_sig_setup.sh", "./verify_sig_setup.sh", cmd,
91 setup_dir, NULL);
92 exit(errno);
93
94 } else if (child_pid > 0) {
95 waitpid(child_pid, &child_status, 0);
96 return WEXITSTATUS(child_status);
97 }
98
99 return -EINVAL;
100}
101
102static int populate_data_item_str(const char *tmp_dir, struct data *data_item)
103{
104 struct stat st;
105 char data_template[] = "/tmp/dataXXXXXX";
106 char path[PATH_MAX];
107 int ret, fd, child_status, child_pid;
108
109 data_item->data_len = 4;
110 memcpy(data_item->data, "test", data_item->data_len);
111
112 fd = mkstemp(data_template);
113 if (fd == -1)
114 return -errno;
115
116 ret = write(fd, data_item->data, data_item->data_len);
117
118 close(fd);
119
120 if (ret != data_item->data_len) {
121 ret = -EIO;
122 goto out;
123 }
124
125 child_pid = fork();
126
127 if (child_pid == -1) {
128 ret = -errno;
129 goto out;
130 }
131
132 if (child_pid == 0) {
133 snprintf(path, sizeof(path), "%s/signing_key.pem", tmp_dir);
134
135 return execlp("./sign-file", "./sign-file", "-d", "sha256",
136 path, path, data_template, NULL);
137 }
138
139 waitpid(child_pid, &child_status, 0);
140
141 ret = WEXITSTATUS(child_status);
142 if (ret)
143 goto out;
144
145 snprintf(path, sizeof(path), "%s.p7s", data_template);
146
147 ret = stat(path, &st);
148 if (ret == -1) {
149 ret = -errno;
150 goto out;
151 }
152
153 if (st.st_size > sizeof(data_item->sig)) {
154 ret = -EINVAL;
155 goto out_sig;
156 }
157
158 data_item->sig_len = st.st_size;
159
160 fd = open(path, O_RDONLY);
161 if (fd == -1) {
162 ret = -errno;
163 goto out_sig;
164 }
165
166 ret = read(fd, data_item->sig, data_item->sig_len);
167
168 close(fd);
169
170 if (ret != data_item->sig_len) {
171 ret = -EIO;
172 goto out_sig;
173 }
174
175 ret = 0;
176out_sig:
177 unlink(path);
178out:
179 unlink(data_template);
180 return ret;
181}
182
183static int populate_data_item_mod(struct data *data_item)
184{
185 char mod_path[PATH_MAX], *mod_path_ptr;
186 struct stat st;
187 void *mod;
188 FILE *fp;
189 struct module_signature ms;
190 int ret, fd, modlen, marker_len, sig_len;
191
192 data_item->data_len = 0;
193
194 if (stat("/lib/modules", &st) == -1)
195 return 0;
196
197 /* Requires CONFIG_TCP_CONG_BIC=m. */
198 fp = popen("find /lib/modules/$(uname -r) -name tcp_bic.ko", "r");
199 if (!fp)
200 return 0;
201
202 mod_path_ptr = fgets(mod_path, sizeof(mod_path), fp);
203 pclose(fp);
204
205 if (!mod_path_ptr)
206 return 0;
207
208 mod_path_ptr = strchr(mod_path, '\n');
209 if (!mod_path_ptr)
210 return 0;
211
212 *mod_path_ptr = '\0';
213
214 if (stat(mod_path, &st) == -1)
215 return 0;
216
217 modlen = st.st_size;
218 marker_len = sizeof(MODULE_SIG_STRING) - 1;
219
220 fd = open(mod_path, O_RDONLY);
221 if (fd == -1)
222 return -errno;
223
224 mod = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
225
226 close(fd);
227
228 if (mod == MAP_FAILED)
229 return -errno;
230
231 if (strncmp(mod + modlen - marker_len, MODULE_SIG_STRING, marker_len)) {
232 ret = -EINVAL;
233 goto out;
234 }
235
236 modlen -= marker_len;
237
238 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
239
240 sig_len = __be32_to_cpu(ms.sig_len);
241 modlen -= sig_len + sizeof(ms);
242
243 if (modlen > sizeof(data_item->data)) {
244 ret = -E2BIG;
245 goto out;
246 }
247
248 memcpy(data_item->data, mod, modlen);
249 data_item->data_len = modlen;
250
251 if (sig_len > sizeof(data_item->sig)) {
252 ret = -E2BIG;
253 goto out;
254 }
255
256 memcpy(data_item->sig, mod + modlen, sig_len);
257 data_item->sig_len = sig_len;
258 ret = 0;
259out:
260 munmap(mod, st.st_size);
261 return ret;
262}
263
264static void test_verify_pkcs7_sig_from_map(void)
265{
266 libbpf_print_fn_t old_print_cb;
267 char tmp_dir_template[] = "/tmp/verify_sigXXXXXX";
268 char *tmp_dir;
269 struct test_verify_pkcs7_sig *skel = NULL;
270 struct bpf_map *map;
271 struct data data;
272 int ret, zero = 0;
273
274 /* Trigger creation of session keyring. */
275 syscall(__NR_request_key, "keyring", "_uid.0", NULL,
276 KEY_SPEC_SESSION_KEYRING);
277
278 tmp_dir = mkdtemp(tmp_dir_template);
279 if (!ASSERT_OK_PTR(tmp_dir, "mkdtemp"))
280 return;
281
282 ret = _run_setup_process(tmp_dir, "setup");
283 if (!ASSERT_OK(ret, "_run_setup_process"))
284 goto close_prog;
285
286 skel = test_verify_pkcs7_sig__open();
287 if (!ASSERT_OK_PTR(skel, "test_verify_pkcs7_sig__open"))
288 goto close_prog;
289
290 old_print_cb = libbpf_set_print(libbpf_print_cb);
291 ret = test_verify_pkcs7_sig__load(skel);
292 libbpf_set_print(old_print_cb);
293
294 if (ret < 0 && kfunc_not_supported) {
295 printf(
296 "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n",
297 __func__);
298 test__skip();
299 goto close_prog;
300 }
301
302 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__load"))
303 goto close_prog;
304
305 ret = test_verify_pkcs7_sig__attach(skel);
306 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__attach"))
307 goto close_prog;
308
309 map = bpf_object__find_map_by_name(skel->obj, "data_input");
310 if (!ASSERT_OK_PTR(map, "data_input not found"))
311 goto close_prog;
312
313 skel->bss->monitored_pid = getpid();
314
315 /* Test without data and signature. */
316 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING;
317
318 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
319 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
320 goto close_prog;
321
322 /* Test successful signature verification with session keyring. */
323 ret = populate_data_item_str(tmp_dir, &data);
324 if (!ASSERT_OK(ret, "populate_data_item_str"))
325 goto close_prog;
326
327 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
328 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
329 goto close_prog;
330
331 /* Test successful signature verification with testing keyring. */
332 skel->bss->user_keyring_serial = syscall(__NR_request_key, "keyring",
333 "ebpf_testing_keyring", NULL,
334 KEY_SPEC_SESSION_KEYRING);
335
336 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
337 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
338 goto close_prog;
339
340 /*
341 * Ensure key_task_permission() is called and rejects the keyring
342 * (no Search permission).
343 */
344 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial,
345 0x37373737);
346
347 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
348 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
349 goto close_prog;
350
351 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial,
352 0x3f3f3f3f);
353
354 /*
355 * Ensure key_validate() is called and rejects the keyring (key expired)
356 */
357 syscall(__NR_keyctl, KEYCTL_SET_TIMEOUT,
358 skel->bss->user_keyring_serial, 1);
359 sleep(1);
360
361 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
362 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
363 goto close_prog;
364
365 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING;
366
367 /* Test with corrupted data (signature verification should fail). */
368 data.data[0] = 'a';
369 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
370 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
371 goto close_prog;
372
373 ret = populate_data_item_mod(&data);
374 if (!ASSERT_OK(ret, "populate_data_item_mod"))
375 goto close_prog;
376
377 /* Test signature verification with system keyrings. */
378 if (data.data_len) {
379 skel->bss->user_keyring_serial = 0;
380 skel->bss->system_keyring_id = 0;
381
382 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
383 BPF_ANY);
384 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
385 goto close_prog;
386
387 skel->bss->system_keyring_id = VERIFY_USE_SECONDARY_KEYRING;
388
389 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
390 BPF_ANY);
391 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
392 goto close_prog;
393
394 skel->bss->system_keyring_id = VERIFY_USE_PLATFORM_KEYRING;
395
396 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
397 BPF_ANY);
398 ASSERT_LT(ret, 0, "bpf_map_update_elem data_input");
399 }
400
401close_prog:
402 _run_setup_process(tmp_dir, "cleanup");
403
404 if (!skel)
405 return;
406
407 skel->bss->monitored_pid = 0;
408 test_verify_pkcs7_sig__destroy(skel);
409}
410
411static int get_signature_size(const char *sig_path)
412{
413 struct stat st;
414
415 if (stat(sig_path, &st) == -1)
416 return -1;
417
418 return st.st_size;
419}
420
421static int add_signature_to_xattr(const char *data_path, const char *sig_path)
422{
423 char sig[MAX_SIG_SIZE] = {0};
424 int fd, size, ret;
425
426 if (sig_path) {
427 fd = open(sig_path, O_RDONLY);
428 if (fd < 0)
429 return -1;
430
431 size = read(fd, sig, MAX_SIG_SIZE);
432 close(fd);
433 if (size <= 0)
434 return -1;
435 } else {
436 /* no sig_path, just write 32 bytes of zeros */
437 size = 32;
438 }
439 ret = setxattr(data_path, "user.sig", sig, size, 0);
440 if (!ASSERT_OK(ret, "setxattr"))
441 return -1;
442
443 return 0;
444}
445
446static int test_open_file(struct test_sig_in_xattr *skel, char *data_path,
447 pid_t pid, bool should_success, char *name)
448{
449 int ret;
450
451 skel->bss->monitored_pid = pid;
452 ret = open(data_path, O_RDONLY);
453 close(ret);
454 skel->bss->monitored_pid = 0;
455
456 if (should_success) {
457 if (!ASSERT_GE(ret, 0, name))
458 return -1;
459 } else {
460 if (!ASSERT_LT(ret, 0, name))
461 return -1;
462 }
463 return 0;
464}
465
466static void test_pkcs7_sig_fsverity(void)
467{
468 char data_path[PATH_MAX];
469 char sig_path[PATH_MAX];
470 char tmp_dir_template[] = "/tmp/verify_sigXXXXXX";
471 char *tmp_dir;
472 struct test_sig_in_xattr *skel = NULL;
473 pid_t pid;
474 int ret;
475
476 tmp_dir = mkdtemp(tmp_dir_template);
477 if (!ASSERT_OK_PTR(tmp_dir, "mkdtemp"))
478 return;
479
480 snprintf(data_path, PATH_MAX, "%s/data-file", tmp_dir);
481 snprintf(sig_path, PATH_MAX, "%s/sig-file", tmp_dir);
482
483 ret = _run_setup_process(tmp_dir, "setup");
484 if (!ASSERT_OK(ret, "_run_setup_process"))
485 goto out;
486
487 ret = _run_setup_process(tmp_dir, "fsverity-create-sign");
488
489 if (ret) {
490 printf("%s: SKIP: fsverity [sign|enable] doesn't work.\n"
491 "To run this test, try enable CONFIG_FS_VERITY and enable FSVerity for the filesystem.\n",
492 __func__);
493 test__skip();
494 goto out;
495 }
496
497 skel = test_sig_in_xattr__open();
498 if (!ASSERT_OK_PTR(skel, "test_sig_in_xattr__open"))
499 goto out;
500 ret = get_signature_size(sig_path);
501 if (!ASSERT_GT(ret, 0, "get_signature_size"))
502 goto out;
503 skel->bss->sig_size = ret;
504 skel->bss->user_keyring_serial = syscall(__NR_request_key, "keyring",
505 "ebpf_testing_keyring", NULL,
506 KEY_SPEC_SESSION_KEYRING);
507 memcpy(skel->bss->digest, "FSVerity", 8);
508
509 ret = test_sig_in_xattr__load(skel);
510 if (!ASSERT_OK(ret, "test_sig_in_xattr__load"))
511 goto out;
512
513 ret = test_sig_in_xattr__attach(skel);
514 if (!ASSERT_OK(ret, "test_sig_in_xattr__attach"))
515 goto out;
516
517 pid = getpid();
518
519 /* Case 1: fsverity is not enabled, open should succeed */
520 if (test_open_file(skel, data_path, pid, true, "open_1"))
521 goto out;
522
523 /* Case 2: fsverity is enabled, xattr is missing, open should
524 * fail
525 */
526 ret = _run_setup_process(tmp_dir, "fsverity-enable");
527 if (!ASSERT_OK(ret, "fsverity-enable"))
528 goto out;
529 if (test_open_file(skel, data_path, pid, false, "open_2"))
530 goto out;
531
532 /* Case 3: fsverity is enabled, xattr has valid signature, open
533 * should succeed
534 */
535 ret = add_signature_to_xattr(data_path, sig_path);
536 if (!ASSERT_OK(ret, "add_signature_to_xattr_1"))
537 goto out;
538
539 if (test_open_file(skel, data_path, pid, true, "open_3"))
540 goto out;
541
542 /* Case 4: fsverity is enabled, xattr has invalid signature, open
543 * should fail
544 */
545 ret = add_signature_to_xattr(data_path, NULL);
546 if (!ASSERT_OK(ret, "add_signature_to_xattr_2"))
547 goto out;
548 test_open_file(skel, data_path, pid, false, "open_4");
549
550out:
551 _run_setup_process(tmp_dir, "cleanup");
552 if (!skel)
553 return;
554
555 skel->bss->monitored_pid = 0;
556 test_sig_in_xattr__destroy(skel);
557}
558
559void test_verify_pkcs7_sig(void)
560{
561 if (test__start_subtest("pkcs7_sig_from_map"))
562 test_verify_pkcs7_sig_from_map();
563 if (test__start_subtest("pkcs7_sig_fsverity"))
564 test_pkcs7_sig_fsverity();
565}
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
5 *
6 * Author: Roberto Sassu <roberto.sassu@huawei.com>
7 */
8
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <endian.h>
14#include <limits.h>
15#include <sys/stat.h>
16#include <sys/wait.h>
17#include <sys/mman.h>
18#include <linux/keyctl.h>
19#include <test_progs.h>
20
21#include "test_verify_pkcs7_sig.skel.h"
22
23#define MAX_DATA_SIZE (1024 * 1024)
24#define MAX_SIG_SIZE 1024
25
26#define VERIFY_USE_SECONDARY_KEYRING (1UL)
27#define VERIFY_USE_PLATFORM_KEYRING (2UL)
28
29/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
30#define MODULE_SIG_STRING "~Module signature appended~\n"
31
32/*
33 * Module signature information block.
34 *
35 * The constituents of the signature section are, in order:
36 *
37 * - Signer's name
38 * - Key identifier
39 * - Signature data
40 * - Information block
41 */
42struct module_signature {
43 __u8 algo; /* Public-key crypto algorithm [0] */
44 __u8 hash; /* Digest algorithm [0] */
45 __u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
46 __u8 signer_len; /* Length of signer's name [0] */
47 __u8 key_id_len; /* Length of key identifier [0] */
48 __u8 __pad[3];
49 __be32 sig_len; /* Length of signature data */
50};
51
52struct data {
53 __u8 data[MAX_DATA_SIZE];
54 __u32 data_len;
55 __u8 sig[MAX_SIG_SIZE];
56 __u32 sig_len;
57};
58
59static bool kfunc_not_supported;
60
61static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt,
62 va_list args)
63{
64 if (strcmp(fmt, "libbpf: extern (func ksym) '%s': not found in kernel or module BTFs\n"))
65 return 0;
66
67 if (strcmp(va_arg(args, char *), "bpf_verify_pkcs7_signature"))
68 return 0;
69
70 kfunc_not_supported = true;
71 return 0;
72}
73
74static int _run_setup_process(const char *setup_dir, const char *cmd)
75{
76 int child_pid, child_status;
77
78 child_pid = fork();
79 if (child_pid == 0) {
80 execlp("./verify_sig_setup.sh", "./verify_sig_setup.sh", cmd,
81 setup_dir, NULL);
82 exit(errno);
83
84 } else if (child_pid > 0) {
85 waitpid(child_pid, &child_status, 0);
86 return WEXITSTATUS(child_status);
87 }
88
89 return -EINVAL;
90}
91
92static int populate_data_item_str(const char *tmp_dir, struct data *data_item)
93{
94 struct stat st;
95 char data_template[] = "/tmp/dataXXXXXX";
96 char path[PATH_MAX];
97 int ret, fd, child_status, child_pid;
98
99 data_item->data_len = 4;
100 memcpy(data_item->data, "test", data_item->data_len);
101
102 fd = mkstemp(data_template);
103 if (fd == -1)
104 return -errno;
105
106 ret = write(fd, data_item->data, data_item->data_len);
107
108 close(fd);
109
110 if (ret != data_item->data_len) {
111 ret = -EIO;
112 goto out;
113 }
114
115 child_pid = fork();
116
117 if (child_pid == -1) {
118 ret = -errno;
119 goto out;
120 }
121
122 if (child_pid == 0) {
123 snprintf(path, sizeof(path), "%s/signing_key.pem", tmp_dir);
124
125 return execlp("./sign-file", "./sign-file", "-d", "sha256",
126 path, path, data_template, NULL);
127 }
128
129 waitpid(child_pid, &child_status, 0);
130
131 ret = WEXITSTATUS(child_status);
132 if (ret)
133 goto out;
134
135 snprintf(path, sizeof(path), "%s.p7s", data_template);
136
137 ret = stat(path, &st);
138 if (ret == -1) {
139 ret = -errno;
140 goto out;
141 }
142
143 if (st.st_size > sizeof(data_item->sig)) {
144 ret = -EINVAL;
145 goto out_sig;
146 }
147
148 data_item->sig_len = st.st_size;
149
150 fd = open(path, O_RDONLY);
151 if (fd == -1) {
152 ret = -errno;
153 goto out_sig;
154 }
155
156 ret = read(fd, data_item->sig, data_item->sig_len);
157
158 close(fd);
159
160 if (ret != data_item->sig_len) {
161 ret = -EIO;
162 goto out_sig;
163 }
164
165 ret = 0;
166out_sig:
167 unlink(path);
168out:
169 unlink(data_template);
170 return ret;
171}
172
173static int populate_data_item_mod(struct data *data_item)
174{
175 char mod_path[PATH_MAX], *mod_path_ptr;
176 struct stat st;
177 void *mod;
178 FILE *fp;
179 struct module_signature ms;
180 int ret, fd, modlen, marker_len, sig_len;
181
182 data_item->data_len = 0;
183
184 if (stat("/lib/modules", &st) == -1)
185 return 0;
186
187 /* Requires CONFIG_TCP_CONG_BIC=m. */
188 fp = popen("find /lib/modules/$(uname -r) -name tcp_bic.ko", "r");
189 if (!fp)
190 return 0;
191
192 mod_path_ptr = fgets(mod_path, sizeof(mod_path), fp);
193 pclose(fp);
194
195 if (!mod_path_ptr)
196 return 0;
197
198 mod_path_ptr = strchr(mod_path, '\n');
199 if (!mod_path_ptr)
200 return 0;
201
202 *mod_path_ptr = '\0';
203
204 if (stat(mod_path, &st) == -1)
205 return 0;
206
207 modlen = st.st_size;
208 marker_len = sizeof(MODULE_SIG_STRING) - 1;
209
210 fd = open(mod_path, O_RDONLY);
211 if (fd == -1)
212 return -errno;
213
214 mod = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
215
216 close(fd);
217
218 if (mod == MAP_FAILED)
219 return -errno;
220
221 if (strncmp(mod + modlen - marker_len, MODULE_SIG_STRING, marker_len)) {
222 ret = -EINVAL;
223 goto out;
224 }
225
226 modlen -= marker_len;
227
228 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
229
230 sig_len = __be32_to_cpu(ms.sig_len);
231 modlen -= sig_len + sizeof(ms);
232
233 if (modlen > sizeof(data_item->data)) {
234 ret = -E2BIG;
235 goto out;
236 }
237
238 memcpy(data_item->data, mod, modlen);
239 data_item->data_len = modlen;
240
241 if (sig_len > sizeof(data_item->sig)) {
242 ret = -E2BIG;
243 goto out;
244 }
245
246 memcpy(data_item->sig, mod + modlen, sig_len);
247 data_item->sig_len = sig_len;
248 ret = 0;
249out:
250 munmap(mod, st.st_size);
251 return ret;
252}
253
254void test_verify_pkcs7_sig(void)
255{
256 libbpf_print_fn_t old_print_cb;
257 char tmp_dir_template[] = "/tmp/verify_sigXXXXXX";
258 char *tmp_dir;
259 struct test_verify_pkcs7_sig *skel = NULL;
260 struct bpf_map *map;
261 struct data data;
262 int ret, zero = 0;
263
264 /* Trigger creation of session keyring. */
265 syscall(__NR_request_key, "keyring", "_uid.0", NULL,
266 KEY_SPEC_SESSION_KEYRING);
267
268 tmp_dir = mkdtemp(tmp_dir_template);
269 if (!ASSERT_OK_PTR(tmp_dir, "mkdtemp"))
270 return;
271
272 ret = _run_setup_process(tmp_dir, "setup");
273 if (!ASSERT_OK(ret, "_run_setup_process"))
274 goto close_prog;
275
276 skel = test_verify_pkcs7_sig__open();
277 if (!ASSERT_OK_PTR(skel, "test_verify_pkcs7_sig__open"))
278 goto close_prog;
279
280 old_print_cb = libbpf_set_print(libbpf_print_cb);
281 ret = test_verify_pkcs7_sig__load(skel);
282 libbpf_set_print(old_print_cb);
283
284 if (ret < 0 && kfunc_not_supported) {
285 printf(
286 "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n",
287 __func__);
288 test__skip();
289 goto close_prog;
290 }
291
292 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__load"))
293 goto close_prog;
294
295 ret = test_verify_pkcs7_sig__attach(skel);
296 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__attach"))
297 goto close_prog;
298
299 map = bpf_object__find_map_by_name(skel->obj, "data_input");
300 if (!ASSERT_OK_PTR(map, "data_input not found"))
301 goto close_prog;
302
303 skel->bss->monitored_pid = getpid();
304
305 /* Test without data and signature. */
306 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING;
307
308 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
309 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
310 goto close_prog;
311
312 /* Test successful signature verification with session keyring. */
313 ret = populate_data_item_str(tmp_dir, &data);
314 if (!ASSERT_OK(ret, "populate_data_item_str"))
315 goto close_prog;
316
317 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
318 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
319 goto close_prog;
320
321 /* Test successful signature verification with testing keyring. */
322 skel->bss->user_keyring_serial = syscall(__NR_request_key, "keyring",
323 "ebpf_testing_keyring", NULL,
324 KEY_SPEC_SESSION_KEYRING);
325
326 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
327 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
328 goto close_prog;
329
330 /*
331 * Ensure key_task_permission() is called and rejects the keyring
332 * (no Search permission).
333 */
334 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial,
335 0x37373737);
336
337 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
338 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
339 goto close_prog;
340
341 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial,
342 0x3f3f3f3f);
343
344 /*
345 * Ensure key_validate() is called and rejects the keyring (key expired)
346 */
347 syscall(__NR_keyctl, KEYCTL_SET_TIMEOUT,
348 skel->bss->user_keyring_serial, 1);
349 sleep(1);
350
351 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
352 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
353 goto close_prog;
354
355 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING;
356
357 /* Test with corrupted data (signature verification should fail). */
358 data.data[0] = 'a';
359 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY);
360 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"))
361 goto close_prog;
362
363 ret = populate_data_item_mod(&data);
364 if (!ASSERT_OK(ret, "populate_data_item_mod"))
365 goto close_prog;
366
367 /* Test signature verification with system keyrings. */
368 if (data.data_len) {
369 skel->bss->user_keyring_serial = 0;
370 skel->bss->system_keyring_id = 0;
371
372 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
373 BPF_ANY);
374 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
375 goto close_prog;
376
377 skel->bss->system_keyring_id = VERIFY_USE_SECONDARY_KEYRING;
378
379 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
380 BPF_ANY);
381 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input"))
382 goto close_prog;
383
384 skel->bss->system_keyring_id = VERIFY_USE_PLATFORM_KEYRING;
385
386 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data,
387 BPF_ANY);
388 ASSERT_LT(ret, 0, "bpf_map_update_elem data_input");
389 }
390
391close_prog:
392 _run_setup_process(tmp_dir, "cleanup");
393
394 if (!skel)
395 return;
396
397 skel->bss->monitored_pid = 0;
398 test_verify_pkcs7_sig__destroy(skel);
399}