mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/4] arm64, riscv: release shadow stacks on failed fork
@ 2026-10-16 19:45 Iván Ezequiel Rodriguez
  2026-10-16 19:46 ` [PATCH 1/4] arm64/gcs: release GCS " Iván Ezequiel Rodriguez
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Iván Ezequiel Rodriguez @ 2026-10-16 19:45 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
	linux-arm-kernel, linux-riscv
  Cc: linux-kernel, linux-kselftest, Mark Rutland, Mark Brown,
	Deepak Gupta, Alexandre Ghiti, Albert Ou, Shuah Khan,
	Christian Brauner, James Morse, Yury Khrustalev,
	Thiago Jung Bauermann, Samuel Holland, Zong Li, Charlie Jenkins,
	Shaopeng Tan, Zishun Yi, Peter Zijlstra (Intel)

This is not a port of the x86 TLS fix i sent yesterday. That leak was inside
copy_thread() when set_new_tls() failed, so copy_process() skipped
exit_thread(). Here copy_thread() returns 0 and a later
copy_process() step fails. The concrete hole is clone3() with
CLONE_VM|CLONE_PIDFD and an unwritable pidfd pointer: put_user()
returns -EFAULT after the architecture has mapped a shadow stack.
exit_thread() does run, but arm64 and riscv did not implement it, so
that mapping stays in the parent's mm.

Normal exit already frees via deactivate_mm(). The failed-fork path
never reaches that. The free helpers already refuse a foreign mm
and a cleared base, so wiring them to exit_thread() does not unmap
the parent on !CLONE_VM or double-free on a normal exit. A
successful clone3() child with the same flags exits through
deactivate_mm() and then exit_thread(); that is the usual teardown
order this series also enables.

riscv's shstk_release() comment already described this
exit_thread() call. The architecture never selected
HAVE_EXIT_THREAD, so the documented path was not connected.

Do not free on a copy_thread() allocation error: the child still
aliases the parent's base, and copy_process() skips exit_thread()
when copy_thread() fails. kernel_thread() uses CLONE_VM, so a
failed copy_process() still shares the caller's mm and the mm check
in the free helpers does not save us; the kthread path clears
inherited tracking for that reason.

The selftests assume /proc is mounted. A clone3() with a valid
pidfd must succeed and write a pidfd before the rejected calls
count. ENOSYS, EINVAL, and EPERM from that clone skip; any other
error fails the test.

Sixteen clone3() calls with CLONE_VM|CLONE_PIDFD and an unwritable
pidfd pointer leaked 16 shadow-stack VMAs without the fix. With it,
the count stayed unchanged and call/return on the parent still used
the original mapping.

Base: 2f2f7eeef8b0 ("Merge tag 'soc-fixes-7.3-3' of
git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc").

arm64: QEMU 11.1.2 -machine virt -cpu max, CONFIG_ARM64_GCS, one
vCPU. Unpatched ss_vmas=1->17 (+512 kB). Patched ss_vmas=1->1.

riscv: QEMU 11.1.2 -machine virt
-cpu rv64,zimop=on,zcmop=on,zicfiss=on, CONFIG_RISCV_USER_CFI, one
vCPU. Unpatched ss_vmas=1->17 (+1024 kB). Patched ss_vmas=1->1.

Assisted-by: LLM

Iván Ezequiel Rodriguez (4):
  arm64/gcs: release GCS on failed fork
  riscv/shstk: release shadow stack on failed fork
  selftests/arm64: GCS must not leak on a failed clone3
  selftests/riscv: shadow stack must not leak on a failed clone3

 arch/arm64/Kconfig                            |   1 +
 arch/arm64/kernel/process.c                   |  21 ++
 arch/riscv/Kconfig                            |   1 +
 arch/riscv/kernel/process.c                   |  18 +
 tools/testing/selftests/arm64/gcs/Makefile    |   3 +-
 .../selftests/arm64/gcs/gcs-clone-pidfd.c     | 355 ++++++++++++++++++
 tools/testing/selftests/riscv/cfi/Makefile    |   5 +-
 .../selftests/riscv/cfi/shstk-clone-pidfd.c   | 317 ++++++++++++++++
 8 files changed, 719 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/arm64/gcs/gcs-clone-pidfd.c
 create mode 100644 tools/testing/selftests/riscv/cfi/shstk-clone-pidfd.c

-- 
2.43.0

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

end of thread, other threads:[~2026-10-16 19:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16 19:45 [PATCH 0/4] arm64, riscv: release shadow stacks on failed fork Iván Ezequiel Rodriguez
2026-10-16 19:46 ` [PATCH 1/4] arm64/gcs: release GCS " Iván Ezequiel Rodriguez
2026-10-16 19:46 ` [PATCH 2/4] riscv/shstk: release shadow stack " Iván Ezequiel Rodriguez
2026-10-16 19:46 ` [PATCH 3/4] selftests/arm64: GCS must not leak on a failed clone3 Iván Ezequiel Rodriguez
2026-10-16 19:46 ` [PATCH 4/4] selftests/riscv: shadow stack " Iván Ezequiel Rodriguez

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

all inboxes | Powered by JetHome®