forked from mirrors/linux
		
	selftests/mm: use sys_pkey helpers consistently
sys_pkey_alloc, sys_pkey_free and sys_mprotect_pkey are currently used in
protections_keys.c, while pkey_sighandler_tests.c calls the libc wrappers
directly (e.g.  pkey_mprotect()).  This is probably ok when using glibc
(those symbols appeared a while ago), but Musl does not currently provide
them.  The logging in the helpers from pkey-helpers.h can also come in
handy.
Make things more consistent by using the sys_pkey helpers in
pkey_sighandler_tests.c too.  To that end their implementation is moved to
a common .c file (pkey_util.c).  This also enables calling
is_pkeys_supported() outside of protections_keys.c, since it relies on
sys_pkey_{alloc,free}.
[kevin.brodsky@arm.com: fix dependency on pkey_util.c]
  Link: https://lkml.kernel.org/r/20241216092849.2140850-1-kevin.brodsky@arm.com
Link: https://lkml.kernel.org/r/20241209095019.1732120-12-kevin.brodsky@arm.com
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Joey Gouly <joey.gouly@arm.com>
Cc: Keith Lucas <keith.lucas@oracle.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
			
			
This commit is contained in:
		
							parent
							
								
									b0cc298487
								
							
						
					
					
						commit
						50910acd6f
					
				
					 5 changed files with 50 additions and 39 deletions
				
			
		| 
						 | 
					@ -158,11 +158,15 @@ $(TEST_GEN_FILES): vm_util.c thp_settings.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(OUTPUT)/uffd-stress: uffd-common.c
 | 
					$(OUTPUT)/uffd-stress: uffd-common.c
 | 
				
			||||||
$(OUTPUT)/uffd-unit-tests: uffd-common.c
 | 
					$(OUTPUT)/uffd-unit-tests: uffd-common.c
 | 
				
			||||||
 | 
					$(OUTPUT)/protection_keys: pkey_util.c
 | 
				
			||||||
 | 
					$(OUTPUT)/pkey_sighandler_tests: pkey_util.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(ARCH),x86_64)
 | 
					ifeq ($(ARCH),x86_64)
 | 
				
			||||||
BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
 | 
					BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
 | 
				
			||||||
BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
 | 
					BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(BINARIES_32) $(BINARIES_64): pkey_util.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define gen-target-rule-32
 | 
					define gen-target-rule-32
 | 
				
			||||||
$(1) $(1)_32: $(OUTPUT)/$(1)_32
 | 
					$(1) $(1)_32: $(OUTPUT)/$(1)_32
 | 
				
			||||||
.PHONY: $(1) $(1)_32
 | 
					.PHONY: $(1) $(1)_32
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,6 +89,8 @@ extern void abort_hooks(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sys_pkey_alloc(unsigned long flags, unsigned long init_val);
 | 
					int sys_pkey_alloc(unsigned long flags, unsigned long init_val);
 | 
				
			||||||
int sys_pkey_free(unsigned long pkey);
 | 
					int sys_pkey_free(unsigned long pkey);
 | 
				
			||||||
 | 
					int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
 | 
				
			||||||
 | 
							unsigned long pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* For functions called from protection_keys.c only */
 | 
					/* For functions called from protection_keys.c only */
 | 
				
			||||||
noinline int read_ptr(int *ptr);
 | 
					noinline int read_ptr(int *ptr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,8 +311,8 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
 | 
				
			||||||
	__write_pkey_reg(pkey_reg);
 | 
						__write_pkey_reg(pkey_reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Protect the new stack with MPK 1 */
 | 
						/* Protect the new stack with MPK 1 */
 | 
				
			||||||
	pkey = pkey_alloc(0, 0);
 | 
						pkey = sys_pkey_alloc(0, 0);
 | 
				
			||||||
	pkey_mprotect(stack, STACK_SIZE, PROT_READ | PROT_WRITE, pkey);
 | 
						sys_mprotect_pkey(stack, STACK_SIZE, PROT_READ | PROT_WRITE, pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set up alternate signal stack that will use the default MPK */
 | 
						/* Set up alternate signal stack that will use the default MPK */
 | 
				
			||||||
	sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
						sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
| 
						 | 
					@ -484,8 +484,8 @@ static void test_pkru_sigreturn(void)
 | 
				
			||||||
	__write_pkey_reg(pkey_reg);
 | 
						__write_pkey_reg(pkey_reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Protect the stack with MPK 2 */
 | 
						/* Protect the stack with MPK 2 */
 | 
				
			||||||
	pkey = pkey_alloc(0, 0);
 | 
						pkey = sys_pkey_alloc(0, 0);
 | 
				
			||||||
	pkey_mprotect(stack, STACK_SIZE, PROT_READ | PROT_WRITE, pkey);
 | 
						sys_mprotect_pkey(stack, STACK_SIZE, PROT_READ | PROT_WRITE, pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set up alternate signal stack that will use the default MPK */
 | 
						/* Set up alternate signal stack that will use the default MPK */
 | 
				
			||||||
	sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
						sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								tools/testing/selftests/mm/pkey_util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tools/testing/selftests/mm/pkey_util.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-only
 | 
				
			||||||
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "pkey-helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = syscall(SYS_pkey_alloc, flags, init_val);
 | 
				
			||||||
 | 
						dprintf1("%s(flags=%lx, init_val=%lx) syscall ret: %d errno: %d\n",
 | 
				
			||||||
 | 
								__func__, flags, init_val, ret, errno);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sys_pkey_free(unsigned long pkey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = syscall(SYS_pkey_free, pkey);
 | 
				
			||||||
 | 
						dprintf1("%s(pkey=%ld) syscall ret: %d\n", __func__, pkey, ret);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
 | 
				
			||||||
 | 
							unsigned long pkey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int sret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dprintf2("%s(0x%p, %zx, prot=%lx, pkey=%lx)\n", __func__,
 | 
				
			||||||
 | 
								ptr, size, orig_prot, pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						errno = 0;
 | 
				
			||||||
 | 
						sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey);
 | 
				
			||||||
 | 
						if (errno) {
 | 
				
			||||||
 | 
							dprintf2("SYS_mprotect_key sret: %d\n", sret);
 | 
				
			||||||
 | 
							dprintf2("SYS_mprotect_key prot: 0x%lx\n", orig_prot);
 | 
				
			||||||
 | 
							dprintf2("SYS_mprotect_key failed, errno: %d\n", errno);
 | 
				
			||||||
 | 
							if (DEBUG_LEVEL >= 2)
 | 
				
			||||||
 | 
								perror("SYS_mprotect_pkey");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -460,34 +460,6 @@ static pid_t fork_lazy_child(void)
 | 
				
			||||||
	return forkret;
 | 
						return forkret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
 | 
					 | 
				
			||||||
		unsigned long pkey)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int sret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dprintf2("%s(0x%p, %zx, prot=%lx, pkey=%lx)\n", __func__,
 | 
					 | 
				
			||||||
			ptr, size, orig_prot, pkey);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	errno = 0;
 | 
					 | 
				
			||||||
	sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey);
 | 
					 | 
				
			||||||
	if (errno) {
 | 
					 | 
				
			||||||
		dprintf2("SYS_mprotect_key sret: %d\n", sret);
 | 
					 | 
				
			||||||
		dprintf2("SYS_mprotect_key prot: 0x%lx\n", orig_prot);
 | 
					 | 
				
			||||||
		dprintf2("SYS_mprotect_key failed, errno: %d\n", errno);
 | 
					 | 
				
			||||||
		if (DEBUG_LEVEL >= 2)
 | 
					 | 
				
			||||||
			perror("SYS_mprotect_pkey");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return sret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = syscall(SYS_pkey_alloc, flags, init_val);
 | 
					 | 
				
			||||||
	dprintf1("%s(flags=%lx, init_val=%lx) syscall ret: %d errno: %d\n",
 | 
					 | 
				
			||||||
			__func__, flags, init_val, ret, errno);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int alloc_pkey(void)
 | 
					static int alloc_pkey(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -534,13 +506,6 @@ static int alloc_pkey(void)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sys_pkey_free(unsigned long pkey)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = syscall(SYS_pkey_free, pkey);
 | 
					 | 
				
			||||||
	dprintf1("%s(pkey=%ld) syscall ret: %d\n", __func__, pkey, ret);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * I had a bug where pkey bits could be set by mprotect() but
 | 
					 * I had a bug where pkey bits could be set by mprotect() but
 | 
				
			||||||
 * not cleared.  This ensures we get lots of random bit sets
 | 
					 * not cleared.  This ensures we get lots of random bit sets
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue