pac.c (e74e1d55728509b352e4eec4283dd5b2781b2070) pac.c (766d95b1ed93ebdd07ac87490e60e442342f5dc4)
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2020 ARM Limited
3
4#include <sys/auxv.h>
5#include <signal.h>
6#include <setjmp.h>
7
8#include "../../kselftest_harness.h"
9#include "helper.h"
10
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2020 ARM Limited
3
4#include <sys/auxv.h>
5#include <signal.h>
6#include <setjmp.h>
7
8#include "../../kselftest_harness.h"
9#include "helper.h"
10
11#define PAC_COLLISION_ATTEMPTS 10
12/*
13 * The kernel sets TBID by default. So bits 55 and above should remain
14 * untouched no matter what.
15 * The VA space size is 48 bits. Bigger is opt-in.
16 */
17#define PAC_MASK (~0xff80ffffffffffff)
11#define ASSERT_PAUTH_ENABLED() \
12do { \
13 unsigned long hwcaps = getauxval(AT_HWCAP); \
14 /* data key instructions are not in NOP space. This prevents a SIGILL */ \
15 ASSERT_NE(0, hwcaps & HWCAP_PACA) TH_LOG("PAUTH not enabled"); \
16} while (0)
18#define ASSERT_PAUTH_ENABLED() \
19do { \
20 unsigned long hwcaps = getauxval(AT_HWCAP); \
21 /* data key instructions are not in NOP space. This prevents a SIGILL */ \
22 ASSERT_NE(0, hwcaps & HWCAP_PACA) TH_LOG("PAUTH not enabled"); \
23} while (0)
24#define ASSERT_GENERIC_PAUTH_ENABLED() \
25do { \
26 unsigned long hwcaps = getauxval(AT_HWCAP); \
27 /* generic key instructions are not in NOP space. This prevents a SIGILL */ \
28 ASSERT_NE(0, hwcaps & HWCAP_PACG) TH_LOG("Generic PAUTH not enabled"); \
29} while (0)
17
18sigjmp_buf jmpbuf;
19void pac_signal_handler(int signum, siginfo_t *si, void *uc)
20{
21 if (signum == SIGSEGV || signum == SIGILL)
22 siglongjmp(jmpbuf, 1);
23}
24

--- 11 unchanged lines hidden (view full) ---

36 sigaction(SIGSEGV, &sa, NULL);
37 sigaction(SIGILL, &sa, NULL);
38
39 pac_corruptor();
40 ASSERT_TRUE(0) TH_LOG("SIGSEGV/SIGILL signal did not occur");
41 }
42}
43
30
31sigjmp_buf jmpbuf;
32void pac_signal_handler(int signum, siginfo_t *si, void *uc)
33{
34 if (signum == SIGSEGV || signum == SIGILL)
35 siglongjmp(jmpbuf, 1);
36}
37

--- 11 unchanged lines hidden (view full) ---

49 sigaction(SIGSEGV, &sa, NULL);
50 sigaction(SIGILL, &sa, NULL);
51
52 pac_corruptor();
53 ASSERT_TRUE(0) TH_LOG("SIGSEGV/SIGILL signal did not occur");
54 }
55}
56
57/*
58 * There are no separate pac* and aut* controls so checking only the pac*
59 * instructions is sufficient
60 */
61TEST(pac_instructions_not_nop)
62{
63 size_t keyia = 0;
64 size_t keyib = 0;
65 size_t keyda = 0;
66 size_t keydb = 0;
67
68 ASSERT_PAUTH_ENABLED();
69
70 for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) {
71 keyia |= keyia_sign(i) & PAC_MASK;
72 keyib |= keyib_sign(i) & PAC_MASK;
73 keyda |= keyda_sign(i) & PAC_MASK;
74 keydb |= keydb_sign(i) & PAC_MASK;
75 }
76
77 ASSERT_NE(0, keyia) TH_LOG("keyia instructions did nothing");
78 ASSERT_NE(0, keyib) TH_LOG("keyib instructions did nothing");
79 ASSERT_NE(0, keyda) TH_LOG("keyda instructions did nothing");
80 ASSERT_NE(0, keydb) TH_LOG("keydb instructions did nothing");
81}
82
83TEST(pac_instructions_not_nop_generic)
84{
85 size_t keyg = 0;
86
87 ASSERT_GENERIC_PAUTH_ENABLED();
88
89 for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++)
90 keyg |= keyg_sign(i) & PAC_MASK;
91
92 ASSERT_NE(0, keyg) TH_LOG("keyg instructions did nothing");
93}
94
44TEST_HARNESS_MAIN
95TEST_HARNESS_MAIN