public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
@ 2024-06-10 21:02 Kees Cook
  2024-06-11  6:14 ` David Gow
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Kees Cook @ 2024-06-10 21:02 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Kees Cook, David Gow, Ingo Molnar, Borislav Petkov, Dave Hansen,
	x86, H. Peter Anvin, Sean Christopherson, Peter Zijlstra,
	Arnd Bergmann, Kirill A. Shutemov, Qiuxu Zhuo, Nadav Amit,
	Masahiro Yamada, Christian Brauner, David Howells, Uros Bizjak,
	linux-kernel, linux-hardening

When reworking the range checking for get_user(), the get_user_8() case
on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8
was accidentally dropped.) Restore the correct error handling
destination (and rename the jump to using the expected ".L" prefix).

While here, switch to using a named argument ("size") for the call
template ("%c4" to "%c[size]") as already used in the other call
templates in this file.

Found after moving the usercopy selftests to KUnit:

      # usercopy_test_invalid: EXPECTATION FAILED at
      lib/usercopy_kunit.c:278
      Expected val_u64 == 0, but
          val_u64 == -60129542144 (0xfffffff200000000)

Reported-by: David Gow <davidgow@google.com>
Closes: https://lore.kernel.org/all/CABVgOSn=tb=Lj9SxHuT4_9MTjjKVxsq-ikdXC4kGHO4CfKVmGQ@mail.gmail.com
Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user() and put_user()")
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Cc: Nadav Amit <nadav.amit@gmail.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
---
 arch/x86/include/asm/uaccess.h | 4 ++--
 arch/x86/lib/getuser.S         | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 0f9bab92a43d..3a7755c1a441 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -78,10 +78,10 @@ extern int __get_user_bad(void);
 	int __ret_gu;							\
 	register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);		\
 	__chk_user_ptr(ptr);						\
-	asm volatile("call __" #fn "_%c4"				\
+	asm volatile("call __" #fn "_%c[size]"				\
 		     : "=a" (__ret_gu), "=r" (__val_gu),		\
 			ASM_CALL_CONSTRAINT				\
-		     : "0" (ptr), "i" (sizeof(*(ptr))));		\
+		     : "0" (ptr), [size] "i" (sizeof(*(ptr))));		\
 	instrument_get_user(__val_gu);					\
 	(x) = (__force __typeof__(*(ptr))) __val_gu;			\
 	__builtin_expect(__ret_gu, 0);					\
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index 10d5ed8b5990..a1cb3a4e6742 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -44,7 +44,11 @@
 	or %rdx, %rax
 .else
 	cmp $TASK_SIZE_MAX-\size+1, %eax
+.if \size != 8
 	jae .Lbad_get_user
+.else
+	jae .Lbad_get_user_8
+.endif
 	sbb %edx, %edx		/* array_index_mask_nospec() */
 	and %edx, %eax
 .endif
@@ -154,7 +158,7 @@ SYM_CODE_END(__get_user_handle_exception)
 #ifdef CONFIG_X86_32
 SYM_CODE_START_LOCAL(__get_user_8_handle_exception)
 	ASM_CLAC
-bad_get_user_8:
+.Lbad_get_user_8:
 	xor %edx,%edx
 	xor %ecx,%ecx
 	mov $(-EFAULT),%_ASM_AX
-- 
2.34.1


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

* Re: [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
  2024-06-10 21:02 [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking Kees Cook
@ 2024-06-11  6:14 ` David Gow
  2024-06-11  6:21 ` Greg KH
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: David Gow @ 2024-06-11  6:14 UTC (permalink / raw)
  To: Kees Cook
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Sean Christopherson, Peter Zijlstra,
	Arnd Bergmann, Kirill A. Shutemov, Qiuxu Zhuo, Nadav Amit,
	Masahiro Yamada, Christian Brauner, David Howells, Uros Bizjak,
	linux-kernel, linux-hardening

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

On Tue, 11 Jun 2024 at 05:02, Kees Cook <kees@kernel.org> wrote:
>
> When reworking the range checking for get_user(), the get_user_8() case
> on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8
> was accidentally dropped.) Restore the correct error handling
> destination (and rename the jump to using the expected ".L" prefix).
>
> While here, switch to using a named argument ("size") for the call
> template ("%c4" to "%c[size]") as already used in the other call
> templates in this file.
>
> Found after moving the usercopy selftests to KUnit:
>
>       # usercopy_test_invalid: EXPECTATION FAILED at
>       lib/usercopy_kunit.c:278
>       Expected val_u64 == 0, but
>           val_u64 == -60129542144 (0xfffffff200000000)
>
> Reported-by: David Gow <davidgow@google.com>
> Closes: https://lore.kernel.org/all/CABVgOSn=tb=Lj9SxHuT4_9MTjjKVxsq-ikdXC4kGHO4CfKVmGQ@mail.gmail.com
> Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user() and put_user()")
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Sean Christopherson <seanjc@google.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> Cc: Nadav Amit <nadav.amit@gmail.com>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> ---

Thanks: this fixes it here, both under qemu and on real hardware.

Tested-by: David Gow <davidgow@google.com>

-- David

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4014 bytes --]

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

* Re: [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
  2024-06-10 21:02 [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking Kees Cook
  2024-06-11  6:14 ` David Gow
@ 2024-06-11  6:21 ` Greg KH
  2024-06-11  6:57 ` Zhuo, Qiuxu
  2024-06-11 10:29 ` Kirill A. Shutemov
  3 siblings, 0 replies; 5+ messages in thread
From: Greg KH @ 2024-06-11  6:21 UTC (permalink / raw)
  To: Kees Cook
  Cc: Thomas Gleixner, David Gow, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Sean Christopherson,
	Peter Zijlstra, Arnd Bergmann, Kirill A. Shutemov, Qiuxu Zhuo,
	Nadav Amit, Masahiro Yamada, Christian Brauner, David Howells,
	Uros Bizjak, linux-kernel, linux-hardening

On Mon, Jun 10, 2024 at 02:02:27PM -0700, Kees Cook wrote:
> When reworking the range checking for get_user(), the get_user_8() case
> on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8
> was accidentally dropped.) Restore the correct error handling
> destination (and rename the jump to using the expected ".L" prefix).
> 
> While here, switch to using a named argument ("size") for the call
> template ("%c4" to "%c[size]") as already used in the other call
> templates in this file.
> 
> Found after moving the usercopy selftests to KUnit:
> 
>       # usercopy_test_invalid: EXPECTATION FAILED at
>       lib/usercopy_kunit.c:278
>       Expected val_u64 == 0, but
>           val_u64 == -60129542144 (0xfffffff200000000)
> 
> Reported-by: David Gow <davidgow@google.com>
> Closes: https://lore.kernel.org/all/CABVgOSn=tb=Lj9SxHuT4_9MTjjKVxsq-ikdXC4kGHO4CfKVmGQ@mail.gmail.com
> Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user() and put_user()")
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Sean Christopherson <seanjc@google.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> Cc: Nadav Amit <nadav.amit@gmail.com>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> ---
>  arch/x86/include/asm/uaccess.h | 4 ++--
>  arch/x86/lib/getuser.S         | 6 +++++-
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- You have marked a patch with a "Fixes:" tag for a commit that is in an
  older released kernel, yet you do not have a cc: stable line in the
  signed-off-by area at all, which means that the patch will not be
  applied to any older kernel releases.  To properly fix this, please
  follow the documented rules in the
  Documentation/process/stable-kernel-rules.rst file for how to resolve
  this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

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

* RE: [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
  2024-06-10 21:02 [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking Kees Cook
  2024-06-11  6:14 ` David Gow
  2024-06-11  6:21 ` Greg KH
@ 2024-06-11  6:57 ` Zhuo, Qiuxu
  2024-06-11 10:29 ` Kirill A. Shutemov
  3 siblings, 0 replies; 5+ messages in thread
From: Zhuo, Qiuxu @ 2024-06-11  6:57 UTC (permalink / raw)
  To: Kees Cook, Thomas Gleixner
  Cc: David Gow, Ingo Molnar, Borislav Petkov, Dave Hansen,
	x86@kernel.org, H. Peter Anvin, Sean Christopherson,
	Peter Zijlstra, Arnd Bergmann, Kirill A. Shutemov, Nadav Amit,
	Masahiro Yamada, Christian Brauner, David Howells, Uros Bizjak,
	linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org

> From: Kees Cook <kees@kernel.org>
> [...]
> Subject: [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range
> checking
> 
> When reworking the range checking for get_user(), the get_user_8() case on
> 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8 was
> accidentally dropped.) Restore the correct error handling destination (and
> rename the jump to using the expected ".L" prefix).
> 
> While here, switch to using a named argument ("size") for the call template
> ("%c4" to "%c[size]") as already used in the other call templates in this file.
> 
> Found after moving the usercopy selftests to KUnit:
> 
>       # usercopy_test_invalid: EXPECTATION FAILED at
>       lib/usercopy_kunit.c:278
>       Expected val_u64 == 0, but
>           val_u64 == -60129542144 (0xfffffff200000000)
> 
> Reported-by: David Gow <davidgow@google.com>
> Closes: https://lore.kernel.org/all/CABVgOSn=tb=Lj9SxHuT4_9MTjjKVxsq-
> ikdXC4kGHO4CfKVmGQ@mail.gmail.com
> Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user()
> and put_user()")
> Signed-off-by: Kees Cook <kees@kernel.org>
> [...]
>  arch/x86/include/asm/uaccess.h | 4 ++--
>  arch/x86/lib/getuser.S         | 6 +++++-
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/uaccess.h
> b/arch/x86/include/asm/uaccess.h index 0f9bab92a43d..3a7755c1a441
> 100644
> --- a/arch/x86/include/asm/uaccess.h
> +++ b/arch/x86/include/asm/uaccess.h
> @@ -78,10 +78,10 @@ extern int __get_user_bad(void);
>  	int __ret_gu;							\
>  	register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);		\
>  	__chk_user_ptr(ptr);						\
> -	asm volatile("call __" #fn "_%c4"				\
> +	asm volatile("call __" #fn "_%c[size]"				\
>  		     : "=a" (__ret_gu), "=r" (__val_gu),		\
>  			ASM_CALL_CONSTRAINT
> 	\
> -		     : "0" (ptr), "i" (sizeof(*(ptr))));		\
> +		     : "0" (ptr), [size] "i" (sizeof(*(ptr))));		\
>  	instrument_get_user(__val_gu);
> 	\
>  	(x) = (__force __typeof__(*(ptr))) __val_gu;			\
>  	__builtin_expect(__ret_gu, 0);					\
> diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index
> 10d5ed8b5990..a1cb3a4e6742 100644
> --- a/arch/x86/lib/getuser.S
> +++ b/arch/x86/lib/getuser.S
> @@ -44,7 +44,11 @@
>  	or %rdx, %rax
>  .else
>  	cmp $TASK_SIZE_MAX-\size+1, %eax
> +.if \size != 8
>  	jae .Lbad_get_user
> +.else
> +	jae .Lbad_get_user_8
> +.endif
>  	sbb %edx, %edx		/* array_index_mask_nospec() */
>  	and %edx, %eax
>  .endif
> @@ -154,7 +158,7 @@ SYM_CODE_END(__get_user_handle_exception)
>  #ifdef CONFIG_X86_32
>  SYM_CODE_START_LOCAL(__get_user_8_handle_exception)
>  	ASM_CLAC
> -bad_get_user_8:
> +.Lbad_get_user_8:
>  	xor %edx,%edx
>  	xor %ecx,%ecx
>  	mov $(-EFAULT),%_ASM_AX
> --
> 2.34.1

LGTM. Thanks!

Reviewed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>

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

* Re: [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
  2024-06-10 21:02 [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking Kees Cook
                   ` (2 preceding siblings ...)
  2024-06-11  6:57 ` Zhuo, Qiuxu
@ 2024-06-11 10:29 ` Kirill A. Shutemov
  3 siblings, 0 replies; 5+ messages in thread
From: Kirill A. Shutemov @ 2024-06-11 10:29 UTC (permalink / raw)
  To: Kees Cook
  Cc: Thomas Gleixner, David Gow, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Sean Christopherson,
	Peter Zijlstra, Arnd Bergmann, Qiuxu Zhuo, Nadav Amit,
	Masahiro Yamada, Christian Brauner, David Howells, Uros Bizjak,
	linux-kernel, linux-hardening

On Mon, Jun 10, 2024 at 02:02:27PM -0700, Kees Cook wrote:
> When reworking the range checking for get_user(), the get_user_8() case
> on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8
> was accidentally dropped.) Restore the correct error handling
> destination (and rename the jump to using the expected ".L" prefix).

Oh. My bad.

Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

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

end of thread, other threads:[~2024-06-11 10:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-10 21:02 [PATCH] x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking Kees Cook
2024-06-11  6:14 ` David Gow
2024-06-11  6:21 ` Greg KH
2024-06-11  6:57 ` Zhuo, Qiuxu
2024-06-11 10:29 ` Kirill A. Shutemov

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