Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Add test for atomic uaccess with permission overlay
@ 2026-05-21  9:42 Kevin Brodsky
  2026-05-21  9:42 ` [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1 Kevin Brodsky
  2026-05-21  9:42 ` [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE Kevin Brodsky
  0 siblings, 2 replies; 7+ messages in thread
From: Kevin Brodsky @ 2026-05-21  9:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
	Shuah Khan, Will Deacon, linux-kernel, linux-kselftest

Permission overlays are not currently applied for memory types
configured in PIR_EL1, meaning that even if POE were enabled at EL1,
memory accesses would not be subject to POE restrictions.

A patch [1] in my series adding page table protection using
pkeys/POE [2] enabled overlays for all memory types in PIR_EL1. It
turns out this is wrong, as reported by Sashiko [3]. User memory
types must not have overlays applied in PIR_EL1, otherwise direct
accesses to user memory with privileged loads/stores (and PAN
disabled) will mistakenly be checked against POR_EL1, instead of the
intended POR_EL0.

To avoid any accident in the future, this series adds a comment
above the PIR_EL1 configuration block, and a kselftest to ensure
that atomic futex uaccess (which uses privileged loads/stores unless
FEAT_LSUI is available) does work on memory mapped with a
non-default pkey. 

Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>

[1] https://lore.kernel.org/all/20260505-kpkeys-v7-3-20c0bdd97197@arm.com/
[2] https://lore.kernel.org/all/20260505-kpkeys-v7-0-20c0bdd97197@arm.com/
[3] https://sashiko.dev/#/patchset/20260505-kpkeys-v7-0-20c0bdd97197%40arm.com?part=3

---
To: linux-arm-kernel@lists.infradead.org
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Joey Gouly <joey.gouly@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org

---
Kevin Brodsky (2):
      arm64: mm: Add note about overlays in PIE_EL1
      kselftest/arm64: Add test for atomic futex uaccess with POE

 arch/arm64/include/asm/pgtable-prot.h         |  7 +++
 tools/testing/selftests/arm64/Makefile        |  2 +-
 tools/testing/selftests/arm64/poe/.gitignore  |  2 +
 tools/testing/selftests/arm64/poe/Makefile    |  6 +++
 tools/testing/selftests/arm64/poe/poe_futex.c | 62 +++++++++++++++++++++++++++
 5 files changed, 78 insertions(+), 1 deletion(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260520-poe_futex-ecb8c2276894



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1
  2026-05-21  9:42 [PATCH 0/2] Add test for atomic uaccess with permission overlay Kevin Brodsky
@ 2026-05-21  9:42 ` Kevin Brodsky
  2026-05-21  9:48   ` Kevin Brodsky
  2026-05-21  9:42 ` [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE Kevin Brodsky
  1 sibling, 1 reply; 7+ messages in thread
From: Kevin Brodsky @ 2026-05-21  9:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
	Shuah Khan, Will Deacon, linux-kernel, linux-kselftest

It isn't completely obvious why user page types do not have overlays
applied in PIE_EL1. Add a comment to that effect, to avoid
unpleasant surprises in the future.

Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
 arch/arm64/include/asm/pgtable-prot.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 212ce1b02e15..6e2f99820909 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -175,6 +175,13 @@ static inline bool __pure lpa2_is_enabled(void)
 	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_READONLY),      PIE_R_O)   | \
 	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_SHARED),        PIE_RW_O))
 
+/*
+ * Regular user page types such as _PAGE_SHARED must not have overlays applied
+ * in PIE_EL1. If POE is enabled at EL1, and in the absence of FEAT_LSUI, this
+ * would break futex atomic operations on user memory with a non-default
+ * POIndex; the privileged atomic load/store instructions would be mistakenly
+ * checked against POR_EL1.
+ */
 #define PIE_E1	( \
 	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS),           PIE_NONE_O) | \
 	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS_RO),        PIE_NONE_O) | \

-- 
2.51.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE
  2026-05-21  9:42 [PATCH 0/2] Add test for atomic uaccess with permission overlay Kevin Brodsky
  2026-05-21  9:42 ` [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1 Kevin Brodsky
@ 2026-05-21  9:42 ` Kevin Brodsky
  2026-05-21 11:22   ` Mark Brown
  1 sibling, 1 reply; 7+ messages in thread
From: Kevin Brodsky @ 2026-05-21  9:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
	Shuah Khan, Will Deacon, linux-kernel, linux-kselftest

Add a new test to ensure that atomic futex uaccess succeeds on
memory mapped with a non-default POIndex/pkey.

In the absence of FEAT_LSUI, atomic futex uaccess operations such as
those triggered by FUTEX_WAKE_OP use privileged atomic load/store
instructions and thus cannot have user permission overlays applied
(as per POR_EL0). In case the kernel enabled POE at EL1, it is worth
checking that PIR_EL1 isn't mistakenly configured to have kernel
overlays (POR_EL1) applied instead, as that would fail for non-zero
pkeys.

Note that if such misconfiguration occurs, futex_wake_op() may get
stuck in an infinite loop because futex_atomic_op_inuser() will fail
but fault_in_user_writeable() will still report success.

Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
 tools/testing/selftests/arm64/Makefile        |  2 +-
 tools/testing/selftests/arm64/poe/.gitignore  |  2 +
 tools/testing/selftests/arm64/poe/Makefile    |  6 +++
 tools/testing/selftests/arm64/poe/poe_futex.c | 62 +++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
index e456f3b62fa1..bad5c3b33dce 100644
--- a/tools/testing/selftests/arm64/Makefile
+++ b/tools/testing/selftests/arm64/Makefile
@@ -4,7 +4,7 @@
 ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 
 ifneq (,$(filter $(ARCH),aarch64 arm64))
-ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs
+ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs poe
 else
 ARM64_SUBTARGETS :=
 endif
diff --git a/tools/testing/selftests/arm64/poe/.gitignore b/tools/testing/selftests/arm64/poe/.gitignore
new file mode 100644
index 000000000000..0dce4a3aa38b
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+poe_futex
diff --git a/tools/testing/selftests/arm64/poe/Makefile b/tools/testing/selftests/arm64/poe/Makefile
new file mode 100644
index 000000000000..2af2bbf3f6d3
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += $(KHDR_INCLUDES)
+TEST_GEN_PROGS := poe_futex
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/poe/poe_futex.c b/tools/testing/selftests/arm64/poe/poe_futex.c
new file mode 100644
index 000000000000..21a2e109ee43
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/poe_futex.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/futex.h>
+#include <sys/syscall.h>
+
+#include "kselftest_harness.h"
+
+static int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
+{
+	return syscall(__NR_pkey_alloc, flags, init_val);
+}
+
+static int sys_pkey_mprotect(void *ptr, size_t size, int prot, int pkey)
+{
+	return syscall(__NR_pkey_mprotect, ptr, size, prot, pkey);
+}
+
+static int futex_wake_op(uint32_t *uaddr, uint32_t val, uint32_t val2,
+			 uint32_t *uaddr2, uint32_t val3)
+{
+	return syscall(SYS_futex, uaddr, FUTEX_WAKE_OP, val, val2,
+		       uaddr2, val3);
+}
+
+/*
+ * Trigger some atomic uaccess on a page mapped with a non-default pkey.
+ *
+ * This ensures that such access is not mistakenly checked against the
+ * kernel's POR_EL1 register.
+ */
+TEST(poe_futex)
+{
+	int ret, pkey;
+	void *ptr;
+	size_t size = getpagesize();
+
+	pkey = sys_pkey_alloc(0, 0);
+
+	if (pkey == -1 && errno == ENOSPC)
+		SKIP(return, "pkeys are not supported");
+
+	ASSERT_GT(pkey, 0);
+
+	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	ASSERT_NE(ptr, MAP_FAILED);
+
+	ret = sys_pkey_mprotect(ptr, size, PROT_READ | PROT_WRITE, pkey);
+	ASSERT_EQ(ret, 0);
+
+	/*
+	 * There is no one to wake up so this syscall boils down to *(ptr+4) = 0
+	 * (arch_futex_atomic_op_inuser() called with FUTEX_OP_SET and op_arg=0).
+	 */
+	ret = futex_wake_op(ptr, 1, 1, ptr + sizeof(uint32_t), 0);
+	ASSERT_EQ(ret, 0);
+}
+
+TEST_HARNESS_MAIN

-- 
2.51.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1
  2026-05-21  9:42 ` [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1 Kevin Brodsky
@ 2026-05-21  9:48   ` Kevin Brodsky
  0 siblings, 0 replies; 7+ messages in thread
From: Kevin Brodsky @ 2026-05-21  9:48 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Catalin Marinas, Joey Gouly, Mark Brown, Shuah Khan, Will Deacon,
	linux-kernel, linux-kselftest

On 21/05/2026 11:42, Kevin Brodsky wrote:
> It isn't completely obvious why user page types do not have overlays
> applied in PIE_EL1. Add a comment to that effect, to avoid
> unpleasant surprises in the future.

Should probably s/PIE_EL1/PIR_EL1/ in this whole patch.

I'm also tempted to rename PIE_E* to PIR_E* to avoid anyone else's brain
being confused like mine... The extension is called PIE, but this is
really about the register configuration, i.e. PIR.

- Kevin

> Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
> ---
>  arch/arm64/include/asm/pgtable-prot.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
> index 212ce1b02e15..6e2f99820909 100644
> --- a/arch/arm64/include/asm/pgtable-prot.h
> +++ b/arch/arm64/include/asm/pgtable-prot.h
> @@ -175,6 +175,13 @@ static inline bool __pure lpa2_is_enabled(void)
>  	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_READONLY),      PIE_R_O)   | \
>  	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_SHARED),        PIE_RW_O))
>  
> +/*
> + * Regular user page types such as _PAGE_SHARED must not have overlays applied
> + * in PIE_EL1. If POE is enabled at EL1, and in the absence of FEAT_LSUI, this
> + * would break futex atomic operations on user memory with a non-default
> + * POIndex; the privileged atomic load/store instructions would be mistakenly
> + * checked against POR_EL1.
> + */
>  #define PIE_E1	( \
>  	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS),           PIE_NONE_O) | \
>  	PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS_RO),        PIE_NONE_O) | \
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE
  2026-05-21  9:42 ` [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE Kevin Brodsky
@ 2026-05-21 11:22   ` Mark Brown
  2026-05-21 12:01     ` Kevin Brodsky
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Brown @ 2026-05-21 11:22 UTC (permalink / raw)
  To: Kevin Brodsky
  Cc: linux-arm-kernel, Catalin Marinas, Joey Gouly, Shuah Khan,
	Will Deacon, linux-kernel, linux-kselftest

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

On Thu, May 21, 2026 at 10:42:31AM +0100, Kevin Brodsky wrote:

> Add a new test to ensure that atomic futex uaccess succeeds on
> memory mapped with a non-default POIndex/pkey.

> +	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
> +		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +	ASSERT_NE(ptr, MAP_FAILED);

Doesn't matter while there's only one test but we should probably
munmap() this when we're done.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE
  2026-05-21 11:22   ` Mark Brown
@ 2026-05-21 12:01     ` Kevin Brodsky
  2026-05-21 12:06       ` Mark Brown
  0 siblings, 1 reply; 7+ messages in thread
From: Kevin Brodsky @ 2026-05-21 12:01 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-arm-kernel, Catalin Marinas, Joey Gouly, Shuah Khan,
	Will Deacon, linux-kernel, linux-kselftest

On 21/05/2026 13:22, Mark Brown wrote:
> On Thu, May 21, 2026 at 10:42:31AM +0100, Kevin Brodsky wrote:
>
>> Add a new test to ensure that atomic futex uaccess succeeds on
>> memory mapped with a non-default POIndex/pkey.
>> +	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
>> +		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>> +	ASSERT_NE(ptr, MAP_FAILED);
> Doesn't matter while there's only one test but we should probably
> munmap() this when we're done.

Fair enough, I was being lazy :) A pkey_free() is also in order to be
comprehensive, another wrapper to add. I considered using
../../mm/pkey-helpers.h but helpers there aren't implemented inline...
Maybe refactoring for later.

- Kevin


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE
  2026-05-21 12:01     ` Kevin Brodsky
@ 2026-05-21 12:06       ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2026-05-21 12:06 UTC (permalink / raw)
  To: Kevin Brodsky
  Cc: linux-arm-kernel, Catalin Marinas, Joey Gouly, Shuah Khan,
	Will Deacon, linux-kernel, linux-kselftest

[-- Attachment #1: Type: text/plain, Size: 887 bytes --]

On Thu, May 21, 2026 at 02:01:17PM +0200, Kevin Brodsky wrote:
> On 21/05/2026 13:22, Mark Brown wrote:

> > Doesn't matter while there's only one test but we should probably
> > munmap() this when we're done.

> Fair enough, I was being lazy :) A pkey_free() is also in order to be
> comprehensive, another wrapper to add. I considered using
> ../../mm/pkey-helpers.h but helpers there aren't implemented inline...
> Maybe refactoring for later.

There was another thread librifying the GUP helpers which might be a
good model:

   https://lore.kernel.org/linux-mm/20260521111801.173019-1-sarthak.sharma@arm.com/T/#t

I'm always a bit nervous about peering inside other selftest
directories, it can work well but some instances of it are relatively
frequent sources of regressions as people working in the main directory
don't think about users in other directories when doing updates.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-05-21 12:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-21  9:42 [PATCH 0/2] Add test for atomic uaccess with permission overlay Kevin Brodsky
2026-05-21  9:42 ` [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1 Kevin Brodsky
2026-05-21  9:48   ` Kevin Brodsky
2026-05-21  9:42 ` [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE Kevin Brodsky
2026-05-21 11:22   ` Mark Brown
2026-05-21 12:01     ` Kevin Brodsky
2026-05-21 12:06       ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox