Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Brown <broonie@kernel.org>
To: "Iván Ezequiel Rodriguez" <ivanrwcm25@gmail.com>
Cc: 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, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org,
	Mark Rutland <mark.rutland@arm.com>,
	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: Re: [PATCH 3/4] selftests/arm64: GCS must not leak on a failed clone3
Date: Tue, 20 Oct 2026 16:16:26 +0100	[thread overview]
Message-ID: <ateFyuJkEgL94Rvc@sirena.org.uk> (raw)
In-Reply-To: <ed22ebf64ed00a56d5e1eff31ac639fef00dcae6.1792179433.git.ivanrwcm25@gmail.com>

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

On Fri, Oct 16, 2026 at 04:46:02PM -0300, Iván Ezequiel Rodriguez wrote:

> clone3(CLONE_VM|CLONE_PIDFD) with an unwritable pidfd pointer fails
> in put_user() after copy_thread() has mapped a GCS. copy_process()
> then calls exit_thread(). Without HAVE_EXIT_THREAD that free is a
> no-op and the VMA stays in the parent's mm.

> Assisted-by: LLM

This is pretty hard to follow, there's a lot of open coding, duplication
and strange structures or tests.  It makes it hard to follow what's
actually being tested and why which is going to be a maintainability
issue.

> +/* Same value as KSFT_SKIP in kselftest.h. */
> +#define KSFT_SKIP		4

Why are we not just including kselftest.h?  It doesn't have the fun
interactions with libc headers that some of the other things have.
If we are going to cut'n'paste values why only KSFT_SKIP and not any of
the other exit codes we use?

> +/* Same wrapper as gcs-locking.c: extra prctl args must be zero. */
> +#define my_syscall2(num, arg1, arg2)					\
> +({									\
> +	register long _num  __asm__ ("x8") = (num);			\
> +	register long _arg1 __asm__ ("x0") = (long)(arg1);		\
> +	register long _arg2 __asm__ ("x1") = (long)(arg2);		\
> +	register long _arg3 __asm__ ("x2") = 0;				\
> +	register long _arg4 __asm__ ("x3") = 0;				\
> +	register long _arg5 __asm__ ("x4") = 0;				\
> +									\
> +	__asm__ volatile (						\
> +		"svc #0\n"						\
> +		: "=r"(_arg1)						\
> +		: "r"(_arg1), "r"(_arg2),				\
> +		  "r"(_arg3), "r"(_arg4),				\
> +		  "r"(_arg5), "r"(_num)					\
> +		: "memory", "cc"					\
> +	);								\
> +	_arg1;								\
> +})

Factor this out.

> +static void on_fault(int sig)
> +{
> +	static const char msg[] = "[FAIL]\tparent guarded control stack faulted\n";

This isn't KTAP format.

> +		/*
> +		 * An empty GCS leaves GCSPR at the exclusive end. If
> +		 * the next VMA is contiguous that address is also the
> +		 * start of the next range; prefer the mapping that
> +		 * ends here.
> +		 */

I'm not clear what you mean by exclusive end here?

> +static int skip_enable(long rc)
> +{
> +	if (rc == -EOPNOTSUPP) {
> +		printf("[SKIP]\tkernel has no GCS\n");
> +	} else if (rc == -EINVAL) {
> +		printf("[SKIP]\tkernel built without GCS\n");
> +	} else if (rc == -EBUSY) {
> +		printf("[SKIP]\tGCS is locked\n");
> +	} else {
> +		printf("[FAIL]\tPR_SET_SHADOW_STACK_STATUS returned %ld\n", rc);
> +		return 1;
> +	}
> +	return KSFT_SKIP;
> +}

This feels rather contorted, and ends up returning a raw 1 from main()
rather than a KSFT_ exit code.

> +int main(void)
> +{
> +	struct sigaction sa;
> +	struct ss_span parent;
> +	void *stack;
> +	void *bad_pidfd;
> +	unsigned long gcspr, gcspr_mid;
> +	unsigned long gcs_mode;
> +	long rc;
> +	int pidfd;
> +	int vmas0, kb0, vmas1, kb1;
> +	int i, kept, d, cret;
> +
> +	setbuf(stdout, NULL);

There's also setvbuf().  Using kselftest.h and it's helpers would
probably be better, it takes care of disabling buffering.  I can't see
any reason to avoid that.

> +	gcspr = (unsigned long)get_gcspr();
> +	if (!gcspr) {
> +		printf("[FAIL]\tenable left GCSPR_EL0 at 0\n");
> +		_exit(1);
> +	}

Why are we using _exit(), and more of these raw 1s?

> +	gcspr = (unsigned long)get_gcspr();
> +	ss_scan(&vmas0, &kb0, gcspr, &parent, NULL, NULL);
> +	if (!parent.start) {
> +		printf("[FAIL]\tGCSPR %lx matches no shadow-stack VMA\n", gcspr);
> +		_exit(1);
> +	}

Why is this something we're validating, and how do we expect to be able
to do function calls if it is the case?

> +	if (vmas1 != vmas0 || kb1 != kb0) {
> +		printf("[FAIL]\tleaked %d shadow-stack VMA(s), %d kB\n",
> +		       vmas1 - vmas0, kb1 - kb0);
> +		_exit(1);
> +	}
> +	if (!kept) {
> +		printf("[FAIL]\tparent GCS %lx-%lx was unmapped\n",
> +		       parent.start, parent.end);
> +		_exit(2);
> +	}

Why are some failures exiting with a different exit code?

> +	if (d != 17) {
> +		printf("[FAIL]\tparent call/return returned %d, want 17\n", d);
> +		_exit(2);
> +	}

...because?

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

  reply	other threads:[~2026-10-20 15:17 UTC|newest]

Thread overview: 12+ 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:46 ` [PATCH 1/4] arm64/gcs: release GCS " Iván Ezequiel Rodriguez
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 ` [PATCH 3/4] selftests/arm64: GCS must not leak on a failed clone3 Iván Ezequiel Rodriguez
2026-10-20 15:16   ` Mark Brown [this message]
2026-10-16 19:46 ` [PATCH 4/4] selftests/riscv: shadow stack " Iván Ezequiel Rodriguez
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   ` [PATCH v2 2/4] riscv/shstk: release shadow stack " 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   ` [PATCH v2 4/4] selftests/riscv: shadow stack " 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=ateFyuJkEgL94Rvc@sirena.org.uk \
    --to=broonie@kernel.org \
    --cc=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=brauner@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=debug@rivosinc.com \
    --cc=ivanrwcm25@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox