selftests/vm/pkeys: rename all references to pkru to a generic name

This renames PKRU references to "pkey_reg" or "pkey" based on
the usage.

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Dave Hansen <dave.hansen@intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: "Desnes A. Nunes do Rosario" <desnesn@linux.vnet.ibm.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Suchanek <msuchanek@suse.de>
Cc: Shuah Khan <shuah@kernel.org>
Link: http://lkml.kernel.org/r/2c6970bc6d2e99796cd5cc1101bd2ecf7eccb937.1585646528.git.sandipan@linux.ibm.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Ram Pai 2020-06-04 16:51:37 -07:00 коммит произвёл Linus Torvalds
Родитель 804eb64615
Коммит c4273c7f0e
2 изменённых файлов: 170 добавлений и 155 удалений

Просмотреть файл

@ -14,7 +14,7 @@
#include <sys/mman.h>
#define NR_PKEYS 16
#define PKRU_BITS_PER_PKEY 2
#define PKEY_BITS_PER_PKEY 2
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL 0
@ -53,85 +53,88 @@ static inline void sigsafe_printf(const char *format, ...)
#define dprintf3(args...) dprintf_level(3, args)
#define dprintf4(args...) dprintf_level(4, args)
extern unsigned int shadow_pkru;
static inline unsigned int __rdpkru(void)
extern unsigned int shadow_pkey_reg;
static inline unsigned int __read_pkey_reg(void)
{
unsigned int eax, edx;
unsigned int ecx = 0;
unsigned int pkru;
unsigned int pkey_reg;
asm volatile(".byte 0x0f,0x01,0xee\n\t"
: "=a" (eax), "=d" (edx)
: "c" (ecx));
pkru = eax;
return pkru;
pkey_reg = eax;
return pkey_reg;
}
static inline unsigned int _rdpkru(int line)
static inline unsigned int _read_pkey_reg(int line)
{
unsigned int pkru = __rdpkru();
unsigned int pkey_reg = __read_pkey_reg();
dprintf4("rdpkru(line=%d) pkru: %x shadow: %x\n",
line, pkru, shadow_pkru);
assert(pkru == shadow_pkru);
dprintf4("read_pkey_reg(line=%d) pkey_reg: %x shadow: %x\n",
line, pkey_reg, shadow_pkey_reg);
assert(pkey_reg == shadow_pkey_reg);
return pkru;
return pkey_reg;
}
#define rdpkru() _rdpkru(__LINE__)
#define read_pkey_reg() _read_pkey_reg(__LINE__)
static inline void __wrpkru(unsigned int pkru)
static inline void __write_pkey_reg(unsigned int pkey_reg)
{
unsigned int eax = pkru;
unsigned int eax = pkey_reg;
unsigned int ecx = 0;
unsigned int edx = 0;
dprintf4("%s() changing %08x to %08x\n", __func__, __rdpkru(), pkru);
dprintf4("%s() changing %08x to %08x\n", __func__,
__read_pkey_reg(), pkey_reg);
asm volatile(".byte 0x0f,0x01,0xef\n\t"
: : "a" (eax), "c" (ecx), "d" (edx));
assert(pkru == __rdpkru());
assert(pkey_reg == __read_pkey_reg());
}
static inline void wrpkru(unsigned int pkru)
static inline void write_pkey_reg(unsigned int pkey_reg)
{
dprintf4("%s() changing %08x to %08x\n", __func__, __rdpkru(), pkru);
dprintf4("%s() changing %08x to %08x\n", __func__,
__read_pkey_reg(), pkey_reg);
/* will do the shadow check for us: */
rdpkru();
__wrpkru(pkru);
shadow_pkru = pkru;
dprintf4("%s(%08x) pkru: %08x\n", __func__, pkru, __rdpkru());
read_pkey_reg();
__write_pkey_reg(pkey_reg);
shadow_pkey_reg = pkey_reg;
dprintf4("%s(%08x) pkey_reg: %08x\n", __func__,
pkey_reg, __read_pkey_reg());
}
/*
* These are technically racy. since something could
* change PKRU between the read and the write.
* change PKEY register between the read and the write.
*/
static inline void __pkey_access_allow(int pkey, int do_allow)
{
unsigned int pkru = rdpkru();
unsigned int pkey_reg = read_pkey_reg();
int bit = pkey * 2;
if (do_allow)
pkru &= (1<<bit);
pkey_reg &= (1<<bit);
else
pkru |= (1<<bit);
pkey_reg |= (1<<bit);
dprintf4("pkru now: %08x\n", rdpkru());
wrpkru(pkru);
dprintf4("pkey_reg now: %08x\n", read_pkey_reg());
write_pkey_reg(pkey_reg);
}
static inline void __pkey_write_allow(int pkey, int do_allow_write)
{
long pkru = rdpkru();
long pkey_reg = read_pkey_reg();
int bit = pkey * 2 + 1;
if (do_allow_write)
pkru &= (1<<bit);
pkey_reg &= (1<<bit);
else
pkru |= (1<<bit);
pkey_reg |= (1<<bit);
wrpkru(pkru);
dprintf4("pkru now: %08x\n", rdpkru());
write_pkey_reg(pkey_reg);
dprintf4("pkey_reg now: %08x\n", read_pkey_reg());
}
#define PROT_PKEY0 0x10 /* protection key value (bit 0) */
@ -181,10 +184,10 @@ static inline int cpu_has_pku(void)
return 1;
}
#define XSTATE_PKRU_BIT (9)
#define XSTATE_PKRU 0x200
#define XSTATE_PKEY_BIT (9)
#define XSTATE_PKEY 0x200
int pkru_xstate_offset(void)
int pkey_reg_xstate_offset(void)
{
unsigned int eax;
unsigned int ebx;
@ -195,21 +198,21 @@ int pkru_xstate_offset(void)
unsigned long XSTATE_CPUID = 0xd;
int leaf;
/* assume that XSTATE_PKRU is set in XCR0 */
leaf = XSTATE_PKRU_BIT;
/* assume that XSTATE_PKEY is set in XCR0 */
leaf = XSTATE_PKEY_BIT;
{
eax = XSTATE_CPUID;
ecx = leaf;
__cpuid(&eax, &ebx, &ecx, &edx);
if (leaf == XSTATE_PKRU_BIT) {
if (leaf == XSTATE_PKEY_BIT) {
xstate_offset = ebx;
xstate_size = eax;
}
}
if (xstate_size == 0) {
printf("could not find size/offset of PKRU in xsave state\n");
printf("could not find size/offset of PKEY in xsave state\n");
return 0;
}

Просмотреть файл

@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Tests x86 Memory Protection Keys (see Documentation/core-api/protection-keys.rst)
* Tests Memory Protection Keys (see Documentation/vm/protection-keys.txt)
*
* There are examples in here of:
* * how to set protection keys on memory
* * how to set/clear bits in PKRU (the rights register)
* * how to handle SEGV_PKRU signals and extract pkey-relevant
* * how to set/clear bits in pkey registers (the rights register)
* * how to handle SEGV_PKUERR signals and extract pkey-relevant
* information from the siginfo
*
* Things to add:
@ -48,7 +48,7 @@
int iteration_nr = 1;
int test_nr;
unsigned int shadow_pkru;
unsigned int shadow_pkey_reg;
#define HPAGE_SIZE (1UL<<21)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@ -255,7 +255,7 @@ static char *si_code_str(int si_code)
return "UNKNOWN";
}
int pkru_faults;
int pkey_faults;
int last_si_pkey = -1;
void signal_handler(int signum, siginfo_t *si, void *vucontext)
{
@ -263,16 +263,16 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
int trapno;
unsigned long ip;
char *fpregs;
u32 *pkru_ptr;
u32 *pkey_reg_ptr;
u64 siginfo_pkey;
u32 *si_pkey_ptr;
int pkru_offset;
int pkey_reg_offset;
fpregset_t fpregset;
dprint_in_signal = 1;
dprintf1(">>>>===============SIGSEGV============================\n");
dprintf1("%s()::%d, pkru: 0x%x shadow: %x\n", __func__, __LINE__,
__rdpkru(), shadow_pkru);
dprintf1("%s()::%d, pkey_reg: 0x%x shadow: %x\n", __func__, __LINE__,
__read_pkey_reg(), shadow_pkey_reg);
trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
@ -289,19 +289,19 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
*/
fpregs += 0x70;
#endif
pkru_offset = pkru_xstate_offset();
pkru_ptr = (void *)(&fpregs[pkru_offset]);
pkey_reg_offset = pkey_reg_xstate_offset();
pkey_reg_ptr = (void *)(&fpregs[pkey_reg_offset]);
dprintf1("siginfo: %p\n", si);
dprintf1(" fpregs: %p\n", fpregs);
/*
* If we got a PKRU fault, we *HAVE* to have at least one bit set in
* If we got a PKEY fault, we *HAVE* to have at least one bit set in
* here.
*/
dprintf1("pkru_xstate_offset: %d\n", pkru_xstate_offset());
dprintf1("pkey_reg_xstate_offset: %d\n", pkey_reg_xstate_offset());
if (DEBUG_LEVEL > 4)
dump_mem(pkru_ptr - 128, 256);
pkey_assert(*pkru_ptr);
dump_mem(pkey_reg_ptr - 128, 256);
pkey_assert(*pkey_reg_ptr);
if ((si->si_code == SEGV_MAPERR) ||
(si->si_code == SEGV_ACCERR) ||
@ -317,13 +317,16 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
pkey_assert(siginfo_pkey < NR_PKEYS);
last_si_pkey = siginfo_pkey;
dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr);
/* need __rdpkru() version so we do not do shadow_pkru checking */
dprintf1("signal pkru from pkru: %08x\n", __rdpkru());
dprintf1("signal pkey_reg from xsave: %08x\n", *pkey_reg_ptr);
/*
* need __read_pkey_reg() version so we do not do shadow_pkey_reg
* checking
*/
dprintf1("signal pkey_reg from pkey_reg: %08x\n", __read_pkey_reg());
dprintf1("pkey from siginfo: %jx\n", siginfo_pkey);
*(u64 *)pkru_ptr = 0x00000000;
dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n");
pkru_faults++;
*(u64 *)pkey_reg_ptr = 0x00000000;
dprintf1("WARNING: set PKEY_REG=0 to allow faulting instruction to continue\n");
pkey_faults++;
dprintf1("<<<<==================================================\n");
dprint_in_signal = 0;
}
@ -402,45 +405,47 @@ pid_t fork_lazy_child(void)
static u32 hw_pkey_get(int pkey, unsigned long flags)
{
u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
u32 pkru = __rdpkru();
u32 shifted_pkru;
u32 masked_pkru;
u32 pkey_reg = __read_pkey_reg();
u32 shifted_pkey_reg;
u32 masked_pkey_reg;
dprintf1("%s(pkey=%d, flags=%lx) = %x / %d\n",
__func__, pkey, flags, 0, 0);
dprintf2("%s() raw pkru: %x\n", __func__, pkru);
dprintf2("%s() raw pkey_reg: %x\n", __func__, pkey_reg);
shifted_pkru = (pkru >> (pkey * PKRU_BITS_PER_PKEY));
dprintf2("%s() shifted_pkru: %x\n", __func__, shifted_pkru);
masked_pkru = shifted_pkru & mask;
dprintf2("%s() masked pkru: %x\n", __func__, masked_pkru);
shifted_pkey_reg = (pkey_reg >> (pkey * PKEY_BITS_PER_PKEY));
dprintf2("%s() shifted_pkey_reg: %x\n", __func__, shifted_pkey_reg);
masked_pkey_reg = shifted_pkey_reg & mask;
dprintf2("%s() masked pkey_reg: %x\n", __func__, masked_pkey_reg);
/*
* shift down the relevant bits to the lowest two, then
* mask off all the other high bits.
*/
return masked_pkru;
return masked_pkey_reg;
}
static int hw_pkey_set(int pkey, unsigned long rights, unsigned long flags)
{
u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
u32 old_pkru = __rdpkru();
u32 new_pkru;
u32 old_pkey_reg = __read_pkey_reg();
u32 new_pkey_reg;
/* make sure that 'rights' only contains the bits we expect: */
assert(!(rights & ~mask));
/* copy old pkru */
new_pkru = old_pkru;
/* copy old pkey_reg */
new_pkey_reg = old_pkey_reg;
/* mask out bits from pkey in old value: */
new_pkru &= ~(mask << (pkey * PKRU_BITS_PER_PKEY));
new_pkey_reg &= ~(mask << (pkey * PKEY_BITS_PER_PKEY));
/* OR in new bits for pkey: */
new_pkru |= (rights << (pkey * PKRU_BITS_PER_PKEY));
new_pkey_reg |= (rights << (pkey * PKEY_BITS_PER_PKEY));
__wrpkru(new_pkru);
__write_pkey_reg(new_pkey_reg);
dprintf3("%s(pkey=%d, rights=%lx, flags=%lx) = %x pkru now: %x old_pkru: %x\n",
__func__, pkey, rights, flags, 0, __rdpkru(), old_pkru);
dprintf3("%s(pkey=%d, rights=%lx, flags=%lx) = %x"
" pkey_reg now: %x old_pkey_reg: %x\n",
__func__, pkey, rights, flags, 0, __read_pkey_reg(),
old_pkey_reg);
return 0;
}
@ -449,7 +454,7 @@ void pkey_disable_set(int pkey, int flags)
unsigned long syscall_flags = 0;
int ret;
int pkey_rights;
u32 orig_pkru = rdpkru();
u32 orig_pkey_reg = read_pkey_reg();
dprintf1("START->%s(%d, 0x%x)\n", __func__,
pkey, flags);
@ -465,9 +470,9 @@ void pkey_disable_set(int pkey, int flags)
ret = hw_pkey_set(pkey, pkey_rights, syscall_flags);
assert(!ret);
/*pkru and flags have the same format */
shadow_pkru |= flags << (pkey * 2);
dprintf1("%s(%d) shadow: 0x%x\n", __func__, pkey, shadow_pkru);
/* pkey_reg and flags have the same format */
shadow_pkey_reg |= flags << (pkey * 2);
dprintf1("%s(%d) shadow: 0x%x\n", __func__, pkey, shadow_pkey_reg);
pkey_assert(ret >= 0);
@ -475,9 +480,9 @@ void pkey_disable_set(int pkey, int flags)
dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
pkey, pkey, pkey_rights);
dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
dprintf1("%s(%d) pkey_reg: 0x%x\n", __func__, pkey, read_pkey_reg());
if (flags)
pkey_assert(rdpkru() > orig_pkru);
pkey_assert(read_pkey_reg() > orig_pkey_reg);
dprintf1("END<---%s(%d, 0x%x)\n", __func__,
pkey, flags);
}
@ -487,7 +492,7 @@ void pkey_disable_clear(int pkey, int flags)
unsigned long syscall_flags = 0;
int ret;
int pkey_rights = hw_pkey_get(pkey, syscall_flags);
u32 orig_pkru = rdpkru();
u32 orig_pkey_reg = read_pkey_reg();
pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
@ -498,17 +503,16 @@ void pkey_disable_clear(int pkey, int flags)
pkey_rights |= flags;
ret = hw_pkey_set(pkey, pkey_rights, 0);
/* pkru and flags have the same format */
shadow_pkru &= ~(flags << (pkey * 2));
shadow_pkey_reg &= ~(flags << (pkey * 2));
pkey_assert(ret >= 0);
pkey_rights = hw_pkey_get(pkey, syscall_flags);
dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__,
pkey, pkey, pkey_rights);
dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
dprintf1("%s(%d) pkey_reg: 0x%x\n", __func__, pkey, read_pkey_reg());
if (flags)
assert(rdpkru() > orig_pkru);
assert(read_pkey_reg() > orig_pkey_reg);
}
void pkey_write_allow(int pkey)
@ -561,33 +565,38 @@ int alloc_pkey(void)
int ret;
unsigned long init_val = 0x0;
dprintf1("alloc_pkey()::%d, pkru: 0x%x shadow: %x\n",
__LINE__, __rdpkru(), shadow_pkru);
dprintf1("%s()::%d, pkey_reg: 0x%x shadow: %x\n", __func__,
__LINE__, __read_pkey_reg(), shadow_pkey_reg);
ret = sys_pkey_alloc(0, init_val);
/*
* pkey_alloc() sets PKRU, so we need to reflect it in
* shadow_pkru:
* pkey_alloc() sets PKEY register, so we need to reflect it in
* shadow_pkey_reg:
*/
dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf4("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
if (ret) {
/* clear both the bits: */
shadow_pkru &= ~(0x3 << (ret * 2));
dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
__LINE__, ret, __rdpkru(), shadow_pkru);
shadow_pkey_reg &= ~(0x3 << (ret * 2));
dprintf4("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__,
__LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
/*
* move the new state in from init_val
* (remember, we cheated and init_val == pkru format)
* (remember, we cheated and init_val == pkey_reg format)
*/
shadow_pkru |= (init_val << (ret * 2));
shadow_pkey_reg |= (init_val << (ret * 2));
}
dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf1("alloc_pkey()::%d errno: %d\n", __LINE__, errno);
dprintf4("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
dprintf1("%s()::%d errno: %d\n", __func__, __LINE__, errno);
/* for shadow checking: */
rdpkru();
dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
__LINE__, ret, __rdpkru(), shadow_pkru);
read_pkey_reg();
dprintf4("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
return ret;
}
@ -638,8 +647,8 @@ int alloc_random_pkey(void)
free_ret = sys_pkey_free(alloced_pkeys[i]);
pkey_assert(!free_ret);
}
dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf1("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __read_pkey_reg(), shadow_pkey_reg);
return ret;
}
@ -657,11 +666,13 @@ int mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
if (nr_iterations-- < 0)
break;
dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf1("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
sys_pkey_free(rpkey);
dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf1("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, ret, __read_pkey_reg(),
shadow_pkey_reg);
}
pkey_assert(pkey < NR_PKEYS);
@ -669,8 +680,8 @@ int mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
dprintf1("mprotect_pkey(%p, %zx, prot=0x%lx, pkey=%ld) ret: %d\n",
ptr, size, orig_prot, pkey, ret);
pkey_assert(!ret);
dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __rdpkru(), shadow_pkru);
dprintf1("%s()::%d, ret: %d pkey_reg: 0x%x shadow: 0x%x\n", __func__,
__LINE__, ret, __read_pkey_reg(), shadow_pkey_reg);
return ret;
}
@ -752,7 +763,7 @@ void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey)
void *ptr;
int ret;
rdpkru();
read_pkey_reg();
dprintf1("doing %s(size=%ld, prot=0x%x, pkey=%d)\n", __func__,
size, prot, pkey);
pkey_assert(pkey < NR_PKEYS);
@ -761,7 +772,7 @@ void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey)
ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey);
pkey_assert(!ret);
record_pkey_malloc(ptr, size, prot);
rdpkru();
read_pkey_reg();
dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr);
return ptr;
@ -924,14 +935,14 @@ void *malloc_pkey(long size, int prot, u16 pkey)
return ret;
}
int last_pkru_faults;
int last_pkey_faults;
#define UNKNOWN_PKEY -2
void expected_pk_fault(int pkey)
void expected_pkey_fault(int pkey)
{
dprintf2("%s(): last_pkru_faults: %d pkru_faults: %d\n",
__func__, last_pkru_faults, pkru_faults);
dprintf2("%s(): last_pkey_faults: %d pkey_faults: %d\n",
__func__, last_pkey_faults, pkey_faults);
dprintf2("%s(%d): last_si_pkey: %d\n", __func__, pkey, last_si_pkey);
pkey_assert(last_pkru_faults + 1 == pkru_faults);
pkey_assert(last_pkey_faults + 1 == pkey_faults);
/*
* For exec-only memory, we do not know the pkey in
@ -941,23 +952,23 @@ void expected_pk_fault(int pkey)
pkey_assert(last_si_pkey == pkey);
/*
* The signal handler shold have cleared out PKRU to let the
* The signal handler shold have cleared out PKEY register to let the
* test program continue. We now have to restore it.
*/
if (__rdpkru() != 0)
if (__read_pkey_reg() != 0)
pkey_assert(0);
__wrpkru(shadow_pkru);
dprintf1("%s() set PKRU=%x to restore state after signal nuked it\n",
__func__, shadow_pkru);
last_pkru_faults = pkru_faults;
__write_pkey_reg(shadow_pkey_reg);
dprintf1("%s() set pkey_reg=%x to restore state after signal "
"nuked it\n", __func__, shadow_pkey_reg);
last_pkey_faults = pkey_faults;
last_si_pkey = -1;
}
#define do_not_expect_pk_fault(msg) do { \
if (last_pkru_faults != pkru_faults) \
dprintf0("unexpected PK fault: %s\n", msg); \
pkey_assert(last_pkru_faults == pkru_faults); \
#define do_not_expect_pkey_fault(msg) do { \
if (last_pkey_faults != pkey_faults) \
dprintf0("unexpected PKey fault: %s\n", msg); \
pkey_assert(last_pkey_faults == pkey_faults); \
} while (0)
int test_fds[10] = { -1 };
@ -1015,25 +1026,25 @@ void test_read_of_access_disabled_region(int *ptr, u16 pkey)
int ptr_contents;
dprintf1("disabling access to PKEY[%02d], doing read @ %p\n", pkey, ptr);
rdpkru();
read_pkey_reg();
pkey_access_deny(pkey);
ptr_contents = read_ptr(ptr);
dprintf1("*ptr: %d\n", ptr_contents);
expected_pk_fault(pkey);
expected_pkey_fault(pkey);
}
void test_write_of_write_disabled_region(int *ptr, u16 pkey)
{
dprintf1("disabling write access to PKEY[%02d], doing write\n", pkey);
pkey_write_deny(pkey);
*ptr = __LINE__;
expected_pk_fault(pkey);
expected_pkey_fault(pkey);
}
void test_write_of_access_disabled_region(int *ptr, u16 pkey)
{
dprintf1("disabling access to PKEY[%02d], doing write\n", pkey);
pkey_access_deny(pkey);
*ptr = __LINE__;
expected_pk_fault(pkey);
expected_pkey_fault(pkey);
}
void test_kernel_write_of_access_disabled_region(int *ptr, u16 pkey)
{
@ -1160,9 +1171,10 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
int new_pkey;
dprintf1("%s() alloc loop: %d\n", __func__, i);
new_pkey = alloc_pkey();
dprintf4("%s()::%d, err: %d pkru: 0x%x shadow: 0x%x\n", __func__,
__LINE__, err, __rdpkru(), shadow_pkru);
rdpkru(); /* for shadow checking */
dprintf4("%s()::%d, err: %d pkey_reg: 0x%x shadow: 0x%x\n",
__func__, __LINE__, err, __read_pkey_reg(),
shadow_pkey_reg);
read_pkey_reg(); /* for shadow checking */
dprintf2("%s() errno: %d ENOSPC: %d\n", __func__, errno, ENOSPC);
if ((new_pkey == -1) && (errno == ENOSPC)) {
dprintf2("%s() failed to allocate pkey after %d tries\n",
@ -1201,7 +1213,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
for (i = 0; i < nr_allocated_pkeys; i++) {
err = sys_pkey_free(allocated_pkeys[i]);
pkey_assert(!err);
rdpkru(); /* for shadow checking */
read_pkey_reg(); /* for shadow checking */
}
}
@ -1287,7 +1299,7 @@ void test_ptrace_of_child(int *ptr, u16 pkey)
pkey_assert(ret != -1);
/* Now access from the current task, and expect an exception: */
peek_result = read_ptr(ptr);
expected_pk_fault(pkey);
expected_pkey_fault(pkey);
/*
* Try to access the NON-pkey-protected "plain_ptr" via ptrace:
@ -1297,7 +1309,7 @@ void test_ptrace_of_child(int *ptr, u16 pkey)
pkey_assert(ret != -1);
/* Now access from the current task, and expect NO exception: */
peek_result = read_ptr(plain_ptr);
do_not_expect_pk_fault("read plain pointer after ptrace");
do_not_expect_pkey_fault("read plain pointer after ptrace");
ret = ptrace(PTRACE_DETACH, child_pid, ignored, 0);
pkey_assert(ret != -1);
@ -1347,17 +1359,17 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
pkey_assert(!ret);
pkey_access_deny(pkey);
dprintf2("pkru: %x\n", rdpkru());
dprintf2("pkey_reg: %x\n", read_pkey_reg());
/*
* Make sure this is an *instruction* fault
*/
madvise(p1, PAGE_SIZE, MADV_DONTNEED);
lots_o_noops_around_write(&scratch);
do_not_expect_pk_fault("executing on PROT_EXEC memory");
do_not_expect_pkey_fault("executing on PROT_EXEC memory");
ptr_contents = read_ptr(p1);
dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
expected_pk_fault(pkey);
expected_pkey_fault(pkey);
}
void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
@ -1378,15 +1390,15 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
ret = mprotect(p1, PAGE_SIZE, PROT_EXEC);
pkey_assert(!ret);
dprintf2("pkru: %x\n", rdpkru());
dprintf2("pkru: %x\n", read_pkey_reg());
/* Make sure this is an *instruction* fault */
madvise(p1, PAGE_SIZE, MADV_DONTNEED);
lots_o_noops_around_write(&scratch);
do_not_expect_pk_fault("executing on PROT_EXEC memory");
do_not_expect_pkey_fault("executing on PROT_EXEC memory");
ptr_contents = read_ptr(p1);
dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
expected_pk_fault(UNKNOWN_PKEY);
expected_pkey_fault(UNKNOWN_PKEY);
/*
* Put the memory back to non-PROT_EXEC. Should clear the
@ -1400,7 +1412,7 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
ret = mprotect(p1, PAGE_SIZE, PROT_READ|PROT_EXEC);
pkey_assert(!ret);
ptr_contents = read_ptr(p1);
do_not_expect_pk_fault("plain read on recently PROT_EXEC area");
do_not_expect_pkey_fault("plain read on recently PROT_EXEC area");
}
void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
@ -1442,7 +1454,7 @@ void run_tests_once(void)
for (test_nr = 0; test_nr < ARRAY_SIZE(pkey_tests); test_nr++) {
int pkey;
int orig_pkru_faults = pkru_faults;
int orig_pkey_faults = pkey_faults;
dprintf1("======================\n");
dprintf1("test %d preparing...\n", test_nr);
@ -1457,8 +1469,8 @@ void run_tests_once(void)
free_pkey_malloc(ptr);
sys_pkey_free(pkey);
dprintf1("pkru_faults: %d\n", pkru_faults);
dprintf1("orig_pkru_faults: %d\n", orig_pkru_faults);
dprintf1("pkey_faults: %d\n", pkey_faults);
dprintf1("orig_pkey_faults: %d\n", orig_pkey_faults);
tracing_off();
close_test_fds();
@ -1471,7 +1483,7 @@ void run_tests_once(void)
void pkey_setup_shadow(void)
{
shadow_pkru = __rdpkru();
shadow_pkey_reg = __read_pkey_reg();
}
int main(void)
@ -1495,7 +1507,7 @@ int main(void)
}
pkey_setup_shadow();
printf("startup pkru: %x\n", rdpkru());
printf("startup pkey_reg: %x\n", read_pkey_reg());
setup_hugetlbfs();
while (nr_iterations-- > 0)