1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _PKEYS_HELPER_H
3 #define _PKEYS_HELPER_H
16 /* Define some kernel-like types */
22 #define PTR_ERR_ENOTSUP ((void *)-ENOTSUP)
27 #define DPRINT_IN_SIGNAL_BUF_SIZE 4096
28 extern int dprint_in_signal
;
29 extern char dprint_in_signal_buffer
[DPRINT_IN_SIGNAL_BUF_SIZE
];
32 extern int iteration_nr
;
35 __attribute__((format(printf
, 1, 2)))
37 static inline void sigsafe_printf(const char *format
, ...)
41 if (!dprint_in_signal
) {
48 * No printf() functions are signal-safe.
49 * They deadlock easily. Write the format
50 * string to get some output, even if
53 ret
= write(1, format
, strlen(format
));
58 #define dprintf_level(level, args...) do { \
59 if (level <= DEBUG_LEVEL) \
60 sigsafe_printf(args); \
62 #define dprintf0(args...) dprintf_level(0, args)
63 #define dprintf1(args...) dprintf_level(1, args)
64 #define dprintf2(args...) dprintf_level(2, args)
65 #define dprintf3(args...) dprintf_level(3, args)
66 #define dprintf4(args...) dprintf_level(4, args)
68 extern void abort_hooks(void);
69 #define pkey_assert(condition) do { \
71 dprintf0("assert() at %s::%d test_nr: %d iteration: %d\n", \
73 test_nr, iteration_nr); \
74 dprintf0("errno at assert: %d", errno); \
80 __attribute__((noinline
)) int read_ptr(int *ptr
);
81 void expected_pkey_fault(int pkey
);
82 int sys_pkey_alloc(unsigned long flags
, unsigned long init_val
);
83 int sys_pkey_free(unsigned long pkey
);
84 int mprotect_pkey(void *ptr
, size_t size
, unsigned long orig_prot
,
86 void record_pkey_malloc(void *ptr
, long size
, int prot
);
88 #if defined(__i386__) || defined(__x86_64__) /* arch */
90 #elif defined(__powerpc64__) /* arch */
91 #include "pkey-powerpc.h"
93 #error Architecture not supported
96 #define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
98 static inline u64
set_pkey_bits(u64 reg
, int pkey
, u64 flags
)
100 u32 shift
= pkey_bit_position(pkey
);
101 /* mask out bits from pkey in old value */
102 reg
&= ~((u64
)PKEY_MASK
<< shift
);
103 /* OR in new bits for pkey */
104 reg
|= (flags
& PKEY_MASK
) << shift
;
108 static inline u64
get_pkey_bits(u64 reg
, int pkey
)
110 u32 shift
= pkey_bit_position(pkey
);
112 * shift down the relevant bits to the lowest two, then
113 * mask off all the other higher bits
115 return ((reg
>> shift
) & PKEY_MASK
);
118 extern u64 shadow_pkey_reg
;
120 static inline u64
_read_pkey_reg(int line
)
122 u64 pkey_reg
= __read_pkey_reg();
124 dprintf4("read_pkey_reg(line=%d) pkey_reg: %016llx"
125 " shadow: %016llx\n",
126 line
, pkey_reg
, shadow_pkey_reg
);
127 assert(pkey_reg
== shadow_pkey_reg
);
132 #define read_pkey_reg() _read_pkey_reg(__LINE__)
134 static inline void write_pkey_reg(u64 pkey_reg
)
136 dprintf4("%s() changing %016llx to %016llx\n", __func__
,
137 __read_pkey_reg(), pkey_reg
);
138 /* will do the shadow check for us: */
140 __write_pkey_reg(pkey_reg
);
141 shadow_pkey_reg
= pkey_reg
;
142 dprintf4("%s(%016llx) pkey_reg: %016llx\n", __func__
,
143 pkey_reg
, __read_pkey_reg());
147 * These are technically racy. since something could
148 * change PKEY register between the read and the write.
150 static inline void __pkey_access_allow(int pkey
, int do_allow
)
152 u64 pkey_reg
= read_pkey_reg();
156 pkey_reg
&= (1<<bit
);
158 pkey_reg
|= (1<<bit
);
160 dprintf4("pkey_reg now: %016llx\n", read_pkey_reg());
161 write_pkey_reg(pkey_reg
);
164 static inline void __pkey_write_allow(int pkey
, int do_allow_write
)
166 u64 pkey_reg
= read_pkey_reg();
167 int bit
= pkey
* 2 + 1;
170 pkey_reg
&= (1<<bit
);
172 pkey_reg
|= (1<<bit
);
174 write_pkey_reg(pkey_reg
);
175 dprintf4("pkey_reg now: %016llx\n", read_pkey_reg());
178 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
179 #define ALIGN_UP(x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1))
180 #define ALIGN_DOWN(x, align_to) ((x) & ~((align_to)-1))
181 #define ALIGN_PTR_UP(p, ptr_align_to) \
182 ((typeof(p))ALIGN_UP((unsigned long)(p), ptr_align_to))
183 #define ALIGN_PTR_DOWN(p, ptr_align_to) \
184 ((typeof(p))ALIGN_DOWN((unsigned long)(p), ptr_align_to))
185 #define __stringify_1(x...) #x
186 #define __stringify(x...) __stringify_1(x)
188 static inline u32
*siginfo_get_pkey_ptr(siginfo_t
*si
)
193 return (u32
*)(((u8
*)si
) + si_pkey_offset
);
197 static inline int kernel_has_pkeys(void)
199 /* try allocating a key and see if it succeeds */
200 int ret
= sys_pkey_alloc(0, 0);
208 static inline int is_pkeys_supported(void)
210 /* check if the cpu supports pkeys */
211 if (!cpu_has_pkeys()) {
212 dprintf1("SKIP: %s: no CPU support\n", __func__
);
216 /* check if the kernel supports pkeys */
217 if (!kernel_has_pkeys()) {
218 dprintf1("SKIP: %s: no kernel support\n", __func__
);
225 #endif /* _PKEYS_HELPER_H */