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 (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 74 static 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 92 static 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; 166 out_sig: 167 unlink(path); 168 out: 169 unlink(data_template); 170 return ret; 171 } 172 173 static 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; 249 out: 250 munmap(mod, st.st_size); 251 return ret; 252 } 253 254 void 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 391 close_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 } 400