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 */ 42 struct 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 52 struct data { 53 __u8 data[MAX_DATA_SIZE]; 54 __u32 data_len; 55 __u8 sig[MAX_SIG_SIZE]; 56 __u32 sig_len; 57 }; 58 59 static bool kfunc_not_supported; 60 61 static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt, 62 va_list args) 63 { 64 if (level == LIBBPF_WARN) 65 vprintf(fmt, args); 66 67 if (strcmp(fmt, "libbpf: extern (func ksym) '%s': not found in kernel or module BTFs\n")) 68 return 0; 69 70 if (strcmp(va_arg(args, char *), "bpf_verify_pkcs7_signature")) 71 return 0; 72 73 kfunc_not_supported = true; 74 return 0; 75 } 76 77 static int _run_setup_process(const char *setup_dir, const char *cmd) 78 { 79 int child_pid, child_status; 80 81 child_pid = fork(); 82 if (child_pid == 0) { 83 execlp("./verify_sig_setup.sh", "./verify_sig_setup.sh", cmd, 84 setup_dir, NULL); 85 exit(errno); 86 87 } else if (child_pid > 0) { 88 waitpid(child_pid, &child_status, 0); 89 return WEXITSTATUS(child_status); 90 } 91 92 return -EINVAL; 93 } 94 95 static int populate_data_item_str(const char *tmp_dir, struct data *data_item) 96 { 97 struct stat st; 98 char data_template[] = "/tmp/dataXXXXXX"; 99 char path[PATH_MAX]; 100 int ret, fd, child_status, child_pid; 101 102 data_item->data_len = 4; 103 memcpy(data_item->data, "test", data_item->data_len); 104 105 fd = mkstemp(data_template); 106 if (fd == -1) 107 return -errno; 108 109 ret = write(fd, data_item->data, data_item->data_len); 110 111 close(fd); 112 113 if (ret != data_item->data_len) { 114 ret = -EIO; 115 goto out; 116 } 117 118 child_pid = fork(); 119 120 if (child_pid == -1) { 121 ret = -errno; 122 goto out; 123 } 124 125 if (child_pid == 0) { 126 snprintf(path, sizeof(path), "%s/signing_key.pem", tmp_dir); 127 128 return execlp("./sign-file", "./sign-file", "-d", "sha256", 129 path, path, data_template, NULL); 130 } 131 132 waitpid(child_pid, &child_status, 0); 133 134 ret = WEXITSTATUS(child_status); 135 if (ret) 136 goto out; 137 138 snprintf(path, sizeof(path), "%s.p7s", data_template); 139 140 ret = stat(path, &st); 141 if (ret == -1) { 142 ret = -errno; 143 goto out; 144 } 145 146 if (st.st_size > sizeof(data_item->sig)) { 147 ret = -EINVAL; 148 goto out_sig; 149 } 150 151 data_item->sig_len = st.st_size; 152 153 fd = open(path, O_RDONLY); 154 if (fd == -1) { 155 ret = -errno; 156 goto out_sig; 157 } 158 159 ret = read(fd, data_item->sig, data_item->sig_len); 160 161 close(fd); 162 163 if (ret != data_item->sig_len) { 164 ret = -EIO; 165 goto out_sig; 166 } 167 168 ret = 0; 169 out_sig: 170 unlink(path); 171 out: 172 unlink(data_template); 173 return ret; 174 } 175 176 static int populate_data_item_mod(struct data *data_item) 177 { 178 char mod_path[PATH_MAX], *mod_path_ptr; 179 struct stat st; 180 void *mod; 181 FILE *fp; 182 struct module_signature ms; 183 int ret, fd, modlen, marker_len, sig_len; 184 185 data_item->data_len = 0; 186 187 if (stat("/lib/modules", &st) == -1) 188 return 0; 189 190 /* Requires CONFIG_TCP_CONG_BIC=m. */ 191 fp = popen("find /lib/modules/$(uname -r) -name tcp_bic.ko", "r"); 192 if (!fp) 193 return 0; 194 195 mod_path_ptr = fgets(mod_path, sizeof(mod_path), fp); 196 pclose(fp); 197 198 if (!mod_path_ptr) 199 return 0; 200 201 mod_path_ptr = strchr(mod_path, '\n'); 202 if (!mod_path_ptr) 203 return 0; 204 205 *mod_path_ptr = '\0'; 206 207 if (stat(mod_path, &st) == -1) 208 return 0; 209 210 modlen = st.st_size; 211 marker_len = sizeof(MODULE_SIG_STRING) - 1; 212 213 fd = open(mod_path, O_RDONLY); 214 if (fd == -1) 215 return -errno; 216 217 mod = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 218 219 close(fd); 220 221 if (mod == MAP_FAILED) 222 return -errno; 223 224 if (strncmp(mod + modlen - marker_len, MODULE_SIG_STRING, marker_len)) { 225 ret = -EINVAL; 226 goto out; 227 } 228 229 modlen -= marker_len; 230 231 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 232 233 sig_len = __be32_to_cpu(ms.sig_len); 234 modlen -= sig_len + sizeof(ms); 235 236 if (modlen > sizeof(data_item->data)) { 237 ret = -E2BIG; 238 goto out; 239 } 240 241 memcpy(data_item->data, mod, modlen); 242 data_item->data_len = modlen; 243 244 if (sig_len > sizeof(data_item->sig)) { 245 ret = -E2BIG; 246 goto out; 247 } 248 249 memcpy(data_item->sig, mod + modlen, sig_len); 250 data_item->sig_len = sig_len; 251 ret = 0; 252 out: 253 munmap(mod, st.st_size); 254 return ret; 255 } 256 257 void test_verify_pkcs7_sig(void) 258 { 259 libbpf_print_fn_t old_print_cb; 260 char tmp_dir_template[] = "/tmp/verify_sigXXXXXX"; 261 char *tmp_dir; 262 struct test_verify_pkcs7_sig *skel = NULL; 263 struct bpf_map *map; 264 struct data data; 265 int ret, zero = 0; 266 267 /* Trigger creation of session keyring. */ 268 syscall(__NR_request_key, "keyring", "_uid.0", NULL, 269 KEY_SPEC_SESSION_KEYRING); 270 271 tmp_dir = mkdtemp(tmp_dir_template); 272 if (!ASSERT_OK_PTR(tmp_dir, "mkdtemp")) 273 return; 274 275 ret = _run_setup_process(tmp_dir, "setup"); 276 if (!ASSERT_OK(ret, "_run_setup_process")) 277 goto close_prog; 278 279 skel = test_verify_pkcs7_sig__open(); 280 if (!ASSERT_OK_PTR(skel, "test_verify_pkcs7_sig__open")) 281 goto close_prog; 282 283 old_print_cb = libbpf_set_print(libbpf_print_cb); 284 ret = test_verify_pkcs7_sig__load(skel); 285 libbpf_set_print(old_print_cb); 286 287 if (ret < 0 && kfunc_not_supported) { 288 printf( 289 "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n", 290 __func__); 291 test__skip(); 292 goto close_prog; 293 } 294 295 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__load")) 296 goto close_prog; 297 298 ret = test_verify_pkcs7_sig__attach(skel); 299 if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__attach")) 300 goto close_prog; 301 302 map = bpf_object__find_map_by_name(skel->obj, "data_input"); 303 if (!ASSERT_OK_PTR(map, "data_input not found")) 304 goto close_prog; 305 306 skel->bss->monitored_pid = getpid(); 307 308 /* Test without data and signature. */ 309 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING; 310 311 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 312 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input")) 313 goto close_prog; 314 315 /* Test successful signature verification with session keyring. */ 316 ret = populate_data_item_str(tmp_dir, &data); 317 if (!ASSERT_OK(ret, "populate_data_item_str")) 318 goto close_prog; 319 320 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 321 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input")) 322 goto close_prog; 323 324 /* Test successful signature verification with testing keyring. */ 325 skel->bss->user_keyring_serial = syscall(__NR_request_key, "keyring", 326 "ebpf_testing_keyring", NULL, 327 KEY_SPEC_SESSION_KEYRING); 328 329 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 330 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input")) 331 goto close_prog; 332 333 /* 334 * Ensure key_task_permission() is called and rejects the keyring 335 * (no Search permission). 336 */ 337 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial, 338 0x37373737); 339 340 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 341 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input")) 342 goto close_prog; 343 344 syscall(__NR_keyctl, KEYCTL_SETPERM, skel->bss->user_keyring_serial, 345 0x3f3f3f3f); 346 347 /* 348 * Ensure key_validate() is called and rejects the keyring (key expired) 349 */ 350 syscall(__NR_keyctl, KEYCTL_SET_TIMEOUT, 351 skel->bss->user_keyring_serial, 1); 352 sleep(1); 353 354 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 355 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input")) 356 goto close_prog; 357 358 skel->bss->user_keyring_serial = KEY_SPEC_SESSION_KEYRING; 359 360 /* Test with corrupted data (signature verification should fail). */ 361 data.data[0] = 'a'; 362 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, BPF_ANY); 363 if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input")) 364 goto close_prog; 365 366 ret = populate_data_item_mod(&data); 367 if (!ASSERT_OK(ret, "populate_data_item_mod")) 368 goto close_prog; 369 370 /* Test signature verification with system keyrings. */ 371 if (data.data_len) { 372 skel->bss->user_keyring_serial = 0; 373 skel->bss->system_keyring_id = 0; 374 375 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, 376 BPF_ANY); 377 if (!ASSERT_OK(ret, "bpf_map_update_elem data_input")) 378 goto close_prog; 379 380 skel->bss->system_keyring_id = VERIFY_USE_SECONDARY_KEYRING; 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_PLATFORM_KEYRING; 388 389 ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &data, 390 BPF_ANY); 391 ASSERT_LT(ret, 0, "bpf_map_update_elem data_input"); 392 } 393 394 close_prog: 395 _run_setup_process(tmp_dir, "cleanup"); 396 397 if (!skel) 398 return; 399 400 skel->bss->monitored_pid = 0; 401 test_verify_pkcs7_sig__destroy(skel); 402 } 403