selftests, powerpc, x86: Memory Protection Keys
Subsystems (4)
v19 cover selftests, powerpc, x86: Memory Protection Keys
Memory protection keys enables an application to protect its address space from inadvertent access by its own code.
This feature is now enabled on powerpc and has been available since 4.16-rc1. The patches move the selftests to arch neutral directory and enhance their test coverage.
Tested on powerpc64 and x86_64 (Skylake-SP).
Link to development branch:
https://github.com/sandip4n/linux/tree/pkey-selftests
Resending this based on feedback from maintainers who felt this can go in via the -mm tree. This has no other changes from the last version (v18) apart from being rebased.
Changelog
---------
Link to previous version (v18):
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=155970
v19:
(1) Rebased on top of latest master.
v18:
(1) Fixed issues with x86 multilib builds based on feedback from Dave.
(2) Moved patch 2 to the end of the series.
v17:
(1) Fixed issues with i386 builds when running on x86_64 based on feedback from Dave.
(2) Replaced patch 6 from previous version with patch 7. This addresses u64 format specifier related concerns that Michael had raised in v15.
v16:
(1) Rebased on top of latest master.
(2) Switched to u64 instead of using an arch-dependent pkey_reg_t type for references to the pkey register based on suggestions from Dave, Michal and Michael.
(3) Removed build time determination of page size based on suggestion from Michael.
(4) Fixed comment before the definition of __page_o_noops() from patch 13 ("selftests/vm/pkeys: Introduce powerpc support").
v15:
(1) Rebased on top of latest master.
(2) Addressed review comments from Dave Hansen.
(3) Moved code for getting or setting pkey bits to new helpers. These changes replace patch 7 of v14.
(4) Added a fix which ensures that the correct count of reserved keys is used across different platforms.
(5) Added a fix which ensures that the correct page size is used as powerpc supports both 4K and 64K pages.
v14:
(1) Incorporated another round of comments from Dave Hansen.
v13:
(1) Incorporated comments for Dave Hansen.
(2) Added one more test for correct pkey-0 behavior.
v12:
(1) Fixed the offset of pkey field in the siginfo structure for x86_64 and powerpc. And tries to use the actual field if the headers have it defined.
v11:
(1) Fixed a deadlock in the ptrace testcase.
v10 and prior:
(1) Moved the testcase to arch neutral directory.
(2) Split the changes into incremental patches.
Desnes A. Nunes do Rosario (1):
selftests/vm/pkeys: Fix number of reserved powerpc pkeys
Ram Pai (16):
selftests/x86/pkeys: Move selftests to arch-neutral directory selftests/vm/pkeys: Rename all references to pkru to a generic name selftests/vm/pkeys: Move generic definitions to header file selftests/vm/pkeys: Fix pkey_disable_clear() selftests/vm/pkeys: Fix assertion in pkey_disable_set/clear() selftests/vm/pkeys: Fix alloc_random_pkey() to make it really random selftests/vm/pkeys: Introduce generic pkey abstractions selftests/vm/pkeys: Introduce powerpc support selftests/vm/pkeys: Fix assertion in test_pkey_alloc_exhaust() selftests/vm/pkeys: Improve checks to determine pkey support selftests/vm/pkeys: Associate key on a mapped page and detect access
violation
selftests/vm/pkeys: Associate key on a mapped page and detect write
violation
selftests/vm/pkeys: Detect write violation on a mapped
access-denied-key page
selftests/vm/pkeys: Introduce a sub-page allocator selftests/vm/pkeys: Test correct behaviour of pkey-0 selftests/vm/pkeys: Override access right definitions on powerpc
Sandipan Das (5):
selftests: vm: pkeys: Use sane types for pkey register
selftests: vm: pkeys: Add helpers for pkey bits
selftests: vm: pkeys: Use the correct huge page size
selftests: vm: pkeys: Use the correct page size on powerpc
selftests: vm: pkeys: Fix multilib builds for x86
Thiago Jung Bauermann (2):
selftests/vm/pkeys: Move some definitions to arch-specific header selftests/vm/pkeys: Make gcc check arguments of sigsafe_printf()
tools/testing/selftests/vm/.gitignore | 1 +
tools/testing/selftests/vm/Makefile | 73 ++
tools/testing/selftests/vm/pkey-helpers.h | 225 ++++++
tools/testing/selftests/vm/pkey-powerpc.h | 136 ++++
tools/testing/selftests/vm/pkey-x86.h | 181 +++++
.../selftests/{x86 => vm}/protection_keys.c | 696 ++++++++++--------
tools/testing/selftests/x86/.gitignore | 1 -
tools/testing/selftests/x86/Makefile | 2 +-
tools/testing/selftests/x86/pkey-helpers.h | 219 ------
9 files changed, 1002 insertions(+), 532 deletions(-)
create mode 100644 tools/testing/selftests/vm/pkey-helpers.h
create mode 100644 tools/testing/selftests/vm/pkey-powerpc.h
create mode 100644 tools/testing/selftests/vm/pkey-x86.h
rename tools/testing/selftests/{x86 => vm}/protection_keys.c (74%)
delete mode 100644 tools/testing/selftests/x86/pkey-helpers.hSignature · 1 line
2.17.1
PATCH v19 1/24 selftests/x86/pkeys: Move selftests to arch-neutral directory
From: Ram Pai <[email protected]>
---
tools/testing/selftests/vm/.gitignore | 1 +
tools/testing/selftests/vm/Makefile | 1 +
tools/testing/selftests/{x86 => vm}/pkey-helpers.h | 0
tools/testing/selftests/{x86 => vm}/protection_keys.c | 0
tools/testing/selftests/x86/.gitignore | 1 -
tools/testing/selftests/x86/Makefile | 2 +-
6 files changed, 3 insertions(+), 2 deletions(-)
rename tools/testing/selftests/{x86 => vm}/pkey-helpers.h (100%)
rename tools/testing/selftests/{x86 => vm}/protection_keys.c (100%)tools/testing/selftests/vm/.gitignore +1 -0
@@ -14,3 +14,4 @@ virtual_address_range gup_benchmark va_128TBswitch map_fixed_noreplace +protection_keys
tools/testing/selftests/vm/Makefile +1 -0
@@ -18,6 +18,7 @@ TEST_GEN_FILES += on-fault-limit TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += transhuge-stress TEST_GEN_FILES += userfaultfd +TEST_GEN_FILES += protection_keys ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64)) TEST_GEN_FILES += va_128TBswitch
tools/testing/selftests/vm/pkey-helpers.h renamed from tools/testing/selftests/x86/pkey-helpers.h +0 -0
tools/testing/selftests/vm/protection_keys.c renamed from tools/testing/selftests/x86/protection_keys.c +0 -0
tools/testing/selftests/x86/.gitignore +0 -1
@@ -11,5 +11,4 @@ ldt_gdt iopl mpx-mini-test ioperm -protection_keys test_vdso
tools/testing/selftests/x86/Makefile +1 -1
@@ -12,7 +12,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie) TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ check_initial_reg_state sigreturn iopl ioperm \ - protection_keys test_vdso test_vsyscall mov_ss_trap \ + test_vdso test_vsyscall mov_ss_trap \ syscall_arg_fault TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \
Signature · 1 line
2.17.1
PATCH v19 2/24 selftests/vm/pkeys: Rename all references to pkru to a generic name
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
This renames PKRU references to "pkey_reg" or "pkey" based on the usage.
--- tools/testing/selftests/vm/pkey-helpers.h | 85 +++---- tools/testing/selftests/vm/protection_keys.c | 240 ++++++++++--------- 2 files changed, 170 insertions(+), 155 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +44 -41
@@ -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; asmvolatile (".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); asmvolatile (".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 ; }
tools/testing/selftests/vm/protection_keys.c +126 -114
527 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v19 3/24 selftests/vm/pkeys: Move generic definitions to header file
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Moved all the generic definition and helper functions to the header file.
--- tools/testing/selftests/vm/pkey-helpers.h | 35 +++++++++++++++++--- tools/testing/selftests/vm/protection_keys.c | 27 --------------- 2 files changed, 30 insertions(+), 32 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +30 -5
@@ -13,6 +13,14 @@#include <ucontext.h> #include <sys/mman.h> +/* Define some kernel-like types */ +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t + +#define PTR_ERR_ENOTSUP ((void *)-ENOTSUP) +#define NR_PKEYS 16#define PKEY_BITS_PER_PKEY 2
@@ -53,6 +61,18 @@ static inline void sigsafe_printf(const char *format, ...) #define dprintf3(args...) dprintf_level(3, args) #define dprintf4(args...) dprintf_level(4, args) +extern void abort_hooks (void ); +#define pkey_assert (condition) do { \ + if (!(condition)) { \ + dprintf0("assert() at %s::%d test_nr: %d iteration: %d\n", \ + __FILE__, __LINE__, \ + test_nr, iteration_nr); \ + dprintf0("errno at assert: %d", errno); \ + abort_hooks(); \ + exit(__LINE__); \ + } \ +} while (0) +extern unsigned int shadow_pkey_reg;static inline unsigned int __read_pkey_reg (void ) {
@@ -137,11 +157,6 @@ static inline void __pkey_write_allow(int pkey, int do_allow_write)dprintf4 ("pkey_reg now: %08x\n" ,read_pkey_reg ()); } -#define PROT_PKEY0 0x10/* protection key value (bit 0) */ -#define PROT_PKEY1 0x20/* protection key value (bit 1) */ -#define PROT_PKEY2 0x40/* protection key value (bit 2) */ -#define PROT_PKEY3 0x80/* protection key value (bit 3) */ -#define PAGE_SIZE 4096#define MB (1<<20)
@@ -219,4 +234,14 @@ int pkey_reg_xstate_offset(void)return xstate_offset; } +#define ARRAY_SIZE (x) (sizeof(x) / sizeof(*(x))) +#define ALIGN_UP (x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1)) +#define ALIGN_DOWN (x, align_to) ((x) & ~((align_to)-1)) +#define ALIGN_PTR_UP (p, ptr_align_to) \ + ((typeof(p))ALIGN_UP((unsigned long)(p), ptr_align_to)) +#define ALIGN_PTR_DOWN (p, ptr_align_to) \ + ((typeof(p))ALIGN_DOWN((unsigned long)(p), ptr_align_to)) +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) +#endif /* _PKEYS_HELPER_H */
tools/testing/selftests/vm/protection_keys.c +0 -27
@@ -51,31 +51,10 @@ int test_nr;unsigned int shadow_pkey_reg;#define HPAGE_SIZE (1UL<<21) -#define ARRAY_SIZE (x) (sizeof(x) / sizeof(*(x))) -#define ALIGN_UP (x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1)) -#define ALIGN_DOWN (x, align_to) ((x) & ~((align_to)-1)) -#define ALIGN_PTR_UP (p, ptr_align_to) ((typeof(p))ALIGN_UP((unsigned long)(p), ptr_align_to)) -#define ALIGN_PTR_DOWN (p, ptr_align_to) ((typeof(p))ALIGN_DOWN((unsigned long)(p), ptr_align_to)) -#define __stringify_1(x...) #x -#define __stringify(x...) __stringify_1(x) - -#define PTR_ERR_ENOTSUP ((void *)-ENOTSUP)int dprint_in_signal;char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE ]; -extern void abort_hooks (void ); -#define pkey_assert (condition) do { \ - if (!(condition)) { \ - dprintf0("assert() at %s::%d test_nr: %d iteration: %d\n", \ - __FILE__, __LINE__, \ - test_nr, iteration_nr); \ - dprintf0("errno at assert: %d", errno); \ - abort_hooks(); \ - exit(__LINE__); \ - } \ -} while (0) -void cat_into_file (char *str,char *file) {int fd =open (file,O_RDWR );
@@ -186,12 +165,6 @@ void lots_o_noops_around_write(int *write_to_me)dprintf3 ("%s() done\n" , __func__); } -/* Define some kernel-like types */ -#define u8 uint8_t -#define u16 uint16_t -#define u32 uint32_t -#define u64 uint64_t -#ifdef __i386__#ifndef SYS_mprotect_key
Signature · 1 line
2.17.1
PATCH v19 4/24 selftests/vm/pkeys: Move some definitions to arch-specific header
In reply to Sandipan DasFrom: Thiago Jung Bauermann <[email protected]>
In preparation for multi-arch support, move definitions which have arch-specific values to x86-specific header.
--- tools/testing/selftests/vm/pkey-helpers.h | 111 +------------ tools/testing/selftests/vm/pkey-x86.h | 156 +++++++++++++++++++ tools/testing/selftests/vm/protection_keys.c | 47 ------ 3 files changed, 162 insertions(+), 152 deletions(-) create mode 100644 tools/testing/selftests/vm/pkey-x86.h
tools/testing/selftests/vm/pkey-helpers.h +6 -105
@@ -21,9 +21,6 @@#define PTR_ERR_ENOTSUP ((void *)-ENOTSUP) -#define NR_PKEYS 16 -#define PKEY_BITS_PER_PKEY 2 -#ifndef DEBUG_LEVEL #define DEBUG_LEVEL 0#endif
@@ -73,19 +70,13 @@ extern void abort_hooks(void); } \ } while (0) +#if defined(__i386__) || defined(__x86_64__)/* arch */ +#include "pkey-x86.h" +#else /* arch */ +#error Architecture not supported +#endif /* arch */ +extern unsigned int shadow_pkey_reg; -static inline unsigned int __read_pkey_reg (void ) -{ -unsigned int eax, edx; -unsigned int ecx =0 ; -unsigned int pkey_reg; - - asmvolatile (".byte 0x0f,0x01,0xee\n\t" - :"=a" (eax),"=d" (edx) - :"c" (ecx)); - pkey_reg = eax; -return pkey_reg; -}static inline unsigned int _read_pkey_reg (int line) {
@@ -100,19 +91,6 @@ static inline unsigned int _read_pkey_reg(int line)#define read_pkey_reg () _read_pkey_reg(__LINE__) -static inline void __write_pkey_reg (unsigned int pkey_reg) -{ -unsigned int eax = pkey_reg; -unsigned int ecx =0 ; -unsigned int edx =0 ; - -dprintf4 ("%s() changing %08x to %08x\n" , __func__, -__read_pkey_reg (), pkey_reg); - asmvolatile (".byte 0x0f,0x01,0xef\n\t" - : :"a" (eax),"c" (ecx),"d" (edx)); -assert (pkey_reg ==__read_pkey_reg ()); -} -static inline void write_pkey_reg (unsigned int pkey_reg) { dprintf4("%s() changing %08x to %08x\n", __func__,
@@ -157,83 +135,6 @@ static inline void __pkey_write_allow(int pkey, int do_allow_write)dprintf4 ("pkey_reg now: %08x\n" ,read_pkey_reg ()); } -#define PAGE_SIZE 4096 -#define MB (1<<20) - -static inline void __cpuid (unsigned int *eax,unsigned int *ebx, -unsigned int *ecx,unsigned int *edx) -{ -/* ecx is often an input as well as an output. */ - asmvolatile ( -"cpuid;" - :"=a" (*eax), -"=b" (*ebx), -"=c" (*ecx), -"=d" (*edx) - :"0" (*eax),"2" (*ecx)); -} - -/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx) */ -#define X86_FEATURE_PKU (1<<3)/* Protection Keys for Userspace */ -#define X86_FEATURE_OSPKE (1<<4)/* OS Protection Keys Enable */ - -static inline int cpu_has_pku (void ) -{ -unsigned int eax; -unsigned int ebx; -unsigned int ecx; -unsigned int edx; - - eax =0x7 ; - ecx =0x0 ; -__cpuid (&eax, &ebx, &ecx, &edx); - -if (!(ecx &X86_FEATURE_PKU )) { -dprintf2 ("cpu does not have PKU\n" ); -return 0 ; - } -if (!(ecx &X86_FEATURE_OSPKE )) { -dprintf2 ("cpu does not have OSPKE\n" ); -return 0 ; - } -return 1 ; -} - -#define XSTATE_PKEY_BIT (9) -#define XSTATE_PKEY 0x200 - -int pkey_reg_xstate_offset (void ) -{ -unsigned int eax; -unsigned int ebx; -unsigned int ecx; -unsigned int edx; -int xstate_offset; -int xstate_size; -unsigned long XSTATE_CPUID =0xd ; -int leaf; - -/* 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_PKEY_BIT ) { - xstate_offset = ebx; - xstate_size = eax; - } - } - -if (xstate_size ==0 ) { -printf ("could not find size/offset of PKEY in xsave state\n" ); -return 0 ; - } - -return xstate_offset; -} -#define ARRAY_SIZE (x) (sizeof(x) / sizeof(*(x)))#define ALIGN_UP (x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1))#define ALIGN_DOWN (x, align_to) ((x) & ~((align_to)-1))
tools/testing/selftests/vm/pkey-x86.h new file +156 -0
156 lines not on this page · raw message
tools/testing/selftests/vm/protection_keys.c +0 -47
71 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v19 5/24 selftests/vm/pkeys: Make gcc check arguments of sigsafe_printf()
In reply to Sandipan DasFrom: Thiago Jung Bauermann <[email protected]>
This will help us ensure we print pkey_reg_t values correctly in different architectures.
--- tools/testing/selftests/vm/pkey-helpers.h | 4 ++++ 1 file changed, 4 insertions(+)
tools/testing/selftests/vm/pkey-helpers.h +4 -0
@@ -27,6 +27,10 @@#define DPRINT_IN_SIGNAL_BUF_SIZE 4096extern int dprint_in_signal;extern char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE ]; + +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif static inline void sigsafe_printf (const char *format, ...) {va_list ap;
Signature · 1 line
2.17.1
PATCH v19 6/24 selftests: vm: pkeys: Use sane types for pkey register
In reply to Sandipan DasThe size of the pkey register can vary across architectures. This converts the data type of all its references to u64 in preparation for multi-arch support.
To keep the definition of the u64 type consistent and remove format specifier related warnings, __SANE_USERSPACE_TYPES__ is defined as suggested by Michael Ellerman.
--- tools/testing/selftests/vm/pkey-helpers.h | 31 +++---- tools/testing/selftests/vm/pkey-x86.h | 8 +- tools/testing/selftests/vm/protection_keys.c | 86 ++++++++++++-------- 3 files changed, 72 insertions(+), 53 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +16 -15
@@ -14,10 +14,10 @@#include <sys/mman.h> /* Define some kernel-like types */ -#define u8 uint8_t -#define u16 uint16_t -#define u32 uint32_t -#define u64 uint64_t +#define u8 __u8 +#define u16 __u16 +#define u32 __u32 +#define u64 __u64#define PTR_ERR_ENOTSUP ((void *)-ENOTSUP)
@@ -80,13 +80,14 @@ extern void abort_hooks(void);#error Architecture not supported#endif /* arch */ -extern unsigned int shadow_pkey_reg; +extern u64 shadow_pkey_reg; -static inline unsigned int _read_pkey_reg (int line) +static inline u64 _read_pkey_reg (int line) { -unsigned int pkey_reg =__read_pkey_reg (); +u64 pkey_reg =__read_pkey_reg (); -dprintf4 ("read_pkey_reg(line=%d) pkey_reg: %x shadow: %x\n" , +dprintf4 ("read_pkey_reg(line=%d) pkey_reg: %016llx" +" shadow: %016llx\n" , line, pkey_reg, shadow_pkey_reg);assert (pkey_reg == shadow_pkey_reg);
@@ -95,15 +96,15 @@ static inline unsigned int _read_pkey_reg(int line)#define read_pkey_reg () _read_pkey_reg(__LINE__) -static inline void write_pkey_reg (unsigned int pkey_reg) +static inline void write_pkey_reg (u64 pkey_reg) { -dprintf4 ("%s() changing %08x to %08x\n" , __func__, +dprintf4 ("%s() changing %016llx to %016llx\n" , __func__,__read_pkey_reg (), pkey_reg);/* will do the shadow check for us: */ read_pkey_reg ();__write_pkey_reg (pkey_reg); shadow_pkey_reg = pkey_reg; -dprintf4 ("%s(%08x) pkey_reg: %08x\n" , __func__, +dprintf4 ("%s(%016llx) pkey_reg: %016llx\n" , __func__, pkey_reg,__read_pkey_reg ()); }
@@ -113,7 +114,7 @@ static inline void write_pkey_reg(unsigned int pkey_reg)*/ static inline void __pkey_access_allow (int pkey,int do_allow) { -unsigned int pkey_reg =read_pkey_reg (); +u64 pkey_reg =read_pkey_reg ();int bit = pkey *2 ;if (do_allow)
@@ -121,13 +122,13 @@ static inline void __pkey_access_allow(int pkey, int do_allow)else pkey_reg |= (1 <<bit); -dprintf4 ("pkey_reg now: %08x\n" ,read_pkey_reg ()); +dprintf4 ("pkey_reg now: %016llx\n" ,read_pkey_reg ());write_pkey_reg (pkey_reg); }static inline void __pkey_write_allow (int pkey,int do_allow_write) { -long pkey_reg =read_pkey_reg (); +u64 pkey_reg =read_pkey_reg ();int bit = pkey *2 +1 ;if (do_allow_write)
@@ -136,7 +137,7 @@ static inline void __pkey_write_allow(int pkey, int do_allow_write) pkey_reg |= (1 <<bit);write_pkey_reg (pkey_reg); -dprintf4 ("pkey_reg now: %08x\n" ,read_pkey_reg ()); +dprintf4 ("pkey_reg now: %016llx\n" ,read_pkey_reg ()); }#define ARRAY_SIZE (x) (sizeof(x) / sizeof(*(x)))
tools/testing/selftests/vm/pkey-x86.h +4 -4
@@ -53,11 +53,11 @@ static inline void __page_o_noops(void) asm(".rept 512 ; nopl 0x7eeeeeee(%eax) ; .endr" ); } -static inline unsigned int __read_pkey_reg (void ) +static inline u64 __read_pkey_reg (void ) {unsigned int eax, edx;unsigned int ecx =0 ; -unsigned int pkey_reg; +unsigned pkey_reg; asmvolatile (".byte 0x0f,0x01,0xee\n\t" : "=a" (eax), "=d" (edx)
@@ -66,13 +66,13 @@ static inline unsigned int __read_pkey_reg(void)return pkey_reg; } -static inline void __write_pkey_reg (unsigned int pkey_reg) +static inline void __write_pkey_reg (u64 pkey_reg) {unsigned int eax = pkey_reg;unsigned int ecx =0 ;unsigned int edx =0 ; -dprintf4 ("%s() changing %08x to %08x\n" , __func__, +dprintf4 ("%s() changing %016llx to %016llx\n" , __func__,__read_pkey_reg (), pkey_reg); asmvolatile (".byte 0x0f,0x01,0xef\n\t" : :"a" (eax),"c" (ecx),"d" (edx));
tools/testing/selftests/vm/protection_keys.c +52 -34
260 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v19 7/24 selftests: vm: pkeys: Add helpers for pkey bits
In reply to Sandipan DasThis introduces some functions that help with setting or clearing bits of a particular pkey. This also adds an abstraction for getting a pkey's bit position in the pkey register as this may vary across architectures.
--- tools/testing/selftests/vm/pkey-helpers.h | 22 ++++++++++++++ tools/testing/selftests/vm/pkey-x86.h | 5 +++ tools/testing/selftests/vm/protection_keys.c | 32 ++++++-------------- 3 files changed, 36 insertions(+), 23 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +22 -0
@@ -80,6 +80,28 @@ extern void abort_hooks(void);#error Architecture not supported#endif /* arch */ +#define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE) + +static inline u64 set_pkey_bits (u64 reg,int pkey,u64 flags) +{ +u32 shift =pkey_bit_position (pkey); +/* mask out bits from pkey in old value */ + reg &= ~((u64 )PKEY_MASK << shift); +/* OR in new bits for pkey */ + reg |= (flags &PKEY_MASK ) << shift; +return reg; +} + +static inline u64 get_pkey_bits (u64 reg,int pkey) +{ +u32 shift =pkey_bit_position (pkey); +/* +* shift down the relevant bits to the lowest two, then +* mask off all the other higher bits +*/ +return ((reg >> shift) &PKEY_MASK ); +} +extern u64 shadow_pkey_reg;static inline u64 _read_pkey_reg (int line)
tools/testing/selftests/vm/pkey-x86.h +5 -0
@@ -118,6 +118,11 @@ static inline int cpu_has_pku(void)return 1 ; } +static inline u32 pkey_bit_position (int pkey) +{ +return pkey *PKEY_BITS_PER_PKEY ; +} +#define XSTATE_PKEY_BIT (9)#define XSTATE_PKEY 0x200
tools/testing/selftests/vm/protection_keys.c +9 -23
@@ -334,25 +334,13 @@ pid_t fork_lazy_child(void)static u32 hw_pkey_get (int pkey,unsigned long flags) { -u32 mask = (PKEY_DISABLE_ACCESS |PKEY_DISABLE_WRITE );u64 pkey_reg =__read_pkey_reg (); -u64 shifted_pkey_reg; -u32 masked_pkey_reg;dprintf1 ("%s(pkey=%d, flags=%lx) = %x / %d\n" , __func__, pkey, flags,0 ,0 );dprintf2 ("%s() raw pkey_reg: %016llx\n" , __func__, pkey_reg); - shifted_pkey_reg = (pkey_reg >> (pkey *PKEY_BITS_PER_PKEY )); -dprintf2 ("%s() shifted_pkey_reg: %016llx\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_pkey_reg; +return (u32 )get_pkey_bits (pkey_reg, pkey); }static int hw_pkey_set (int pkey,unsigned long rights,unsigned long flags)
@@ -364,12 +352,8 @@ static int hw_pkey_set(int pkey, unsigned long rights, unsigned long flags)/* make sure that 'rights' only contains the bits we expect: */ assert (!(rights & ~mask)); -/* copy old pkey_reg */ - new_pkey_reg = old_pkey_reg; -/* mask out bits from pkey in old value: */ - new_pkey_reg &= ~(mask << (pkey *PKEY_BITS_PER_PKEY )); -/* OR in new bits for pkey: */ - new_pkey_reg |= (rights << (pkey *PKEY_BITS_PER_PKEY )); +/* modify bits accordingly in old pkey_reg and assign it */ + new_pkey_reg =set_pkey_bits (old_pkey_reg, pkey, rights);__write_pkey_reg (new_pkey_reg);
@@ -403,7 +387,7 @@ void pkey_disable_set(int pkey, int flags) ret =hw_pkey_set (pkey, pkey_rights, syscall_flags);assert (!ret);/* pkey_reg and flags have the same format */ - shadow_pkey_reg |= flags << (pkey *2 ); + shadow_pkey_reg =set_pkey_bits (shadow_pkey_reg, pkey, pkey_rights);dprintf1 ("%s(%d) shadow: 0x%016llx\n" , __func__, pkey, shadow_pkey_reg);
@@ -437,7 +421,7 @@ void pkey_disable_clear(int pkey, int flags) pkey_rights |= flags; ret =hw_pkey_set (pkey, pkey_rights,0 ); - shadow_pkey_reg &= ~(flags << (pkey *2 )); + shadow_pkey_reg =set_pkey_bits (shadow_pkey_reg, pkey, pkey_rights);pkey_assert (ret >=0 ); pkey_rights =hw_pkey_get (pkey, syscall_flags);
@@ -513,7 +497,8 @@ int alloc_pkey(void) shadow_pkey_reg);if (ret) {/* clear both the bits: */ - shadow_pkey_reg &= ~(0x3 << (ret *2 )); + shadow_pkey_reg =set_pkey_bits (shadow_pkey_reg, ret, + ~PKEY_MASK ); dprintf4("%s()::%d, ret: %d pkey_reg: 0x%016llx" " shadow: 0x%016llx\n", __func__,
@@ -523,7 +508,8 @@ int alloc_pkey(void)* move the new state in from init_val * (remember, we cheated and init_val == pkey_reg format) */ - shadow_pkey_reg |= (init_val << (ret *2 )); + shadow_pkey_reg =set_pkey_bits (shadow_pkey_reg, ret, + init_val); } dprintf4("%s()::%d, ret: %d pkey_reg: 0x%016llx" " shadow: 0x%016llx\n",
Signature · 1 line
2.17.1
PATCH v19 8/24 selftests/vm/pkeys: Fix pkey_disable_clear()
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Currently, pkey_disable_clear() sets the specified bits instead clearing them. This has been dead code up to now because its only callers i.e. pkey_access/write_allow() are also unused.
--- tools/testing/selftests/vm/protection_keys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/protection_keys.c +2 -2
@@ -418,7 +418,7 @@ void pkey_disable_clear(int pkey, int flags) pkey, pkey, pkey_rights);pkey_assert (pkey_rights >=0 ); - pkey_rights |= flags; + pkey_rights &= ~flags; ret =hw_pkey_set (pkey, pkey_rights,0 ); shadow_pkey_reg =set_pkey_bits (shadow_pkey_reg, pkey, pkey_rights);
@@ -431,7 +431,7 @@ void pkey_disable_clear(int pkey, int flags)dprintf1 ("%s(%d) pkey_reg: 0x%016llx\n" , __func__, pkey,read_pkey_reg ());if (flags) -assert (read_pkey_reg () > orig_pkey_reg); +assert (read_pkey_reg () < orig_pkey_reg); }void pkey_write_allow (int pkey)
Signature · 1 line
2.17.1
PATCH v19 9/24 selftests/vm/pkeys: Fix assertion in pkey_disable_set/clear()
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
In some cases, a pkey's bits need not necessarily change in a way that the value of the pkey register increases when performing a pkey_disable_set() or decreases when performing a pkey_disable_clear().
For example, on powerpc, if a pkey's current state is PKEY_DISABLE_ACCESS and we perform a pkey_write_disable() on it, the bits still remain the same. We will observe something similar when the pkey's current state is 0 and a pkey_access_enable() is performed on it.
Either case would cause some assertions to fail. This fixes the problem.
--- tools/testing/selftests/vm/protection_keys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/protection_keys.c +2 -2
@@ -400,7 +400,7 @@ void pkey_disable_set(int pkey, int flags)dprintf1 ("%s(%d) pkey_reg: 0x%016llx\n" , __func__, pkey,read_pkey_reg ());if (flags) -pkey_assert (read_pkey_reg () > orig_pkey_reg); +pkey_assert (read_pkey_reg () >= orig_pkey_reg);dprintf1 ("END<---%s(%d, 0x%x)\n" , __func__, pkey, flags); }
@@ -431,7 +431,7 @@ void pkey_disable_clear(int pkey, int flags)dprintf1 ("%s(%d) pkey_reg: 0x%016llx\n" , __func__, pkey,read_pkey_reg ());if (flags) -assert (read_pkey_reg () < orig_pkey_reg); +assert (read_pkey_reg () <= orig_pkey_reg); }void pkey_write_allow (int pkey)
Signature · 1 line
2.17.1
PATCH v19 10/24 selftests/vm/pkeys: Fix alloc_random_pkey() to make it really random
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
alloc_random_pkey() was allocating the same pkey every time. Not all pkeys were geting tested. This fixes it.
--- tools/testing/selftests/vm/protection_keys.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/vm/protection_keys.c +2 -1
@@ -25,6 +25,7 @@#define __SANE_USERSPACE_TYPES__#include <errno.h> #include <linux/futex.h> +#include <time.h> #include <sys/time.h> #include <sys/syscall.h> #include <string.h>
@@ -546,10 +547,10 @@ int alloc_random_pkey(void)int nr_alloced =0 ;int random_index;memset (alloced_pkeys,0 ,sizeof (alloced_pkeys)); +srand ((unsigned int )time (NULL ));/* allocate every possible key and make a note of which ones we got */ max_nr_pkey_allocs =NR_PKEYS ; - max_nr_pkey_allocs =1 ;for (i =0 ; i < max_nr_pkey_allocs; i++) {int new_pkey =alloc_pkey ();if (new_pkey <0 )
Signature · 1 line
2.17.1
PATCH v19 11/24 selftests: vm: pkeys: Use the correct huge page size
In reply to Sandipan DasThe huge page size can vary across architectures. This will ensure that the correct huge page size is used when accessing the hugetlb controls under sysfs. Instead of using a hardcoded page size (i.e. 2MB), this now uses the HPAGE_SIZE macro which is arch-specific.
--- tools/testing/selftests/vm/protection_keys.c | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-)
tools/testing/selftests/vm/protection_keys.c +16 -7
@@ -739,12 +739,15 @@ void *malloc_pkey_anon_huge(long size, int prot, u16 pkey) }int hugetlb_setup_ok; +#define SYSFS_FMT_NR_HUGE_PAGES "/sys/kernel/mm/hugepages/hugepages-%ldkB/nr_hugepages"#define GET_NR_HUGE_PAGES 10void setup_hugetlbfs (void ) {int err;int fd; -char buf[] ="123" ; +char buf[256 ]; +long hpagesz_kb; +long hpagesz_mb;if (geteuid () !=0 ) {fprintf (stderr,"WARNING: not run as root, can not do hugetlb test\n" );
@@ -755,11 +758,16 @@ void setup_hugetlbfs(void)/* * Now go make sure that we got the pages and that they -* are 2M pages. Someone might have made 1G the default. +* are PMD-level pages. Someone might have made PUD-level +* pages the default. */ - fd =open ("/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" ,O_RDONLY ); + hpagesz_kb =HPAGE_SIZE /1024 ; + hpagesz_mb = hpagesz_kb /1024 ; +sprintf (buf,SYSFS_FMT_NR_HUGE_PAGES , hpagesz_kb); + fd =open (buf,O_RDONLY );if (fd <0 ) { -perror ("opening sysfs 2M hugetlb config" ); +fprintf (stderr,"opening sysfs %ldM hugetlb config: %s\n" , + hpagesz_mb,strerror (errno));return ; }
@@ -767,13 +775,14 @@ void setup_hugetlbfs(void) err =read (fd, buf,sizeof (buf)-1 );close (fd);if (err <=0 ) { -perror ("reading sysfs 2M hugetlb config" ); +fprintf (stderr,"reading sysfs %ldM hugetlb config: %s\n" , + hpagesz_mb,strerror (errno));return ; }if (atoi (buf) !=GET_NR_HUGE_PAGES ) { -fprintf (stderr,"could not confirm 2M pages, got: '%s' expected %d\n" , - buf,GET_NR_HUGE_PAGES ); +fprintf (stderr,"could not confirm %ldM pages, got: '%s' expected %d\n" , + hpagesz_mb, buf,GET_NR_HUGE_PAGES );return ; }
Signature · 1 line
2.17.1
PATCH v19 12/24 selftests/vm/pkeys: Introduce generic pkey abstractions
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
This introduces some generic abstractions and provides the corresponding architecture-specfic implementations for these abstractions.
--- tools/testing/selftests/vm/pkey-helpers.h | 12 ++++++++++++ tools/testing/selftests/vm/pkey-x86.h | 15 +++++++++++++++ tools/testing/selftests/vm/protection_keys.c | 8 ++------ 3 files changed, 29 insertions(+), 6 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +12 -0
@@ -74,6 +74,9 @@ extern void abort_hooks(void); } \ }while (0 ) +__attribute__((noinline)) int read_ptr(int *ptr); +void expected_pkey_fault (int pkey); +#if defined(__i386__) || defined(__x86_64__)/* arch */ #include "pkey-x86.h" #else /* arch */
@@ -172,4 +175,13 @@ static inline void __pkey_write_allow(int pkey, int do_allow_write) #define __stringify_1(x...) #x #define __stringify(x...) __stringify_1(x) +static inline u32 *siginfo_get_pkey_ptr (siginfo_t *si) +{ +#ifdef si_pkey +return &si->si_pkey; +#else +return (u32 *)(((u8 *)si) + si_pkey_offset); +#endif +} +#endif /* _PKEYS_HELPER_H */
tools/testing/selftests/vm/pkey-x86.h +15 -0
@@ -42,6 +42,7 @@#endif #define NR_PKEYS 16 +#define NR_RESERVED_PKEYS 2/* pkey-0 and exec-only-pkey */ #define PKEY_BITS_PER_PKEY 2#define HPAGE_SIZE (1UL<<21)#define PAGE_SIZE 4096
@@ -158,4 +159,18 @@ int pkey_reg_xstate_offset(void) return xstate_offset; } +static inline int get_arch_reserved_keys (void ) +{ +return NR_RESERVED_PKEYS ; +} + +void expect_fault_on_read_execonly_key (void *p1,int pkey) +{ +int ptr_contents; + + ptr_contents =read_ptr (p1); +dprintf2 ("ptr (%p) contents@%d: %x\n" , p1, __LINE__, ptr_contents); +expected_pkey_fault (pkey); +} +#endif /* _PKEYS_X86_H */
tools/testing/selftests/vm/protection_keys.c +2 -6
@@ -1307,9 +1307,7 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)madvise (p1,PAGE_SIZE ,MADV_DONTNEED );lots_o_noops_around_write (&scratch);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_pkey_fault (pkey); +expect_fault_on_read_execonly_key (p1, pkey); }void test_implicit_mprotect_exec_only_memory (int *ptr,u16 pkey)
@@ -1336,9 +1334,7 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)madvise (p1,PAGE_SIZE ,MADV_DONTNEED );lots_o_noops_around_write (&scratch);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_pkey_fault (UNKNOWN_PKEY ); +expect_fault_on_read_execonly_key (p1,UNKNOWN_PKEY );/* * Put the memory back to non-PROT_EXEC. Should clear the
Signature · 1 line
2.17.1
PATCH v19 13/24 selftests/vm/pkeys: Introduce powerpc support
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
This makes use of the abstractions added earlier and introduces support for powerpc.
For powerpc, after receiving the SIGSEGV, the signal handler must explicitly restore access permissions for the faulting pkey to allow the test to continue. As this makes use of pkey_access_allow(), all of its dependencies and other similar functions have been moved ahead of the signal handler.
--- tools/testing/selftests/vm/pkey-helpers.h | 2 + tools/testing/selftests/vm/pkey-powerpc.h | 90 +++++++ tools/testing/selftests/vm/protection_keys.c | 269 ++++++++++--------- 3 files changed, 233 insertions(+), 128 deletions(-) create mode 100644 tools/testing/selftests/vm/pkey-powerpc.h
tools/testing/selftests/vm/pkey-helpers.h +2 -0
@@ -79,6 +79,8 @@ void expected_pkey_fault(int pkey);#if defined(__i386__) || defined(__x86_64__)/* arch */ #include "pkey-x86.h" +#elif defined(__powerpc64__)/* arch */ +#include "pkey-powerpc.h" #else /* arch */ #error Architecture not supported#endif /* arch */
tools/testing/selftests/vm/pkey-powerpc.h new file +90 -0
90 lines not on this page · raw message
tools/testing/selftests/vm/protection_keys.c +141 -128
346 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v19 14/24 selftests/vm/pkeys: Fix number of reserved powerpc pkeys
In reply to Sandipan DasFrom: "Desnes A. Nunes do Rosario" <[email protected]>
The number of reserved pkeys in a PowerNV environment is different from that on PowerVM or KVM.
Tested on PowerVM and PowerNV environments.
--- tools/testing/selftests/vm/pkey-powerpc.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/pkey-powerpc.h +20 -2
@@ -28,7 +28,10 @@#define NR_RESERVED_PKEYS_4K 27/* pkey-0, pkey-1, exec-only-pkey and 24 other keys that cannot be represented in the PTE */ -#define NR_RESERVED_PKEYS_64K 3/* pkey-0, pkey-1 and exec-only-pkey */ +#define NR_RESERVED_PKEYS_64K_3KEYS 3/* PowerNV and KVM: pkey-0, +pkey-1 and exec-only key */ +#define NR_RESERVED_PKEYS_64K_4KEYS 4/* PowerVM: pkey-0, pkey-1, +pkey-31 and exec-only key */ #define PKEY_BITS_PER_PKEY 2#define HPAGE_SIZE (1UL << 24)#define PAGE_SIZE (1UL << 16)
@@ -65,12 +68,27 @@ static inline int cpu_has_pku(void)return 1 ; } +static inline bool arch_is_powervm () +{ +struct stat buf; + +if ((stat ("/sys/firmware/devicetree/base/ibm,partition-name" , &buf) ==0 ) && + (stat ("/sys/firmware/devicetree/base/hmc-managed?" , &buf) ==0 ) && + (stat ("/sys/firmware/devicetree/base/chosen/qemu,graphic-width" , &buf) ==-1 ) ) +return true; + +return false; +} +static inline int get_arch_reserved_keys (void ) {if (sysconf (_SC_PAGESIZE) ==4096 )return NR_RESERVED_PKEYS_4K ;else -return NR_RESERVED_PKEYS_64K ; +if (arch_is_powervm ()) +return NR_RESERVED_PKEYS_64K_4KEYS ; +else +return NR_RESERVED_PKEYS_64K_3KEYS ; }void expect_fault_on_read_execonly_key (void *p1,int pkey)
Signature · 1 line
2.17.1
PATCH v19 15/24 selftests/vm/pkeys: Fix assertion in test_pkey_alloc_exhaust()
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Some pkeys which are valid on the hardware are reserved and not available for application use. These keys cannot be allocated.
test_pkey_alloc_exhaust() tries to account for these and has an assertion which validates if all available pkeys have been exahaustively allocated. However, the expression that is currently used is only valid for x86. On powerpc, a pkey is additionally reserved as compared to x86. Hence, the assertion is made to use an arch-specific helper to get the correct count of reserved pkeys.
--- tools/testing/selftests/vm/protection_keys.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
tools/testing/selftests/vm/protection_keys.c +10 -1
@@ -1153,6 +1153,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)dprintf3 ("%s()::%d\n" , __func__, __LINE__);/* +* On x86: * There are 16 pkeys supported in hardware. Three are * allocated by the time we get here: * 1. The default key (0)
@@ -1160,8 +1161,16 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)* 3. One allocated by the test code and passed in via * 'pkey' to this function. * Ensure that we can allocate at least another 13 (16-3). +* +* On powerpc: +* There are either 5, 28, 29 or 32 pkeys supported in +* hardware depending on the page size (4K or 64K) and +* platform (powernv or powervm). Four are allocated by +* the time we get here. These include pkey-0, pkey-1, +* exec-only pkey and the one allocated by the test code. +* Ensure that we can allocate the remaining. */ -pkey_assert (i >=NR_PKEYS -3 ); +pkey_assert (i >= (NR_PKEYS -get_arch_reserved_keys () -1 ));for (i =0 ; i < nr_allocated_pkeys; i++) { err =sys_pkey_free (allocated_pkeys[i]);
Signature · 1 line
2.17.1
PATCH v19 16/24 selftests/vm/pkeys: Improve checks to determine pkey support
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
For the pkeys subsystem to work, both the CPU and the kernel need to have support. So, additionally check if the kernel supports pkeys apart from the CPU feature checks.
--- tools/testing/selftests/vm/pkey-helpers.h | 30 ++++++++++++++++++++ tools/testing/selftests/vm/pkey-powerpc.h | 3 +- tools/testing/selftests/vm/pkey-x86.h | 2 +- tools/testing/selftests/vm/protection_keys.c | 7 +++-- 4 files changed, 37 insertions(+), 5 deletions(-)
tools/testing/selftests/vm/pkey-helpers.h +30 -0
@@ -76,6 +76,8 @@ extern void abort_hooks(void); __attribute__((noinline))int read_ptr (int *ptr);void expected_pkey_fault (int pkey); +int sys_pkey_alloc (unsigned long flags,unsigned long init_val); +int sys_pkey_free (unsigned long pkey);#if defined(__i386__) || defined(__x86_64__)/* arch */ #include "pkey-x86.h"
@@ -186,4 +188,32 @@ static inline u32 *siginfo_get_pkey_ptr(siginfo_t *si) #endif } +static inline int kernel_has_pkeys (void ) +{ +/* try allocating a key and see if it succeeds */ +int ret =sys_pkey_alloc (0 ,0 ); +if (ret <=0 ) { +return 0 ; + } +sys_pkey_free (ret); +return 1 ; +} + +static inline int is_pkeys_supported (void ) +{ +/* check if the cpu supports pkeys */ +if (!cpu_has_pkeys ()) { +dprintf1 ("SKIP: %s: no CPU support\n" , __func__); +return 0 ; + } + +/* check if the kernel supports pkeys */ +if (!kernel_has_pkeys ()) { +dprintf1 ("SKIP: %s: no kernel support\n" , __func__); +return 0 ; + } + +return 1 ; +} +#endif /* _PKEYS_HELPER_H */
tools/testing/selftests/vm/pkey-powerpc.h +2 -1
@@ -63,8 +63,9 @@ static inline void __write_pkey_reg(u64 pkey_reg) __func__, __read_pkey_reg(), pkey_reg); } -static inline int cpu_has_pku (void ) +static inline int cpu_has_pkeys (void ) { +/* No simple way to determine this */ return 1 ; }
tools/testing/selftests/vm/pkey-x86.h +1 -1
@@ -97,7 +97,7 @@ static inline void __cpuid(unsigned int *eax, unsigned int *ebx,#define X86_FEATURE_PKU (1<<3)/* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (1<<4)/* OS Protection Keys Enable */ -static inline int cpu_has_pku (void ) +static inline int cpu_has_pkeys (void ) {unsigned int eax;unsigned int ebx;
tools/testing/selftests/vm/protection_keys.c +4 -3
@@ -1378,7 +1378,7 @@ void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)int size =PAGE_SIZE ;int sret; -if (cpu_has_pku ()) { +if (cpu_has_pkeys ()) {dprintf1 ("SKIP: %s: no CPU support\n" , __func__);return ; }
@@ -1447,12 +1447,13 @@ void pkey_setup_shadow(void)int main (void ) {int nr_iterations =22 ; +int pkeys_supported =is_pkeys_supported ();setup_handlers (); -printf ("has pku: %d\n" ,cpu_has_pku ()); +printf ("has pkeys: %d\n" , pkeys_supported); -if (!cpu_has_pku ()) { +if (!pkeys_supported) {int size =PAGE_SIZE ;int *ptr;
Signature · 1 line
2.17.1
PATCH v19 17/24 selftests/vm/pkeys: Associate key on a mapped page and detect access violation
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Detect access-violation on a page to which access-disabled key is associated much after the page is mapped.
Signed-off: Sandipan Das <[email protected]>
--- tools/testing/selftests/vm/protection_keys.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
tools/testing/selftests/vm/protection_keys.c +19 -0
@@ -984,6 +984,24 @@ void test_read_of_access_disabled_region(int *ptr, u16 pkey)dprintf1 ("*ptr: %d\n" , ptr_contents);expected_pkey_fault (pkey); } + +void test_read_of_access_disabled_region_with_page_already_mapped (int *ptr, +u16 pkey) +{ +int ptr_contents; + +dprintf1 ("disabling access to PKEY[%02d], doing read @ %p\n" , + pkey, ptr); + ptr_contents =read_ptr (ptr); +dprintf1 ("reading ptr before disabling the read : %d\n" , + ptr_contents); +read_pkey_reg (); +pkey_access_deny (pkey); + ptr_contents =read_ptr (ptr); +dprintf1 ("*ptr: %d\n" , ptr_contents); +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);
@@ -1390,6 +1408,7 @@ void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)void (*pkey_tests[])(int *ptr,u16 pkey) = { test_read_of_write_disabled_region, test_read_of_access_disabled_region, + test_read_of_access_disabled_region_with_page_already_mapped, test_write_of_write_disabled_region, test_write_of_access_disabled_region, test_kernel_write_of_access_disabled_region,
Signature · 1 line
2.17.1
PATCH v19 18/24 selftests/vm/pkeys: Associate key on a mapped page and detect write violation
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Detect write-violation on a page to which write-disabled key is associated much after the page is mapped.
--- tools/testing/selftests/vm/protection_keys.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
tools/testing/selftests/vm/protection_keys.c +12 -0
@@ -1002,6 +1002,17 @@ void test_read_of_access_disabled_region_with_page_already_mapped(int *ptr,expected_pkey_fault (pkey); } +void test_write_of_write_disabled_region_with_page_already_mapped (int *ptr, +u16 pkey) +{ + *ptr = __LINE__; +dprintf1 ("disabling write access; after accessing the page, " +"to PKEY[%02d], doing write\n" , pkey); +pkey_write_deny (pkey); + *ptr = __LINE__; +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);
@@ -1410,6 +1421,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = { test_read_of_access_disabled_region, test_read_of_access_disabled_region_with_page_already_mapped, test_write_of_write_disabled_region, + test_write_of_write_disabled_region_with_page_already_mapped, test_write_of_access_disabled_region, test_kernel_write_of_access_disabled_region, test_kernel_write_of_write_disabled_region,
Signature · 1 line
2.17.1
PATCH v19 19/24 selftests/vm/pkeys: Detect write violation on a mapped access-denied-key page
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Detect write-violation on a page to which access-disabled key is associated much after the page is mapped.
--- tools/testing/selftests/vm/protection_keys.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
tools/testing/selftests/vm/protection_keys.c +13 -0
@@ -1027,6 +1027,18 @@ void test_write_of_access_disabled_region(int *ptr, u16 pkey) *ptr = __LINE__;expected_pkey_fault (pkey); } + +void test_write_of_access_disabled_region_with_page_already_mapped (int *ptr, +u16 pkey) +{ + *ptr = __LINE__; +dprintf1 ("disabling access; after accessing the page, " +" to PKEY[%02d], doing write\n" , pkey); +pkey_access_deny (pkey); + *ptr = __LINE__; +expected_pkey_fault (pkey); +} +void test_kernel_write_of_access_disabled_region (int *ptr,u16 pkey) {int ret;
@@ -1423,6 +1435,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = { test_write_of_write_disabled_region, test_write_of_write_disabled_region_with_page_already_mapped, test_write_of_access_disabled_region, + test_write_of_access_disabled_region_with_page_already_mapped, test_kernel_write_of_access_disabled_region, test_kernel_write_of_write_disabled_region, test_kernel_gup_of_access_disabled_region,
Signature · 1 line
2.17.1
PATCH v19 20/24 selftests/vm/pkeys: Introduce a sub-page allocator
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
This introduces a new allocator that allocates 4K hardware pages to back 64K linux pages. This allocator is available only on powerpc.
--- tools/testing/selftests/vm/pkey-helpers.h | 6 +++++ tools/testing/selftests/vm/pkey-powerpc.h | 25 ++++++++++++++++++++ tools/testing/selftests/vm/pkey-x86.h | 5 ++++ tools/testing/selftests/vm/protection_keys.c | 1 + 4 files changed, 37 insertions(+)
tools/testing/selftests/vm/pkey-helpers.h +6 -0
@@ -28,6 +28,9 @@extern int dprint_in_signal;extern char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE ]; +extern int test_nr; +extern int iteration_nr; +#ifdef __GNUC__ __attribute__((format(printf, 1, 2)))#endif
@@ -78,6 +81,9 @@ __attribute__((noinline)) int read_ptr(int *ptr);void expected_pkey_fault (int pkey);int sys_pkey_alloc (unsigned long flags,unsigned long init_val);int sys_pkey_free (unsigned long pkey); +int mprotect_pkey (void *ptr,size_t size,unsigned long orig_prot, +unsigned long pkey); +void record_pkey_malloc (void *ptr,long size,int prot);#if defined(__i386__) || defined(__x86_64__)/* arch */ #include "pkey-x86.h"
tools/testing/selftests/vm/pkey-powerpc.h +25 -0
@@ -106,4 +106,29 @@ void expect_fault_on_read_execonly_key(void *p1, int pkey)/* 4-byte instructions * 16384 = 64K page */ #define __page_o_noops () asm(".rept 16384 ; nop; .endr") +void *malloc_pkey_with_mprotect_subpage (long size,int prot,u16 pkey) +{ +void *ptr; +int ret; + +dprintf1 ("doing %s(size=%ld, prot=0x%x, pkey=%d)\n" , __func__, + size, prot, pkey); +pkey_assert (pkey <NR_PKEYS ); + ptr =mmap (NULL , size, prot,MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +pkey_assert (ptr != (void *)-1 ); + + ret =syscall (__NR_subpage_prot, ptr, size,NULL ); +if (ret) { +perror ("subpage_perm" ); +return PTR_ERR_ENOTSUP ; + } + + ret =mprotect_pkey ((void *)ptr,PAGE_SIZE , prot, pkey); +pkey_assert (!ret); +record_pkey_malloc (ptr, size, prot); + +dprintf1 ("%s() for pkey %d @ %p\n" , __func__, pkey, ptr); +return ptr; +} +#endif /* _PKEYS_POWERPC_H */
tools/testing/selftests/vm/pkey-x86.h +5 -0
@@ -173,4 +173,9 @@ void expect_fault_on_read_execonly_key(void *p1, int pkey) expected_pkey_fault(pkey); } +void *malloc_pkey_with_mprotect_subpage (long size,int prot,u16 pkey) +{ +return PTR_ERR_ENOTSUP ; +} +#endif /* _PKEYS_X86_H */
tools/testing/selftests/vm/protection_keys.c +1 -0
@@ -845,6 +845,7 @@ void *malloc_pkey_mmap_dax(long size, int prot, u16 pkey)void *(*pkey_malloc[])(long size,int prot,u16 pkey) = { malloc_pkey_with_mprotect, + malloc_pkey_with_mprotect_subpage, malloc_pkey_anon_huge, malloc_pkey_hugetlb/* can not do direct with the pkey_mprotect() API:
Signature · 1 line
2.17.1
PATCH v19 21/24 selftests/vm/pkeys: Test correct behaviour of pkey-0
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Ensure that pkey-0 is allocated on start and that it can be attached dynamically in various modes, without failures.
--- tools/testing/selftests/vm/protection_keys.c | 53 ++++++++++++++++++++ 1 file changed, 53 insertions(+)
tools/testing/selftests/vm/protection_keys.c +53 -0
@@ -964,6 +964,58 @@ __attribute__((noinline)) int read_ptr(int *ptr)return *ptr; } +void test_pkey_alloc_free_attach_pkey0 (int *ptr,u16 pkey) +{ +int i, err; +int max_nr_pkey_allocs; +int alloced_pkeys[NR_PKEYS ]; +int nr_alloced =0 ; +long size; + +pkey_assert (pkey_last_malloc_record); + size = pkey_last_malloc_record->size; +/* +* This is a bit of a hack. But mprotect() requires +* huge-page-aligned sizes when operating on hugetlbfs. +* So, make sure that we use something that's a multiple +* of a huge page when we can. +*/ +if (size >=HPAGE_SIZE ) + size =HPAGE_SIZE ; + +/* allocate every possible key and make sure key-0 never got allocated */ + max_nr_pkey_allocs =NR_PKEYS ; +for (i =0 ; i < max_nr_pkey_allocs; i++) { +int new_pkey =alloc_pkey (); +pkey_assert (new_pkey !=0 ); + +if (new_pkey <0 ) +break ; + alloced_pkeys[nr_alloced++] = new_pkey; + } +/* free all the allocated keys */ +for (i =0 ; i < nr_alloced; i++) { +int free_ret; + +if (!alloced_pkeys[i]) +continue ; + free_ret =sys_pkey_free (alloced_pkeys[i]); +pkey_assert (!free_ret); + } + +/* attach key-0 in various modes */ + err =sys_mprotect_pkey (ptr, size,PROT_READ ,0 ); +pkey_assert (!err); + err =sys_mprotect_pkey (ptr, size,PROT_WRITE ,0 ); +pkey_assert (!err); + err =sys_mprotect_pkey (ptr, size,PROT_EXEC ,0 ); +pkey_assert (!err); + err =sys_mprotect_pkey (ptr, size,PROT_READ |PROT_WRITE ,0 ); +pkey_assert (!err); + err =sys_mprotect_pkey (ptr, size,PROT_READ |PROT_WRITE |PROT_EXEC ,0 ); +pkey_assert (!err); +} +void test_read_of_write_disabled_region (int *ptr,u16 pkey) {int ptr_contents;
@@ -1448,6 +1500,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = { test_pkey_syscalls_on_non_allocated_pkey, test_pkey_syscalls_bad_args, test_pkey_alloc_exhaust, + test_pkey_alloc_free_attach_pkey0, };void run_tests_once (void )
Signature · 1 line
2.17.1
PATCH v19 22/24 selftests/vm/pkeys: Override access right definitions on powerpc
In reply to Sandipan DasFrom: Ram Pai <[email protected]>
Some platforms hardcode the x86 values for PKEY_DISABLE_ACCESS and PKEY_DISABLE_WRITE such as those in:
/usr/include/bits/mman-shared.h.
This overrides the definitions with correct values for powerpc.
--- tools/testing/selftests/vm/pkey-powerpc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/pkey-powerpc.h +4 -2
@@ -16,11 +16,13 @@#define fpregs fp_regs#define si_pkey_offset 0x20 -#ifndef PKEY_DISABLE_ACCESS +#ifdef PKEY_DISABLE_ACCESS +#undef PKEY_DISABLE_ACCESS# define PKEY_DISABLE_ACCESS 0x3/* disable read and write */ #endif -#ifndef PKEY_DISABLE_WRITE +#ifdef PKEY_DISABLE_WRITE +#undef PKEY_DISABLE_WRITE# define PKEY_DISABLE_WRITE 0x2#endif
Signature · 1 line
2.17.1
PATCH v19 23/24 selftests: vm: pkeys: Use the correct page size on powerpc
In reply to Sandipan DasBoth 4K and 64K pages are supported on powerpc. Parts of the selftest code perform alignment computations based on the PAGE_SIZE macro which is currently hardcoded to 64K for powerpc. This causes some test failures on kernels configured with 4K page size.
In some cases, we need to enforce function alignment on page size. Since this can only be done at build time, 64K is used as the alignment factor as that also ensures 4K alignment.
--- tools/testing/selftests/vm/pkey-powerpc.h | 2 +- tools/testing/selftests/vm/protection_keys.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-)
tools/testing/selftests/vm/pkey-powerpc.h +1 -1
@@ -36,7 +36,7 @@pkey-31 and exec-only key */ #define PKEY_BITS_PER_PKEY 2#define HPAGE_SIZE (1UL << 24) -#define PAGE_SIZE (1UL << 16) +#define PAGE_SIZE sysconf(_SC_PAGESIZE)static inline u32 pkey_bit_position (int pkey) {
tools/testing/selftests/vm/protection_keys.c +5 -0
@@ -146,7 +146,12 @@ void abort_hooks(void)* will then fault, which makes sure that the fault code handles * execute-only memory properly. */ +#ifdef __powerpc64__ +/* This way, both 4K and 64K alignment are maintained */ +__attribute__((__aligned__ (65536 ))) +#else __attribute__((__aligned__ (PAGE_SIZE ))) +#endifvoid lots_o_noops_around_write (int *write_to_me) {dprintf3 ("running %s()\n" , __func__);
Signature · 1 line
2.17.1
PATCH v19 24/24 selftests: vm: pkeys: Fix multilib builds for x86
In reply to Sandipan DasThis ensures that both 32-bit and 64-bit binaries are generated when this is built on a x86_64 system. Most of the changes have been borrowed from tools/testing/selftests/x86/Makefile.
--- tools/testing/selftests/vm/Makefile | 72 +++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
tools/testing/selftests/vm/Makefile +72 -0
@@ -18,7 +18,30 @@ TEST_GEN_FILES += on-fault-limit TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += transhuge-stress TEST_GEN_FILES += userfaultfd + +ifeq ($(ARCH),x86_64) +CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_32bit_program.c -m32) +CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_64bit_program.c) +CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_program.c -no-pie) + +TARGETS := protection_keys +BINARIES_32 := $(TARGETS:%=%_32) +BINARIES_64 := $(TARGETS:%=%_64) + +ifeq ($(CAN_BUILD_WITH_NOPIE),1) +CFLAGS += -no-pie +endif + +ifeq ($(CAN_BUILD_I386),1) +TEST_GEN_FILES += $(BINARIES_32) +endif + +ifeq ($(CAN_BUILD_X86_64),1) +TEST_GEN_FILES += $(BINARIES_64) +endif +else TEST_GEN_FILES += protection_keys +endif ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64)) TEST_GEN_FILES += va_128TBswitch
@@ -32,6 +55,55 @@ TEST_FILES := test_vmalloc.sh KSFT_KHDR_INSTALL := 1 include ../lib.mk +ifeq ($(ARCH),x86_64) +BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32)) +BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64)) + +define gen-target-rule-32 +$(1) $(1)_32: $(OUTPUT)/$(1)_32 +.PHONY: $(1) $(1)_32 +endef + +define gen-target-rule-64 +$(1) $(1)_64: $(OUTPUT)/$(1)_64 +.PHONY: $(1) $(1)_64 +endef + +ifeq ($(CAN_BUILD_I386),1) +$(BINARIES_32): CFLAGS += -m32 +$(BINARIES_32): LDLIBS += -lrt -ldl -lm +$(BINARIES_32): %_32: %.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@ +$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-32,$(t)))) +endif + +ifeq ($(CAN_BUILD_X86_64),1) +$(BINARIES_64): CFLAGS += -m64 +$(BINARIES_64): LDLIBS += -lrt -ldl +$(BINARIES_64): %_64: %.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@ +$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-64,$(t)))) +endif + +# x86_64 users should be encouraged to install 32-bit libraries +ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01) +all: warn_32bit_failure + +warn_32bit_failure: + @echo "Warning: you seem to have a broken 32-bit build" 2>&1; \ + echo "environment. This will reduce test coverage of 64-bit" 2>&1; \ + echo "kernels. If you are using a Debian-like distribution," 2>&1; \ + echo "try:"; 2>&1; \ + echo ""; \ + echo " apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \ + echo ""; \ + echo "If you are using a Fedora-like distribution, try:"; \ + echo ""; \ + echo " yum install glibc-devel.*i686"; \ + exit 0; +endif +endif + $(OUTPUT)/userfaultfd: LDLIBS += -lpthread $(OUTPUT)/mlock-random-test: LDLIBS += -lcap
Signature · 1 line
2.17.1