Thread (5 messages) 5 messages, 4 authors, 2024-07-06

Re: [PATCH] powerpc/rtas: Prevent Spectre v1 gadget construction in sys_rtas()

From: Nathan Lynch <hidden>
Date: 2024-05-31 16:47:16

Breno Leitao [off-list ref] writes:
On Thu, May 30, 2024 at 07:44:12PM -0500, Nathan Lynch via B4 Relay wrote:
quoted
From: Nathan Lynch <redacted>

Smatch warns:

  arch/powerpc/kernel/rtas.c:1932 __do_sys_rtas() warn: potential
  spectre issue 'args.args' [r] (local cap)

The 'nargs' and 'nret' locals come directly from a user-supplied
buffer and are used as indexes into a small stack-based array and as
inputs to copy_to_user() after they are subject to bounds checks.

Use array_index_nospec() after the bounds checks to clamp these values
for speculative execution.

Signed-off-by: Nathan Lynch <redacted>
Reported-by: Breno Leitao <leitao@debian.org>
Thanks for working on it. 

Reviewed-by: Breno Leitao <leitao@debian.org>
Thanks!
quoted
+	nargs = array_index_nospec(nargs, ARRAY_SIZE(args.args));
+	nret = array_index_nospec(nret, ARRAY_SIZE(args.args) - nargs);
On an unrelated note, can nargs and nret are integers and could be
eventually negative. Is this a valid use case?
No, it's not valid for a caller to provide negative nargs or nret. I
convinced myself that this bounds check:

	nargs = be32_to_cpu(args.nargs);
	nret  = be32_to_cpu(args.nret);

	if (nargs >= ARRAY_SIZE(args.args)
	    || nret > ARRAY_SIZE(args.args)
	    || nargs + nret > ARRAY_SIZE(args.args))
		return -EINVAL;

rejects negative values of nargs or nret due to C's "usual arithmetic
conversions", where nargs and nret are implicitly converted to size_t
for the comparisons.

However I don't see any value in keeping them as signed int. I have some
changes in progress in this area and I'll plan on making these unsigned.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help