Re: [PATCH v2 13/18] uaccess: generalize access_ok()

2022-02-24 Thread Stafford Horne
On Wed, Feb 16, 2022 at 02:13:27PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann 
> 
> There are many different ways that access_ok() is defined across
> architectures, but in the end, they all just compare against the
> user_addr_max() value or they accept anything.
> 
> Provide one definition that works for most architectures, checking
> against TASK_SIZE_MAX for user processes or skipping the check inside
> of uaccess_kernel() sections.
> 
> For architectures without CONFIG_SET_FS(), this should be the fastest
> check, as it comes down to a single comparison of a pointer against a
> compile-time constant, while the architecture specific versions tend to
> do something more complex for historic reasons or get something wrong.
> 
> Type checking for __user annotations is handled inconsistently across
> architectures, but this is easily simplified as well by using an inline
> function that takes a 'const void __user *' argument. A handful of
> callers need an extra __user annotation for this.
> 
> Some architectures had trick to use 33-bit or 65-bit arithmetic on the
> addresses to calculate the overflow, however this simpler version uses
> fewer registers, which means it can produce better object code in the
> end despite needing a second (statically predicted) branch.
> 
> Reviewed-by: Christoph Hellwig 
> Acked-by: Mark Rutland  [arm64, asm-generic]
> Signed-off-by: Arnd Bergmann 
> ---
...
>  arch/openrisc/include/asm/uaccess.h   | 19 +
...
>  include/asm-generic/access_ok.h   | 59 +++
>  include/asm-generic/uaccess.h | 21 +-
>  include/linux/uaccess.h   |  7 
>  32 files changed, 109 insertions(+), 366 deletions(-)
> 
...
> diff --git a/arch/openrisc/include/asm/uaccess.h 
> b/arch/openrisc/include/asm/uaccess.h
> index 120f5005461b..8f049ec99b3e 100644
> --- a/arch/openrisc/include/asm/uaccess.h
> +++ b/arch/openrisc/include/asm/uaccess.h
> @@ -45,21 +45,7 @@
>  
>  #define uaccess_kernel() (get_fs() == KERNEL_DS)
>  
> -/* Ensure that the range from addr to addr+size is all within the process'
> - * address space
> - */
> -static inline int __range_ok(unsigned long addr, unsigned long size)
> -{
> - const mm_segment_t fs = get_fs();
> -
> - return size <= fs && addr <= (fs - size);
> -}
> -
> -#define access_ok(addr, size)
> \
> -({   \
> - __chk_user_ptr(addr);   \
> - __range_ok((unsigned long)(addr), (size));  \
> -})
> +#include 

I was going to ask why we are missing __chk_user_ptr in the generic version.
But this is basically now a no-op so I think its OK.

>  /*
>   * These are the main single-value transfer routines.  They automatically
> @@ -268,9 +254,6 @@ clear_user(void __user *addr, unsigned long size)
>   return size;
>  }
>  
> -#define user_addr_max() \
> - (uaccess_kernel() ? ~0UL : TASK_SIZE)
> -
>  extern long strncpy_from_user(char *dest, const char __user *src, long 
> count);
>  
>  extern __must_check long strnlen_user(const char __user *str, long n);

...
> diff --git a/include/asm-generic/access_ok.h b/include/asm-generic/access_ok.h
> new file mode 100644
> index ..1aad8964d2ed
> --- /dev/null
> +++ b/include/asm-generic/access_ok.h
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ASM_GENERIC_ACCESS_OK_H__
> +#define __ASM_GENERIC_ACCESS_OK_H__
> +
> +/*
> + * Checking whether a pointer is valid for user space access.
> + * These definitions work on most architectures, but overrides can
> + * be used where necessary.
> + */
> +
> +/*
> + * architectures with compat tasks have a variable TASK_SIZE and should
> + * override this to a constant.
> + */
> +#ifndef TASK_SIZE_MAX
> +#define TASK_SIZE_MAXTASK_SIZE
> +#endif
> +
> +#ifndef uaccess_kernel
> +#ifdef CONFIG_SET_FS
> +#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
> +#else
> +#define uaccess_kernel() (0)
> +#endif
> +#endif
> +
> +#ifndef user_addr_max
> +#define user_addr_max()  (uaccess_kernel() ? ~0UL : 
> TASK_SIZE_MAX)
> +#endif
> +
> +#ifndef __access_ok
> +/*
> + * 'size' is a compile-time constant for most callers, so optimize for
> + * this case to turn the check into a single comparison against a constant
> + * limit and catch all possible overflows.
> + * On architectures with separate user address space (m68k, s390, parisc,
> + * sparc64) or those without an MMU, this should always return true.
> + *
> + * This version was originally contributed by Jonas Bonn for the
> + * OpenRISC architecture, and was found to be the most efficient
> + * for constant 'size' and 'limit' values.
> + */
> +static inline int __access_ok(const void __user *ptr, unsigned long size)
> +{
> + unsigned long limit = user_addr_max();
> + unsigned

Re: [PATCH v2 13/18] uaccess: generalize access_ok()

2022-02-24 Thread Arnd Bergmann
On Thu, Feb 24, 2022 at 9:29 AM Stafford Horne  wrote:

> > -
> > -#define access_ok(addr, size)  
> >   \
> > -({   \
> > - __chk_user_ptr(addr);   \
> > - __range_ok((unsigned long)(addr), (size));  \
> > -})
> > +#include 
>
> I was going to ask why we are missing __chk_user_ptr in the generic version.
> But this is basically now a no-op so I think its OK.

Correct, the type checking is implied by making __access_ok() an inline
function that takes a __user pointer.

> Acked-by: Stafford Horne  [openrisc, asm-generic]

Thanks!

   Arnd

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v2 18/18] uaccess: drop maining CONFIG_SET_FS users

2022-02-24 Thread Stafford Horne
On Wed, Feb 16, 2022 at 02:13:32PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann 
> 
> There are no remaining callers of set_fs(), so CONFIG_SET_FS
> can be removed globally, along with the thread_info field and
> any references to it.
> 
> This turns access_ok() into a cheaper check against TASK_SIZE_MAX.
> 
> With CONFIG_SET_FS gone, so drop all remaining references to
> set_fs()/get_fs(), mm_segment_t and uaccess_kernel().
> 
> Signed-off-by: Arnd Bergmann 
> ---
...
>  arch/openrisc/Kconfig |  1 -
>  arch/openrisc/include/asm/thread_info.h   |  7 ---
>  arch/openrisc/include/asm/uaccess.h   | 23 
...
>  fs/exec.c |  6 --
>  include/asm-generic/access_ok.h   | 10 +---
>  include/asm-generic/uaccess.h | 25 +---
>  include/linux/syscalls.h  |  4 --
>  include/linux/uaccess.h   | 33 ---
>  include/rdma/ib.h |  2 +-
>  kernel/events/callchain.c |  4 --
>  kernel/events/core.c  |  3 -
>  kernel/exit.c | 14 -
>  kernel/kthread.c  |  5 --
>  kernel/stacktrace.c   |  3 -
>  kernel/trace/bpf_trace.c  |  4 --
>  mm/maccess.c  | 11 
>  mm/memory.c   |  8 ---
>  net/bpfilter/bpfilter_kern.c  |  2 +-
>  72 files changed, 10 insertions(+), 522 deletions(-)
>  delete mode 100644 arch/arc/include/asm/segment.h
>  delete mode 100644 arch/csky/include/asm/segment.h
>  delete mode 100644 arch/h8300/include/asm/segment.h
> 
> diff --git a/arch/Kconfig b/arch/Kconfig
> index fa5db36bda67..99349547afed 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -24,9 +24,6 @@ config KEXEC_ELF
>  config HAVE_IMA_KEXEC
>   bool
>  
> -config SET_FS
> - bool
> -
>  config HOTPLUG_SMT
>   bool
>  
...
> diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
> index f724b3f1aeed..0d68adf6e02b 100644
> --- a/arch/openrisc/Kconfig
> +++ b/arch/openrisc/Kconfig
> @@ -36,7 +36,6 @@ config OPENRISC
>   select ARCH_WANT_FRAME_POINTERS
>   select GENERIC_IRQ_MULTI_HANDLER
>   select MMU_GATHER_NO_RANGE if MMU
> - select SET_FS
>   select TRACE_IRQFLAGS_SUPPORT
>  
>  config CPU_BIG_ENDIAN
> diff --git a/arch/openrisc/include/asm/thread_info.h 
> b/arch/openrisc/include/asm/thread_info.h
> index 659834ab87fa..4af3049c34c2 100644
> --- a/arch/openrisc/include/asm/thread_info.h
> +++ b/arch/openrisc/include/asm/thread_info.h
> @@ -40,18 +40,12 @@
>   */
>  #ifndef __ASSEMBLY__
>  
> -typedef unsigned long mm_segment_t;
> -
>  struct thread_info {
>   struct task_struct  *task;  /* main task structure */
>   unsigned long   flags;  /* low level flags */
>   __u32   cpu;/* current CPU */
>   __s32   preempt_count; /* 0 => preemptable, <0 => BUG */
>  
> - mm_segment_taddr_limit; /* thread address space:
> -0-0x7FFF for user-thead
> -0-0x for kernel-thread
> -  */
>   __u8supervisor_stack[0];
>  
>   /* saved context data */
> @@ -71,7 +65,6 @@ struct thread_info {
>   .flags  = 0,\
>   .cpu= 0,\
>   .preempt_count  = INIT_PREEMPT_COUNT,   \
> - .addr_limit = KERNEL_DS,\
>   .ksp= 0,\
>  }
>  
> diff --git a/arch/openrisc/include/asm/uaccess.h 
> b/arch/openrisc/include/asm/uaccess.h
> index 8f049ec99b3e..d6500a374e18 100644
> --- a/arch/openrisc/include/asm/uaccess.h
> +++ b/arch/openrisc/include/asm/uaccess.h
> @@ -22,29 +22,6 @@
>  #include 
>  #include 
>  #include 
> -
> -/*
> - * The fs value determines whether argument validity checking should be
> - * performed or not.  If get_fs() == USER_DS, checking is performed, with
> - * get_fs() == KERNEL_DS, checking is bypassed.
> - *
> - * For historical reasons, these macros are grossly misnamed.
> - */
> -
> -/* addr_limit is the maximum accessible address for the task. we misuse
> - * the KERNEL_DS and USER_DS values to both assign and compare the
> - * addr_limit values through the equally misnamed get/set_fs macros.
> - * (see above)
> - */
> -
> -#define KERNEL_DS(~0UL)
> -
> -#define USER_DS  (TASK_SIZE)
> -#define get_fs() (current_thread_info()->addr_limit)
> -#define set_fs(x)(current_thread_info()->addr_limit = (x))
> -
> -#define uaccess_kernel() (get_fs() == KERNEL_DS)
> -
>  #include 
>  
>  /*
...
> diff --git a/fs/exec.c b/fs/exec.c
> index 79f2c9483302..bc68a0c089ac 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1303,12 +1303,6 @@ int 

Re: [PATCH v2 02/18] uaccess: fix nios2 and microblaze get_user_8()

2022-02-24 Thread Dinh Nguyen




On 2/16/22 07:13, Arnd Bergmann wrote:

From: Arnd Bergmann 

These two architectures implement 8-byte get_user() through
a memcpy() into a four-byte variable, which won't fit.

Use a temporary 64-bit variable instead here, and use a double
cast the way that risc-v and openrisc do to avoid compile-time
warnings.

Fixes: 6a090e97972d ("arch/microblaze: support get_user() of size 8 bytes")
Fixes: 5ccc6af5e88e ("nios2: Memory management")
Signed-off-by: Arnd Bergmann 
---
  arch/microblaze/include/asm/uaccess.h | 18 +-
  arch/nios2/include/asm/uaccess.h  | 26 --
  2 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/arch/microblaze/include/asm/uaccess.h 
b/arch/microblaze/include/asm/uaccess.h
index 5b6e0e7788f4..3fe96979d2c6 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -130,27 +130,27 @@ extern long __user_bad(void);
  
  #define __get_user(x, ptr)		\

  ({\
-   unsigned long __gu_val = 0; \
long __gu_err;  \
switch (sizeof(*(ptr))) {   \
case 1: \
-   __get_user_asm("lbu", (ptr), __gu_val, __gu_err); \
+   __get_user_asm("lbu", (ptr), x, __gu_err);\
break;  \
case 2: \
-   __get_user_asm("lhu", (ptr), __gu_val, __gu_err); \
+   __get_user_asm("lhu", (ptr), x, __gu_err);\
break;  \
case 4: \
-   __get_user_asm("lw", (ptr), __gu_val, __gu_err);  \
+   __get_user_asm("lw", (ptr), x, __gu_err); \
break;  \
-   case 8: \
-   __gu_err = __copy_from_user(&__gu_val, ptr, 8); \
-   if (__gu_err)   \
-   __gu_err = -EFAULT; \
+   case 8: {   \
+   __u64 __x = 0;  \
+   __gu_err = raw_copy_from_user(&__x, ptr, 8) ?   \
+   -EFAULT : 0;\
+   (x) = (typeof(x))(typeof((x) - (x)))__x;\
break;  \
+   }   \
default:\
/* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
}   \
-   x = (__force __typeof__(*(ptr))) __gu_val;  \
__gu_err;   \
  })
  
diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h

index ba9340e96fd4..ca9285a915ef 100644
--- a/arch/nios2/include/asm/uaccess.h
+++ b/arch/nios2/include/asm/uaccess.h
@@ -88,6 +88,7 @@ extern __must_check long strnlen_user(const char __user *s, 
long n);
  /* Optimized macros */
  #define __get_user_asm(val, insn, addr, err)  \
  { \
+   unsigned long __gu_val; \
__asm__ __volatile__(   \
"   movi%0, %3\n" \
"1:   " insn " %1, 0(%2)\n" \
@@ -96,14 +97,20 @@ extern __must_check long strnlen_user(const char __user *s, 
long n);
"   .section __ex_table,\"a\"\n"\
"   .word 1b, 2b\n"   \
"   .previous"\
-   : "=&r" (err), "=r" (val)   \
+   : "=&r" (err), "=r" (__gu_val)  \
: "r" (addr), "i" (-EFAULT));   \
+   val = (__force __typeof__(*(addr)))__gu_val;\
  }
  
-#define __get_user_unknown(val, size, ptr, err) do {			\

+extern void __get_user_unknown(void);
+
+#define __get_user_8(val, ptr, err) do {   \
+   u64 __val = 0;  \
err = 

Re: [PATCH v2 12/18] uaccess: fix type mismatch warnings from access_ok()

2022-02-24 Thread Dinh Nguyen




On 2/16/22 07:13, Arnd Bergmann wrote:

From: Arnd Bergmann 

On some architectures, access_ok() does not do any argument type
checking, so replacing the definition with a generic one causes
a few warnings for harmless issues that were never caught before.

Fix the ones that I found either through my own test builds or
that were reported by the 0-day bot.

Reported-by: kernel test robot 
Signed-off-by: Arnd Bergmann 
---
  arch/arc/kernel/process.c   |  2 +-
  arch/arm/kernel/swp_emulate.c   |  2 +-
  arch/arm/kernel/traps.c |  2 +-
  arch/csky/kernel/signal.c   |  2 +-
  arch/mips/sibyte/common/sb_tbprof.c |  6 +++---
  arch/nios2/kernel/signal.c  | 20 +++-


Acked-by: Dinh Nguyen 

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v2 13/18] uaccess: generalize access_ok()

2022-02-24 Thread Dinh Nguyen




On 2/16/22 07:13, Arnd Bergmann wrote:

From: Arnd Bergmann 

There are many different ways that access_ok() is defined across
architectures, but in the end, they all just compare against the
user_addr_max() value or they accept anything.

Provide one definition that works for most architectures, checking
against TASK_SIZE_MAX for user processes or skipping the check inside
of uaccess_kernel() sections.

For architectures without CONFIG_SET_FS(), this should be the fastest
check, as it comes down to a single comparison of a pointer against a
compile-time constant, while the architecture specific versions tend to
do something more complex for historic reasons or get something wrong.

Type checking for __user annotations is handled inconsistently across
architectures, but this is easily simplified as well by using an inline
function that takes a 'const void __user *' argument. A handful of
callers need an extra __user annotation for this.

Some architectures had trick to use 33-bit or 65-bit arithmetic on the
addresses to calculate the overflow, however this simpler version uses
fewer registers, which means it can produce better object code in the
end despite needing a second (statically predicted) branch.

Reviewed-by: Christoph Hellwig 
Acked-by: Mark Rutland  [arm64, asm-generic]
Signed-off-by: Arnd Bergmann 
---
  arch/Kconfig  |  7 
  arch/alpha/include/asm/uaccess.h  | 34 +++
  arch/arc/include/asm/uaccess.h| 29 -
  arch/arm/include/asm/uaccess.h| 20 +
  arch/arm64/include/asm/uaccess.h  | 11 ++---
  arch/csky/include/asm/uaccess.h   |  8 
  arch/hexagon/include/asm/uaccess.h| 25 
  arch/ia64/include/asm/uaccess.h   |  5 +--
  arch/m68k/Kconfig.cpu |  1 +
  arch/m68k/include/asm/uaccess.h   | 19 +
  arch/microblaze/include/asm/uaccess.h |  8 +---
  arch/mips/include/asm/uaccess.h   | 29 +
  arch/nds32/include/asm/uaccess.h  |  7 +---
  arch/nios2/include/asm/uaccess.h  | 11 +


Acked-by: Dinh Nguyen 

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH v2 18/18] uaccess: drop maining CONFIG_SET_FS users

2022-02-24 Thread Dinh Nguyen




On 2/16/22 07:13, Arnd Bergmann wrote:

From: Arnd Bergmann 

There are no remaining callers of set_fs(), so CONFIG_SET_FS
can be removed globally, along with the thread_info field and
any references to it.

This turns access_ok() into a cheaper check against TASK_SIZE_MAX.

With CONFIG_SET_FS gone, so drop all remaining references to
set_fs()/get_fs(), mm_segment_t and uaccess_kernel().

Signed-off-by: Arnd Bergmann 
---
  arch/Kconfig  |  3 -
  arch/alpha/Kconfig|  1 -
  arch/alpha/include/asm/processor.h|  4 --
  arch/alpha/include/asm/thread_info.h  |  2 -
  arch/alpha/include/asm/uaccess.h  | 19 --
  arch/arc/Kconfig  |  1 -
  arch/arc/include/asm/segment.h| 20 ---
  arch/arc/include/asm/thread_info.h|  3 -
  arch/arc/include/asm/uaccess.h|  1 -
  arch/arm/lib/uaccess_with_memcpy.c| 10 
  arch/csky/Kconfig |  1 -
  arch/csky/include/asm/processor.h |  2 -
  arch/csky/include/asm/segment.h   | 10 
  arch/csky/include/asm/thread_info.h   |  2 -
  arch/csky/include/asm/uaccess.h   |  3 -
  arch/csky/kernel/asm-offsets.c|  1 -
  arch/h8300/Kconfig|  1 -
  arch/h8300/include/asm/processor.h|  1 -
  arch/h8300/include/asm/segment.h  | 40 -
  arch/h8300/include/asm/thread_info.h  |  3 -
  arch/h8300/kernel/entry.S |  1 -
  arch/h8300/kernel/head_ram.S  |  1 -
  arch/h8300/mm/init.c  |  6 --
  arch/h8300/mm/memory.c|  1 -
  arch/hexagon/Kconfig  |  1 -
  arch/hexagon/include/asm/thread_info.h|  6 --
  arch/hexagon/kernel/process.c |  1 -
  arch/microblaze/Kconfig   |  1 -
  arch/microblaze/include/asm/thread_info.h |  6 --
  arch/microblaze/include/asm/uaccess.h | 24 
  arch/microblaze/kernel/asm-offsets.c  |  1 -
  arch/microblaze/kernel/process.c  |  1 -
  arch/nds32/Kconfig|  1 -
  arch/nds32/include/asm/thread_info.h  |  4 --
  arch/nds32/include/asm/uaccess.h  | 15 +
  arch/nds32/kernel/process.c   |  5 +-
  arch/nds32/mm/alignment.c |  3 -
  arch/nios2/Kconfig|  1 -
  arch/nios2/include/asm/thread_info.h  |  9 ---
  arch/nios2/include/asm/uaccess.h  | 12 


For NIOS2:

Acked-by: Dinh Nguyen 

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc