Re: [PATCH v18 02/15] arm64: Introduce prctl() options to control the tagged user addresses ABI

2019-06-24 Thread Kees Cook
On Mon, Jun 24, 2019 at 04:32:47PM +0200, Andrey Konovalov wrote:
> From: Catalin Marinas 
> 
> It is not desirable to relax the ABI to allow tagged user addresses into
> the kernel indiscriminately. This patch introduces a prctl() interface
> for enabling or disabling the tagged ABI with a global sysctl control
> for preventing applications from enabling the relaxed ABI (meant for
> testing user-space prctl() return error checking without reconfiguring
> the kernel). The ABI properties are inherited by threads of the same
> application and fork()'ed children but cleared on execve(). A Kconfig
> option allows the overall disabling of the relaxed ABI.
> 
> The PR_SET_TAGGED_ADDR_CTRL will be expanded in the future to handle
> MTE-specific settings like imprecise vs precise exceptions.
> 
> Signed-off-by: Catalin Marinas 

Reviewed-by: Kees Cook 

-Kees

> Signed-off-by: Andrey Konovalov 
> ---
>  arch/arm64/Kconfig   |  9 
>  arch/arm64/include/asm/processor.h   |  8 
>  arch/arm64/include/asm/thread_info.h |  1 +
>  arch/arm64/include/asm/uaccess.h |  4 +-
>  arch/arm64/kernel/process.c  | 72 
>  include/uapi/linux/prctl.h   |  5 ++
>  kernel/sys.c | 12 +
>  7 files changed, 110 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 697ea0510729..55fbaf20af2d 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1107,6 +1107,15 @@ config ARM64_SW_TTBR0_PAN
> zeroed area and reserved ASID. The user access routines
> restore the valid TTBR0_EL1 temporarily.
>  
> +config ARM64_TAGGED_ADDR_ABI
> + bool "Enable the tagged user addresses syscall ABI"
> + default y
> + help
> +   When this option is enabled, user applications can opt in to a
> +   relaxed ABI via prctl() allowing tagged addresses to be passed
> +   to system calls as pointer arguments. For details, see
> +   Documentation/arm64/tagged-address-abi.txt.
> +
>  menuconfig COMPAT
>   bool "Kernel support for 32-bit EL0"
>   depends on ARM64_4K_PAGES || EXPERT
> diff --git a/arch/arm64/include/asm/processor.h 
> b/arch/arm64/include/asm/processor.h
> index fd5b1a4efc70..ee86070a28d4 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -296,6 +296,14 @@ extern void __init minsigstksz_setup(void);
>  /* PR_PAC_RESET_KEYS prctl */
>  #define PAC_RESET_KEYS(tsk, arg) ptrauth_prctl_reset_keys(tsk, arg)
>  
> +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
> +/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */
> +long set_tagged_addr_ctrl(unsigned long arg);
> +long get_tagged_addr_ctrl(void);
> +#define SET_TAGGED_ADDR_CTRL(arg)set_tagged_addr_ctrl(arg)
> +#define GET_TAGGED_ADDR_CTRL()   get_tagged_addr_ctrl()
> +#endif
> +
>  /*
>   * For CONFIG_GCC_PLUGIN_STACKLEAK
>   *
> diff --git a/arch/arm64/include/asm/thread_info.h 
> b/arch/arm64/include/asm/thread_info.h
> index 2372e97db29c..4f81c4f15404 100644
> --- a/arch/arm64/include/asm/thread_info.h
> +++ b/arch/arm64/include/asm/thread_info.h
> @@ -88,6 +88,7 @@ void arch_release_task_struct(struct task_struct *tsk);
>  #define TIF_SVE  23  /* Scalable Vector Extension in 
> use */
>  #define TIF_SVE_VL_INHERIT   24  /* Inherit sve_vl_onexec across exec */
>  #define TIF_SSBD 25  /* Wants SSB mitigation */
> +#define TIF_TAGGED_ADDR  26  /* Allow tagged user addresses 
> */
>  
>  #define _TIF_SIGPENDING  (1 << TIF_SIGPENDING)
>  #define _TIF_NEED_RESCHED(1 << TIF_NEED_RESCHED)
> diff --git a/arch/arm64/include/asm/uaccess.h 
> b/arch/arm64/include/asm/uaccess.h
> index a138e3b4f717..097d6bfac0b7 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -62,7 +62,9 @@ static inline unsigned long __range_ok(const void __user 
> *addr, unsigned long si
>  {
>   unsigned long ret, limit = current_thread_info()->addr_limit;
>  
> - addr = untagged_addr(addr);
> + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) &&
> + test_thread_flag(TIF_TAGGED_ADDR))
> + addr = untagged_addr(addr);
>  
>   __chk_user_ptr(addr);
>   asm volatile(
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 9856395ccdb7..60e70158a4a1 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -19,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -307,11 +308,18 @@ static void tls_thread_flush(void)
>   }
>  }
>  
> +static void flush_tagged_addr_state(void)
> +{
> + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI))
> + clear_thread_flag(TIF_TAGGED_ADDR);
> +}
> +
>  void flush_thread(void)
>  {
>   fpsimd_flush_thread();
>   tls_thread_flush();
>   flush_ptrace_hw_breakpoint(current);
> + 

[PATCH v18 02/15] arm64: Introduce prctl() options to control the tagged user addresses ABI

2019-06-24 Thread Andrey Konovalov
From: Catalin Marinas 

It is not desirable to relax the ABI to allow tagged user addresses into
the kernel indiscriminately. This patch introduces a prctl() interface
for enabling or disabling the tagged ABI with a global sysctl control
for preventing applications from enabling the relaxed ABI (meant for
testing user-space prctl() return error checking without reconfiguring
the kernel). The ABI properties are inherited by threads of the same
application and fork()'ed children but cleared on execve(). A Kconfig
option allows the overall disabling of the relaxed ABI.

The PR_SET_TAGGED_ADDR_CTRL will be expanded in the future to handle
MTE-specific settings like imprecise vs precise exceptions.

Signed-off-by: Catalin Marinas 
Signed-off-by: Andrey Konovalov 
---
 arch/arm64/Kconfig   |  9 
 arch/arm64/include/asm/processor.h   |  8 
 arch/arm64/include/asm/thread_info.h |  1 +
 arch/arm64/include/asm/uaccess.h |  4 +-
 arch/arm64/kernel/process.c  | 72 
 include/uapi/linux/prctl.h   |  5 ++
 kernel/sys.c | 12 +
 7 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 697ea0510729..55fbaf20af2d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1107,6 +1107,15 @@ config ARM64_SW_TTBR0_PAN
  zeroed area and reserved ASID. The user access routines
  restore the valid TTBR0_EL1 temporarily.
 
+config ARM64_TAGGED_ADDR_ABI
+   bool "Enable the tagged user addresses syscall ABI"
+   default y
+   help
+ When this option is enabled, user applications can opt in to a
+ relaxed ABI via prctl() allowing tagged addresses to be passed
+ to system calls as pointer arguments. For details, see
+ Documentation/arm64/tagged-address-abi.txt.
+
 menuconfig COMPAT
bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT
diff --git a/arch/arm64/include/asm/processor.h 
b/arch/arm64/include/asm/processor.h
index fd5b1a4efc70..ee86070a28d4 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -296,6 +296,14 @@ extern void __init minsigstksz_setup(void);
 /* PR_PAC_RESET_KEYS prctl */
 #define PAC_RESET_KEYS(tsk, arg)   ptrauth_prctl_reset_keys(tsk, arg)
 
+#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
+/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */
+long set_tagged_addr_ctrl(unsigned long arg);
+long get_tagged_addr_ctrl(void);
+#define SET_TAGGED_ADDR_CTRL(arg)  set_tagged_addr_ctrl(arg)
+#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl()
+#endif
+
 /*
  * For CONFIG_GCC_PLUGIN_STACKLEAK
  *
diff --git a/arch/arm64/include/asm/thread_info.h 
b/arch/arm64/include/asm/thread_info.h
index 2372e97db29c..4f81c4f15404 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -88,6 +88,7 @@ void arch_release_task_struct(struct task_struct *tsk);
 #define TIF_SVE23  /* Scalable Vector Extension in 
use */
 #define TIF_SVE_VL_INHERIT 24  /* Inherit sve_vl_onexec across exec */
 #define TIF_SSBD   25  /* Wants SSB mitigation */
+#define TIF_TAGGED_ADDR26  /* Allow tagged user addresses 
*/
 
 #define _TIF_SIGPENDING(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED  (1 << TIF_NEED_RESCHED)
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index a138e3b4f717..097d6bfac0b7 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -62,7 +62,9 @@ static inline unsigned long __range_ok(const void __user 
*addr, unsigned long si
 {
unsigned long ret, limit = current_thread_info()->addr_limit;
 
-   addr = untagged_addr(addr);
+   if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) &&
+   test_thread_flag(TIF_TAGGED_ADDR))
+   addr = untagged_addr(addr);
 
__chk_user_ptr(addr);
asm volatile(
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 9856395ccdb7..60e70158a4a1 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -307,11 +308,18 @@ static void tls_thread_flush(void)
}
 }
 
+static void flush_tagged_addr_state(void)
+{
+   if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI))
+   clear_thread_flag(TIF_TAGGED_ADDR);
+}
+
 void flush_thread(void)
 {
fpsimd_flush_thread();
tls_thread_flush();
flush_ptrace_hw_breakpoint(current);
+   flush_tagged_addr_state();
 }
 
 void release_thread(struct task_struct *dead_task)
@@ -541,3 +549,67 @@ void arch_setup_new_exec(void)
 
ptrauth_thread_init_user(current);
 }
+
+#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
+/*
+ * Control the relaxed ABI allowing tagged user addresses into the kernel.
+