18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (C) 2020 ARM Limited 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#define _GNU_SOURCE 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <sys/auxv.h> 78c2ecf20Sopenharmony_ci#include <sys/types.h> 88c2ecf20Sopenharmony_ci#include <sys/wait.h> 98c2ecf20Sopenharmony_ci#include <signal.h> 108c2ecf20Sopenharmony_ci#include <setjmp.h> 118c2ecf20Sopenharmony_ci#include <sched.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "../../kselftest_harness.h" 148c2ecf20Sopenharmony_ci#include "helper.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define PAC_COLLISION_ATTEMPTS 10 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * The kernel sets TBID by default. So bits 55 and above should remain 198c2ecf20Sopenharmony_ci * untouched no matter what. 208c2ecf20Sopenharmony_ci * The VA space size is 48 bits. Bigger is opt-in. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci#define PAC_MASK (~0xff80ffffffffffff) 238c2ecf20Sopenharmony_ci#define ARBITRARY_VALUE (0x1234) 248c2ecf20Sopenharmony_ci#define ASSERT_PAUTH_ENABLED() \ 258c2ecf20Sopenharmony_cido { \ 268c2ecf20Sopenharmony_ci unsigned long hwcaps = getauxval(AT_HWCAP); \ 278c2ecf20Sopenharmony_ci /* data key instructions are not in NOP space. This prevents a SIGILL */ \ 288c2ecf20Sopenharmony_ci if (!(hwcaps & HWCAP_PACA)) \ 298c2ecf20Sopenharmony_ci SKIP(return, "PAUTH not enabled"); \ 308c2ecf20Sopenharmony_ci} while (0) 318c2ecf20Sopenharmony_ci#define ASSERT_GENERIC_PAUTH_ENABLED() \ 328c2ecf20Sopenharmony_cido { \ 338c2ecf20Sopenharmony_ci unsigned long hwcaps = getauxval(AT_HWCAP); \ 348c2ecf20Sopenharmony_ci /* generic key instructions are not in NOP space. This prevents a SIGILL */ \ 358c2ecf20Sopenharmony_ci if (!(hwcaps & HWCAP_PACG)) \ 368c2ecf20Sopenharmony_ci SKIP(return, "Generic PAUTH not enabled"); \ 378c2ecf20Sopenharmony_ci} while (0) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_civoid sign_specific(struct signatures *sign, size_t val) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci sign->keyia = keyia_sign(val); 428c2ecf20Sopenharmony_ci sign->keyib = keyib_sign(val); 438c2ecf20Sopenharmony_ci sign->keyda = keyda_sign(val); 448c2ecf20Sopenharmony_ci sign->keydb = keydb_sign(val); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_civoid sign_all(struct signatures *sign, size_t val) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci sign->keyia = keyia_sign(val); 508c2ecf20Sopenharmony_ci sign->keyib = keyib_sign(val); 518c2ecf20Sopenharmony_ci sign->keyda = keyda_sign(val); 528c2ecf20Sopenharmony_ci sign->keydb = keydb_sign(val); 538c2ecf20Sopenharmony_ci sign->keyg = keyg_sign(val); 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint n_same(struct signatures *old, struct signatures *new, int nkeys) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int res = 0; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci res += old->keyia == new->keyia; 618c2ecf20Sopenharmony_ci res += old->keyib == new->keyib; 628c2ecf20Sopenharmony_ci res += old->keyda == new->keyda; 638c2ecf20Sopenharmony_ci res += old->keydb == new->keydb; 648c2ecf20Sopenharmony_ci if (nkeys == NKEYS) 658c2ecf20Sopenharmony_ci res += old->keyg == new->keyg; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return res; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciint n_same_single_set(struct signatures *sign, int nkeys) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci size_t vals[nkeys]; 738c2ecf20Sopenharmony_ci int same = 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci vals[0] = sign->keyia & PAC_MASK; 768c2ecf20Sopenharmony_ci vals[1] = sign->keyib & PAC_MASK; 778c2ecf20Sopenharmony_ci vals[2] = sign->keyda & PAC_MASK; 788c2ecf20Sopenharmony_ci vals[3] = sign->keydb & PAC_MASK; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (nkeys >= 4) 818c2ecf20Sopenharmony_ci vals[4] = sign->keyg & PAC_MASK; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci for (int i = 0; i < nkeys - 1; i++) { 848c2ecf20Sopenharmony_ci for (int j = i + 1; j < nkeys; j++) { 858c2ecf20Sopenharmony_ci if (vals[i] == vals[j]) 868c2ecf20Sopenharmony_ci same += 1; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci return same; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciint exec_sign_all(struct signatures *signed_vals, size_t val) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci int new_stdin[2]; 958c2ecf20Sopenharmony_ci int new_stdout[2]; 968c2ecf20Sopenharmony_ci int status; 978c2ecf20Sopenharmony_ci int i; 988c2ecf20Sopenharmony_ci ssize_t ret; 998c2ecf20Sopenharmony_ci pid_t pid; 1008c2ecf20Sopenharmony_ci cpu_set_t mask; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci ret = pipe(new_stdin); 1038c2ecf20Sopenharmony_ci if (ret == -1) { 1048c2ecf20Sopenharmony_ci perror("pipe returned error"); 1058c2ecf20Sopenharmony_ci return -1; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci ret = pipe(new_stdout); 1098c2ecf20Sopenharmony_ci if (ret == -1) { 1108c2ecf20Sopenharmony_ci perror("pipe returned error"); 1118c2ecf20Sopenharmony_ci return -1; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* 1158c2ecf20Sopenharmony_ci * pin this process and all its children to a single CPU, so it can also 1168c2ecf20Sopenharmony_ci * guarantee a context switch with its child 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci sched_getaffinity(0, sizeof(mask), &mask); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(cpu_set_t); i++) 1218c2ecf20Sopenharmony_ci if (CPU_ISSET(i, &mask)) 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci CPU_ZERO(&mask); 1258c2ecf20Sopenharmony_ci CPU_SET(i, &mask); 1268c2ecf20Sopenharmony_ci sched_setaffinity(0, sizeof(mask), &mask); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci pid = fork(); 1298c2ecf20Sopenharmony_ci // child 1308c2ecf20Sopenharmony_ci if (pid == 0) { 1318c2ecf20Sopenharmony_ci dup2(new_stdin[0], STDIN_FILENO); 1328c2ecf20Sopenharmony_ci if (ret == -1) { 1338c2ecf20Sopenharmony_ci perror("dup2 returned error"); 1348c2ecf20Sopenharmony_ci exit(1); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci dup2(new_stdout[1], STDOUT_FILENO); 1388c2ecf20Sopenharmony_ci if (ret == -1) { 1398c2ecf20Sopenharmony_ci perror("dup2 returned error"); 1408c2ecf20Sopenharmony_ci exit(1); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci close(new_stdin[0]); 1448c2ecf20Sopenharmony_ci close(new_stdin[1]); 1458c2ecf20Sopenharmony_ci close(new_stdout[0]); 1468c2ecf20Sopenharmony_ci close(new_stdout[1]); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci ret = execl("exec_target", "exec_target", (char *)NULL); 1498c2ecf20Sopenharmony_ci if (ret == -1) { 1508c2ecf20Sopenharmony_ci perror("exec returned error"); 1518c2ecf20Sopenharmony_ci exit(1); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci close(new_stdin[0]); 1568c2ecf20Sopenharmony_ci close(new_stdout[1]); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci ret = write(new_stdin[1], &val, sizeof(size_t)); 1598c2ecf20Sopenharmony_ci if (ret == -1) { 1608c2ecf20Sopenharmony_ci perror("write returned error"); 1618c2ecf20Sopenharmony_ci return -1; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * wait for the worker to finish, so that read() reads all data 1668c2ecf20Sopenharmony_ci * will also context switch with worker so that this function can be used 1678c2ecf20Sopenharmony_ci * for context switch tests 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci waitpid(pid, &status, 0); 1708c2ecf20Sopenharmony_ci if (WIFEXITED(status) == 0) { 1718c2ecf20Sopenharmony_ci fprintf(stderr, "worker exited unexpectedly\n"); 1728c2ecf20Sopenharmony_ci return -1; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci if (WEXITSTATUS(status) != 0) { 1758c2ecf20Sopenharmony_ci fprintf(stderr, "worker exited with error\n"); 1768c2ecf20Sopenharmony_ci return -1; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci ret = read(new_stdout[0], signed_vals, sizeof(struct signatures)); 1808c2ecf20Sopenharmony_ci if (ret == -1) { 1818c2ecf20Sopenharmony_ci perror("read returned error"); 1828c2ecf20Sopenharmony_ci return -1; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return 0; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cisigjmp_buf jmpbuf; 1898c2ecf20Sopenharmony_civoid pac_signal_handler(int signum, siginfo_t *si, void *uc) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (signum == SIGSEGV || signum == SIGILL) 1928c2ecf20Sopenharmony_ci siglongjmp(jmpbuf, 1); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* check that a corrupted PAC results in SIGSEGV or SIGILL */ 1968c2ecf20Sopenharmony_ciTEST(corrupt_pac) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct sigaction sa; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci ASSERT_PAUTH_ENABLED(); 2018c2ecf20Sopenharmony_ci if (sigsetjmp(jmpbuf, 1) == 0) { 2028c2ecf20Sopenharmony_ci sa.sa_sigaction = pac_signal_handler; 2038c2ecf20Sopenharmony_ci sa.sa_flags = SA_SIGINFO | SA_RESETHAND; 2048c2ecf20Sopenharmony_ci sigemptyset(&sa.sa_mask); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci sigaction(SIGSEGV, &sa, NULL); 2078c2ecf20Sopenharmony_ci sigaction(SIGILL, &sa, NULL); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci pac_corruptor(); 2108c2ecf20Sopenharmony_ci ASSERT_TRUE(0) TH_LOG("SIGSEGV/SIGILL signal did not occur"); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/* 2158c2ecf20Sopenharmony_ci * There are no separate pac* and aut* controls so checking only the pac* 2168c2ecf20Sopenharmony_ci * instructions is sufficient 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ciTEST(pac_instructions_not_nop) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci size_t keyia = 0; 2218c2ecf20Sopenharmony_ci size_t keyib = 0; 2228c2ecf20Sopenharmony_ci size_t keyda = 0; 2238c2ecf20Sopenharmony_ci size_t keydb = 0; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci ASSERT_PAUTH_ENABLED(); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) { 2288c2ecf20Sopenharmony_ci keyia |= keyia_sign(i) & PAC_MASK; 2298c2ecf20Sopenharmony_ci keyib |= keyib_sign(i) & PAC_MASK; 2308c2ecf20Sopenharmony_ci keyda |= keyda_sign(i) & PAC_MASK; 2318c2ecf20Sopenharmony_ci keydb |= keydb_sign(i) & PAC_MASK; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ASSERT_NE(0, keyia) TH_LOG("keyia instructions did nothing"); 2358c2ecf20Sopenharmony_ci ASSERT_NE(0, keyib) TH_LOG("keyib instructions did nothing"); 2368c2ecf20Sopenharmony_ci ASSERT_NE(0, keyda) TH_LOG("keyda instructions did nothing"); 2378c2ecf20Sopenharmony_ci ASSERT_NE(0, keydb) TH_LOG("keydb instructions did nothing"); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciTEST(pac_instructions_not_nop_generic) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci size_t keyg = 0; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci ASSERT_GENERIC_PAUTH_ENABLED(); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) 2478c2ecf20Sopenharmony_ci keyg |= keyg_sign(i) & PAC_MASK; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ASSERT_NE(0, keyg) TH_LOG("keyg instructions did nothing"); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ciTEST(single_thread_different_keys) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci int same = 10; 2558c2ecf20Sopenharmony_ci int nkeys = NKEYS; 2568c2ecf20Sopenharmony_ci int tmp; 2578c2ecf20Sopenharmony_ci struct signatures signed_vals; 2588c2ecf20Sopenharmony_ci unsigned long hwcaps = getauxval(AT_HWCAP); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* generic and data key instructions are not in NOP space. This prevents a SIGILL */ 2618c2ecf20Sopenharmony_ci ASSERT_PAUTH_ENABLED(); 2628c2ecf20Sopenharmony_ci if (!(hwcaps & HWCAP_PACG)) { 2638c2ecf20Sopenharmony_ci TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks"); 2648c2ecf20Sopenharmony_ci nkeys = NKEYS - 1; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* 2688c2ecf20Sopenharmony_ci * In Linux the PAC field can be up to 7 bits wide. Even if keys are 2698c2ecf20Sopenharmony_ci * different, there is about 5% chance for PACs to collide with 2708c2ecf20Sopenharmony_ci * different addresses. This chance rapidly increases with fewer bits 2718c2ecf20Sopenharmony_ci * allocated for the PAC (e.g. wider address). A comparison of the keys 2728c2ecf20Sopenharmony_ci * directly will be more reliable. 2738c2ecf20Sopenharmony_ci * All signed values need to be different at least once out of n 2748c2ecf20Sopenharmony_ci * attempts to be certain that the keys are different 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) { 2778c2ecf20Sopenharmony_ci if (nkeys == NKEYS) 2788c2ecf20Sopenharmony_ci sign_all(&signed_vals, i); 2798c2ecf20Sopenharmony_ci else 2808c2ecf20Sopenharmony_ci sign_specific(&signed_vals, i); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci tmp = n_same_single_set(&signed_vals, nkeys); 2838c2ecf20Sopenharmony_ci if (tmp < same) 2848c2ecf20Sopenharmony_ci same = tmp; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci ASSERT_EQ(0, same) TH_LOG("%d keys clashed every time", same); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * fork() does not change keys. Only exec() does so call a worker program. 2928c2ecf20Sopenharmony_ci * Its only job is to sign a value and report back the resutls 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_ciTEST(exec_changed_keys) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct signatures new_keys; 2978c2ecf20Sopenharmony_ci struct signatures old_keys; 2988c2ecf20Sopenharmony_ci int ret; 2998c2ecf20Sopenharmony_ci int same = 10; 3008c2ecf20Sopenharmony_ci int nkeys = NKEYS; 3018c2ecf20Sopenharmony_ci unsigned long hwcaps = getauxval(AT_HWCAP); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* generic and data key instructions are not in NOP space. This prevents a SIGILL */ 3048c2ecf20Sopenharmony_ci ASSERT_PAUTH_ENABLED(); 3058c2ecf20Sopenharmony_ci if (!(hwcaps & HWCAP_PACG)) { 3068c2ecf20Sopenharmony_ci TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks"); 3078c2ecf20Sopenharmony_ci nkeys = NKEYS - 1; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) { 3118c2ecf20Sopenharmony_ci ret = exec_sign_all(&new_keys, i); 3128c2ecf20Sopenharmony_ci ASSERT_EQ(0, ret) TH_LOG("failed to run worker"); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (nkeys == NKEYS) 3158c2ecf20Sopenharmony_ci sign_all(&old_keys, i); 3168c2ecf20Sopenharmony_ci else 3178c2ecf20Sopenharmony_ci sign_specific(&old_keys, i); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci ret = n_same(&old_keys, &new_keys, nkeys); 3208c2ecf20Sopenharmony_ci if (ret < same) 3218c2ecf20Sopenharmony_ci same = ret; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ASSERT_EQ(0, same) TH_LOG("exec() did not change %d keys", same); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ciTEST(context_switch_keep_keys) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci int ret; 3308c2ecf20Sopenharmony_ci struct signatures trash; 3318c2ecf20Sopenharmony_ci struct signatures before; 3328c2ecf20Sopenharmony_ci struct signatures after; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ASSERT_PAUTH_ENABLED(); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci sign_specific(&before, ARBITRARY_VALUE); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* will context switch with a process with different keys at least once */ 3398c2ecf20Sopenharmony_ci ret = exec_sign_all(&trash, ARBITRARY_VALUE); 3408c2ecf20Sopenharmony_ci ASSERT_EQ(0, ret) TH_LOG("failed to run worker"); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci sign_specific(&after, ARBITRARY_VALUE); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci ASSERT_EQ(before.keyia, after.keyia) TH_LOG("keyia changed after context switching"); 3458c2ecf20Sopenharmony_ci ASSERT_EQ(before.keyib, after.keyib) TH_LOG("keyib changed after context switching"); 3468c2ecf20Sopenharmony_ci ASSERT_EQ(before.keyda, after.keyda) TH_LOG("keyda changed after context switching"); 3478c2ecf20Sopenharmony_ci ASSERT_EQ(before.keydb, after.keydb) TH_LOG("keydb changed after context switching"); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ciTEST(context_switch_keep_keys_generic) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci int ret; 3538c2ecf20Sopenharmony_ci struct signatures trash; 3548c2ecf20Sopenharmony_ci size_t before; 3558c2ecf20Sopenharmony_ci size_t after; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci ASSERT_GENERIC_PAUTH_ENABLED(); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci before = keyg_sign(ARBITRARY_VALUE); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* will context switch with a process with different keys at least once */ 3628c2ecf20Sopenharmony_ci ret = exec_sign_all(&trash, ARBITRARY_VALUE); 3638c2ecf20Sopenharmony_ci ASSERT_EQ(0, ret) TH_LOG("failed to run worker"); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci after = keyg_sign(ARBITRARY_VALUE); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci ASSERT_EQ(before, after) TH_LOG("keyg changed after context switching"); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ciTEST_HARNESS_MAIN 371