All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Iván Ezequiel Rodriguez" <ivanrwcm25@gmail.com>
To: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Paul Walmsley <pjw@kernel.org>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-riscv@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Mark Rutland <mark.rutland@arm.com>,
	Mark Brown <broonie@kernel.org>,
	Deepak Gupta <debug@rivosinc.com>,
	Alexandre Ghiti <alex@ghiti.fr>,
	Albert Ou <aou@eecs.berkeley.edu>, Shuah Khan <shuah@kernel.org>,
	Christian Brauner <brauner@kernel.org>,
	James Morse <james.morse@arm.com>,
	Yury Khrustalev <yury.khrustalev@arm.com>,
	Thiago Jung Bauermann <thiago.bauermann@linaro.org>,
	Samuel Holland <samuel.holland@sifive.com>,
	Zong Li <zong.li@sifive.com>,
	Charlie Jenkins <thecharlesjenkins@gmail.com>,
	Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>,
	Zishun Yi <vulab@iscas.ac.cn>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>
Subject: [PATCH v2 0/4] arm64, riscv: release shadow stacks on failed fork
Date: Tue, 20 Oct 2026 15:19:29 -0300	[thread overview]
Message-ID: <cover.1792519121.git.ivanrwcm25@gmail.com> (raw)
In-Reply-To: <cover.1792179433.git.ivanrwcm25@gmail.com>

This is not a port of the x86 TLS fix. 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 add cleanup for a copy_thread() allocation error:
copy_process() skips exit_thread() when copy_thread() fails. arm64
clears inherited allocation tracking before attempting the
allocation; on riscv a failed allocation can still leave the
inherited parent base in place. Tasks created through the args->fn
path do not allocate a user shadow stack in copy_thread(); with
CLONE_VM a later failed copy_process() still shares the caller's
mm, so that path clears inherited tracking before return.

x86 does not need the same args->fn clear: copy_thread() runs
shstk_alloc_thread_stack() before both the PF_KTHREAD and later
args->fn return paths, so CLONE_VM replaces the inherited tracking
first.

The selftests assume /proc is mounted. They use kselftest.h / KTAP.
Feature and clone3 availability skips run before ksft_set_plan().
The plan is three tests: a valid clone3 writes a pidfd, sixteen
bad-pidfd clones return -EFAULT, and the shadow-stack VMA count is
unchanged.

Based on commit f47d223627f8 ("Merge tag 'vfs-7.4-rc1.sync_close' of
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs").

arm64: QEMU 11.1.2 -machine virt -cpu max, CONFIG_ARM64_GCS, one
vCPU. Unpatched VMA count 1->17. Patched 1->1, 3/3 KTAP pass.

riscv: QEMU 11.1.2 -machine virt
-cpu rv64,zimop=on,zcmop=on,zicfiss=on, CONFIG_RISCV_USER_CFI, one
vCPU. Unpatched VMA count 1->17. Patched 1->1, 3/3 KTAP pass.

Changes since v1:
- arm64: introduce gcs_reset_thread() (empty stub without
  CONFIG_ARM64_GCS). Document why x86 does not need the same
  args->fn clear. Comment the property of the args->fn path, not
  only kernel_thread().
- riscv: same args->fn wording; clarify that normal exit reaches
  shstk_release() through deactivate_mm() while failed-fork did not.
- selftests: rewrite on kselftest.h / KTAP. Drop open-coded
  [OK]/[FAIL], exclusive-end VMA matching, ss_kb, depth(16), and
  parent GCSPR/SSP ping checks. Count only VmFlags lines with " ss".
  Skip before ksft_set_plan(). Factor my_syscall2 into gcs-util.h.

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/include/asm/gcs.h                  |   8 +
 arch/arm64/kernel/process.c                   |  19 ++
 arch/riscv/Kconfig                            |   1 +
 arch/riscv/kernel/process.c                   |  20 ++
 tools/testing/selftests/arm64/gcs/Makefile    |   3 +-
 .../selftests/arm64/gcs/gcs-clone-pidfd.c     | 168 +++++++++++++++++
 .../testing/selftests/arm64/gcs/gcs-locking.c |  20 --
 tools/testing/selftests/arm64/gcs/gcs-util.h  |  24 +++
 tools/testing/selftests/arm64/gcs/libc-gcs.c  |  20 --
 tools/testing/selftests/riscv/cfi/Makefile    |   5 +-
 .../selftests/riscv/cfi/shstk-clone-pidfd.c   | 173 ++++++++++++++++++
 12 files changed, 420 insertions(+), 42 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


base-commit: f47d223627f80cb7a1eb14c585fe6cb35de5e984
-- 
2.43.0

WARNING: multiple messages have this Message-ID (diff)
From: "Iván Ezequiel Rodriguez" <ivanrwcm25@gmail.com>
To: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Paul Walmsley <pjw@kernel.org>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-riscv@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Mark Rutland <mark.rutland@arm.com>,
	Mark Brown <broonie@kernel.org>,
	Deepak Gupta <debug@rivosinc.com>,
	Alexandre Ghiti <alex@ghiti.fr>,
	Albert Ou <aou@eecs.berkeley.edu>, Shuah Khan <shuah@kernel.org>,
	Christian Brauner <brauner@kernel.org>,
	James Morse <james.morse@arm.com>,
	Yury Khrustalev <yury.khrustalev@arm.com>,
	Thiago Jung Bauermann <thiago.bauermann@linaro.org>,
	Samuel Holland <samuel.holland@sifive.com>,
	Zong Li <zong.li@sifive.com>,
	Charlie Jenkins <thecharlesjenkins@gmail.com>,
	Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>,
	Zishun Yi <vulab@iscas.ac.cn>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>
Subject: [PATCH v2 0/4] arm64, riscv: release shadow stacks on failed fork
Date: Tue, 20 Oct 2026 15:19:29 -0300	[thread overview]
Message-ID: <cover.1792519121.git.ivanrwcm25@gmail.com> (raw)
In-Reply-To: <cover.1792179433.git.ivanrwcm25@gmail.com>

This is not a port of the x86 TLS fix. 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 add cleanup for a copy_thread() allocation error:
copy_process() skips exit_thread() when copy_thread() fails. arm64
clears inherited allocation tracking before attempting the
allocation; on riscv a failed allocation can still leave the
inherited parent base in place. Tasks created through the args->fn
path do not allocate a user shadow stack in copy_thread(); with
CLONE_VM a later failed copy_process() still shares the caller's
mm, so that path clears inherited tracking before return.

x86 does not need the same args->fn clear: copy_thread() runs
shstk_alloc_thread_stack() before both the PF_KTHREAD and later
args->fn return paths, so CLONE_VM replaces the inherited tracking
first.

The selftests assume /proc is mounted. They use kselftest.h / KTAP.
Feature and clone3 availability skips run before ksft_set_plan().
The plan is three tests: a valid clone3 writes a pidfd, sixteen
bad-pidfd clones return -EFAULT, and the shadow-stack VMA count is
unchanged.

Based on commit f47d223627f8 ("Merge tag 'vfs-7.4-rc1.sync_close' of
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs").

arm64: QEMU 11.1.2 -machine virt -cpu max, CONFIG_ARM64_GCS, one
vCPU. Unpatched VMA count 1->17. Patched 1->1, 3/3 KTAP pass.

riscv: QEMU 11.1.2 -machine virt
-cpu rv64,zimop=on,zcmop=on,zicfiss=on, CONFIG_RISCV_USER_CFI, one
vCPU. Unpatched VMA count 1->17. Patched 1->1, 3/3 KTAP pass.

Changes since v1:
- arm64: introduce gcs_reset_thread() (empty stub without
  CONFIG_ARM64_GCS). Document why x86 does not need the same
  args->fn clear. Comment the property of the args->fn path, not
  only kernel_thread().
- riscv: same args->fn wording; clarify that normal exit reaches
  shstk_release() through deactivate_mm() while failed-fork did not.
- selftests: rewrite on kselftest.h / KTAP. Drop open-coded
  [OK]/[FAIL], exclusive-end VMA matching, ss_kb, depth(16), and
  parent GCSPR/SSP ping checks. Count only VmFlags lines with " ss".
  Skip before ksft_set_plan(). Factor my_syscall2 into gcs-util.h.

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/include/asm/gcs.h                  |   8 +
 arch/arm64/kernel/process.c                   |  19 ++
 arch/riscv/Kconfig                            |   1 +
 arch/riscv/kernel/process.c                   |  20 ++
 tools/testing/selftests/arm64/gcs/Makefile    |   3 +-
 .../selftests/arm64/gcs/gcs-clone-pidfd.c     | 168 +++++++++++++++++
 .../testing/selftests/arm64/gcs/gcs-locking.c |  20 --
 tools/testing/selftests/arm64/gcs/gcs-util.h  |  24 +++
 tools/testing/selftests/arm64/gcs/libc-gcs.c  |  20 --
 tools/testing/selftests/riscv/cfi/Makefile    |   5 +-
 .../selftests/riscv/cfi/shstk-clone-pidfd.c   | 173 ++++++++++++++++++
 12 files changed, 420 insertions(+), 42 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


base-commit: f47d223627f80cb7a1eb14c585fe6cb35de5e984
-- 
2.43.0

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  parent reply	other threads:[~2026-10-20 18:19 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-16 19:45 [PATCH 0/4] arm64, riscv: release shadow stacks on failed fork Iván Ezequiel Rodriguez
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
2026-10-16 19:46   ` Iván Ezequiel Rodriguez
2026-10-20 12:05   ` Mark Brown
2026-10-20 12:05     ` Mark Brown
2026-10-16 19:46 ` [PATCH 2/4] riscv/shstk: release shadow stack " Iván Ezequiel Rodriguez
2026-10-16 19:46   ` 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   ` Iván Ezequiel Rodriguez
2026-10-20 15:16   ` Mark Brown
2026-10-20 15:16     ` Mark Brown
2026-10-16 19:46 ` [PATCH 4/4] selftests/riscv: shadow stack " Iván Ezequiel Rodriguez
2026-10-16 19:46   ` Iván Ezequiel Rodriguez
2026-10-20 18:19 ` Iván Ezequiel Rodriguez [this message]
2026-10-20 18:19   ` [PATCH v2 0/4] arm64, riscv: release shadow stacks on failed fork Iván Ezequiel Rodriguez
2026-10-20 18:19   ` [PATCH v2 1/4] arm64/gcs: release GCS " Iván Ezequiel Rodriguez
2026-10-20 18:19     ` Iván Ezequiel Rodriguez
2026-10-20 18:19   ` [PATCH v2 2/4] riscv/shstk: release shadow stack " Iván Ezequiel Rodriguez
2026-10-20 18:19     ` Iván Ezequiel Rodriguez
2026-10-20 18:19   ` [PATCH v2 3/4] selftests/arm64: GCS must not leak on a failed clone3 Iván Ezequiel Rodriguez
2026-10-20 18:19     ` Iván Ezequiel Rodriguez
2026-10-20 18:19   ` [PATCH v2 4/4] selftests/riscv: shadow stack " Iván Ezequiel Rodriguez
2026-10-20 18:19     ` Iván Ezequiel Rodriguez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1792519121.git.ivanrwcm25@gmail.com \
    --to=ivanrwcm25@gmail.com \
    --cc=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=brauner@kernel.org \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=debug@rivosinc.com \
    --cc=james.morse@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=palmer@dabbelt.com \
    --cc=peterz@infradead.org \
    --cc=pjw@kernel.org \
    --cc=samuel.holland@sifive.com \
    --cc=shuah@kernel.org \
    --cc=tan.shaopeng@jp.fujitsu.com \
    --cc=thecharlesjenkins@gmail.com \
    --cc=thiago.bauermann@linaro.org \
    --cc=vulab@iscas.ac.cn \
    --cc=will@kernel.org \
    --cc=yury.khrustalev@arm.com \
    --cc=zong.li@sifive.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.