Linux Audio

Check our new training course

Loading...
v6.13.7
  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}
v6.2
  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}