linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/4] syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check
@ 2017-08-14 21:37 Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 2/4] Revert "arm/syscalls: Check address limit on user-mode return" Thomas Garnier
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Thomas Garnier @ 2017-08-14 21:37 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: linux-api, linux-kernel, linux-arm-kernel, kernel-hardening

Use CHECK_DATA_CORRUPTION instead of BUG_ON to provide more flexibility
on address limit failures. By default, send a SIGKILL signal to kill the
current process preventing exploitation of a bad address limit.

Make the TIF_FSCHECK flag optional so ARM can use this function.

Signed-off-by: Thomas Garnier <thgarnie@google.com>
---
 include/linux/syscalls.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 88951b795ee3..65e273aadada 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -219,21 +219,25 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
 	}								\
 	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
-#ifdef TIF_FSCHECK
 /*
  * Called before coming back to user-mode. Returning to user-mode with an
  * address limit different than USER_DS can allow to overwrite kernel memory.
  */
 static inline void addr_limit_user_check(void)
 {
-
+#ifdef TIF_FSCHECK
 	if (!test_thread_flag(TIF_FSCHECK))
 		return;
+#endif
 
-	BUG_ON(!segment_eq(get_fs(), USER_DS));
+	if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS),
+				  "Invalid address limit on user-mode return"))
+		force_sig(SIGKILL, current);
+
+#ifdef TIF_FSCHECK
 	clear_thread_flag(TIF_FSCHECK);
-}
 #endif
+}
 
 asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
 			       qid_t id, void __user *addr);
-- 
2.14.1.480.gb18f417b89-goog

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

* [PATCH v3 2/4] Revert "arm/syscalls: Check address limit on user-mode return"
  2017-08-14 21:37 [PATCH v3 1/4] syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check Thomas Garnier
@ 2017-08-14 21:37 ` Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 3/4] arm/syscalls: Optimize address limit check Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 4/4] arm64/syscalls: Move address limit check in loop Thomas Garnier
  2 siblings, 0 replies; 8+ messages in thread
From: Thomas Garnier @ 2017-08-14 21:37 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: linux-api, linux-kernel, linux-arm-kernel, kernel-hardening

This reverts commit 73ac5d6a2b6ac3ae8d1e1818f3e9946f97489bc9.

The work pending loop can call set_fs after addr_limit_user_check
removed the _TIF_FSCHECK flag. This may happen at anytime based on how
ARM handles alignment exceptions. It leads to an infinite loop condition.

After discussion, it has been agreed that the generic approach is not
tailored to the ARM architecture and any fix might not be complete. This
patch will be replaced by an architecture specific implementation. The
work flag approach will be kept for other architectures.

Reported-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Thomas Garnier <thgarnie@google.com>
---
 arch/arm/include/asm/thread_info.h | 15 ++++++---------
 arch/arm/include/asm/uaccess.h     |  2 --
 arch/arm/kernel/entry-common.S     |  9 ++-------
 arch/arm/kernel/signal.c           |  5 -----
 4 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 1d468b527b7b..776757d1604a 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -139,11 +139,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_NEED_RESCHED	1	/* rescheduling necessary */
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_UPROBE		3	/* breakpointed or singlestepping */
-#define TIF_FSCHECK		4	/* Check FS is USER_DS on return */
-#define TIF_SYSCALL_TRACE	5	/* syscall trace active */
-#define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
-#define TIF_SYSCALL_TRACEPOINT	7	/* syscall tracepoint instrumentation */
-#define TIF_SECCOMP		8	/* seccomp syscall filtering active */
+#define TIF_SYSCALL_TRACE	4	/* syscall trace active */
+#define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
+#define TIF_SYSCALL_TRACEPOINT	6	/* syscall tracepoint instrumentation */
+#define TIF_SECCOMP		7	/* seccomp syscall filtering active */
 
 #define TIF_NOHZ		12	/* in adaptive nohz mode */
 #define TIF_USING_IWMMXT	17
@@ -154,7 +153,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
-#define _TIF_FSCHECK		(1 << TIF_FSCHECK)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
@@ -168,9 +166,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 /*
  * Change these and you break ASM code in entry-common.S
  */
-#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING |	\
-				 _TIF_NOTIFY_RESUME | _TIF_UPROBE |	\
-				 _TIF_FSCHECK)
+#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+				 _TIF_NOTIFY_RESUME | _TIF_UPROBE)
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_ARM_THREAD_INFO_H */
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 87936dd5d151..0bf2347495f1 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -70,8 +70,6 @@ static inline void set_fs(mm_segment_t fs)
 {
 	current_thread_info()->addr_limit = fs;
 	modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
-	/* On user-mode return, check fs is correct */
-	set_thread_flag(TIF_FSCHECK);
 }
 
 #define segment_eq(a, b)	((a) == (b))
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index ca3614dc6938..0b60adf4a5d9 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -49,9 +49,7 @@ ret_fast_syscall:
  UNWIND(.cantunwind	)
 	disable_irq_notrace			@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
-	tst	r1, #_TIF_SYSCALL_WORK
-	bne	fast_work_pending
-	tst	r1, #_TIF_WORK_MASK
+	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
 	bne	fast_work_pending
 
 	/* perform architecture specific actions before user return */
@@ -77,15 +75,12 @@ ret_fast_syscall:
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
 	disable_irq_notrace			@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
-	tst	r1, #_TIF_SYSCALL_WORK
-	bne	fast_work_pending
-	tst	r1, #_TIF_WORK_MASK
+	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
 	beq	no_work_pending
  UNWIND(.fnend		)
 ENDPROC(ret_fast_syscall)
 
 	/* Slower path - fall through to work_pending */
-fast_work_pending:
 #endif
 
 	tst	r1, #_TIF_SYSCALL_WORK
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index e2de50bf8742..5814298ef0b7 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -14,7 +14,6 @@
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 #include <linux/uprobes.h>
-#include <linux/syscalls.h>
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
@@ -614,10 +613,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 	 * Update the trace code with the current status.
 	 */
 	trace_hardirqs_off();
-
-	/* Check valid user FS if needed */
-	addr_limit_user_check();
-
 	do {
 		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
 			schedule();
-- 
2.14.1.480.gb18f417b89-goog

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

* [PATCH v3 3/4] arm/syscalls: Optimize address limit check
  2017-08-14 21:37 [PATCH v3 1/4] syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 2/4] Revert "arm/syscalls: Check address limit on user-mode return" Thomas Garnier
@ 2017-08-14 21:37 ` Thomas Garnier
  2017-08-22 16:42   ` Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 4/4] arm64/syscalls: Move address limit check in loop Thomas Garnier
  2 siblings, 1 reply; 8+ messages in thread
From: Thomas Garnier @ 2017-08-14 21:37 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: linux-api, linux-kernel, linux-arm-kernel, kernel-hardening

Disable the generic address limit check in favor of an architecture
specific optimized implementation. The generic implementation using
pending work flags did not work well with ARM and alignment faults.

The address limit is checked on each syscall return path to user-mode
path as well as the irq user-mode return function. If the address limit
was changed, a function is called to report data corruption (stopping
the kernel or process based on configuration).

The address limit check has to be done before any pending work because
they can reset the address limit and the process is killed using a
SIGKILL signal. For example the lkdtm address limit check does not work
because the signal to kill the process will reset the user-mode address
limit.

Signed-off-by: Thomas Garnier <thgarnie@google.com>
---
 arch/arm/kernel/entry-common.S | 11 +++++++++++
 arch/arm/kernel/signal.c       |  7 +++++++
 2 files changed, 18 insertions(+)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 0b60adf4a5d9..99c908226065 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -12,6 +12,7 @@
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
 #include <asm/unwind.h>
+#include <asm/memory.h>
 #ifdef CONFIG_AEABI
 #include <asm/unistd-oabi.h>
 #endif
@@ -48,10 +49,14 @@ ret_fast_syscall:
  UNWIND(.fnstart	)
  UNWIND(.cantunwind	)
 	disable_irq_notrace			@ disable interrupts
+	ldr	r2, [tsk, #TI_ADDR_LIMIT]
+	cmp	r2, #TASK_SIZE
+	blne	addr_limit_check_failed
 	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
 	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
 	bne	fast_work_pending
 
+
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr
 
@@ -74,6 +79,9 @@ ret_fast_syscall:
  UNWIND(.cantunwind	)
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
 	disable_irq_notrace			@ disable interrupts
+	ldr	r2, [tsk, #TI_ADDR_LIMIT]
+	cmp	r2, #TASK_SIZE
+	blne	addr_limit_check_failed
 	ldr	r1, [tsk, #TI_FLAGS]		@ re-check for syscall tracing
 	tst	r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
 	beq	no_work_pending
@@ -106,6 +114,9 @@ ENTRY(ret_to_user)
 ret_slow_syscall:
 	disable_irq_notrace			@ disable interrupts
 ENTRY(ret_to_user_from_irq)
+	ldr	r2, [tsk, #TI_ADDR_LIMIT]
+	cmp	r2, #TASK_SIZE
+	blne	addr_limit_check_failed
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
 	bne	slow_work_pending
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 5814298ef0b7..b67ae12503f3 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -14,6 +14,7 @@
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 #include <linux/uprobes.h>
+#include <linux/syscalls.h>
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
@@ -673,3 +674,9 @@ struct page *get_signal_page(void)
 
 	return page;
 }
+
+/* Defer to generic check */
+asmlinkage void addr_limit_check_failed(void)
+{
+	addr_limit_user_check();
+}
-- 
2.14.1.480.gb18f417b89-goog

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

* [PATCH v3 4/4] arm64/syscalls: Move address limit check in loop
  2017-08-14 21:37 [PATCH v3 1/4] syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 2/4] Revert "arm/syscalls: Check address limit on user-mode return" Thomas Garnier
  2017-08-14 21:37 ` [PATCH v3 3/4] arm/syscalls: Optimize address limit check Thomas Garnier
@ 2017-08-14 21:37 ` Thomas Garnier
  2 siblings, 0 replies; 8+ messages in thread
From: Thomas Garnier @ 2017-08-14 21:37 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: linux-api, linux-kernel, linux-arm-kernel, kernel-hardening

A bug was reported on ARM where set_fs might be called after it was
checked on the work pending function. ARM64 is not affected by this bug
but has a similar construct. In order to avoid any similar problems in
the future, the addr_limit_user_check function is moved at the beginning
of the loop.

Fixes: cf7de27ab351 ("arm64/syscalls: Check address limit on user-mode return")
Reported-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Thomas Garnier <thgarnie@google.com>
---
 arch/arm64/kernel/signal.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index c45214f8fb54..0bdc96c61bc0 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -751,10 +751,10 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
 	 */
 	trace_hardirqs_off();
 
-	/* Check valid user FS if needed */
-	addr_limit_user_check();
-
 	do {
+		/* Check valid user FS if needed */
+		addr_limit_user_check();
+
 		if (thread_flags & _TIF_NEED_RESCHED) {
 			schedule();
 		} else {
-- 
2.14.1.480.gb18f417b89-goog

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

* Re: [PATCH v3 3/4] arm/syscalls: Optimize address limit check
  2017-08-14 21:37 ` [PATCH v3 3/4] arm/syscalls: Optimize address limit check Thomas Garnier
@ 2017-08-22 16:42   ` Thomas Garnier
       [not found]     ` <CAJcbSZG1b7ObJAv6Kmp-fR3vZRg7AdbcgqDceGB95r-72Yv0yg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Garnier @ 2017-08-22 16:42 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: Linux API, LKML, linux-arm-kernel, Kernel Hardening

On Mon, Aug 14, 2017 at 2:37 PM, Thomas Garnier <thgarnie@google.com> wrote:
> Disable the generic address limit check in favor of an architecture
> specific optimized implementation. The generic implementation using
> pending work flags did not work well with ARM and alignment faults.
>
> The address limit is checked on each syscall return path to user-mode
> path as well as the irq user-mode return function. If the address limit
> was changed, a function is called to report data corruption (stopping
> the kernel or process based on configuration).
>
> The address limit check has to be done before any pending work because
> they can reset the address limit and the process is killed using a
> SIGKILL signal. For example the lkdtm address limit check does not work
> because the signal to kill the process will reset the user-mode address
> limit.
>
> Signed-off-by: Thomas Garnier <thgarnie@google.com>

Any feedback?

> ---
>  arch/arm/kernel/entry-common.S | 11 +++++++++++
>  arch/arm/kernel/signal.c       |  7 +++++++
>  2 files changed, 18 insertions(+)
>
> diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
> index 0b60adf4a5d9..99c908226065 100644
> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S
> @@ -12,6 +12,7 @@
>  #include <asm/unistd.h>
>  #include <asm/ftrace.h>
>  #include <asm/unwind.h>
> +#include <asm/memory.h>
>  #ifdef CONFIG_AEABI
>  #include <asm/unistd-oabi.h>
>  #endif
> @@ -48,10 +49,14 @@ ret_fast_syscall:
>   UNWIND(.fnstart       )
>   UNWIND(.cantunwind    )
>         disable_irq_notrace                     @ disable interrupts
> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
> +       cmp     r2, #TASK_SIZE
> +       blne    addr_limit_check_failed
>         ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
>         tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
>         bne     fast_work_pending
>
> +
>         /* perform architecture specific actions before user return */
>         arch_ret_to_user r1, lr
>
> @@ -74,6 +79,9 @@ ret_fast_syscall:
>   UNWIND(.cantunwind    )
>         str     r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
>         disable_irq_notrace                     @ disable interrupts
> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
> +       cmp     r2, #TASK_SIZE
> +       blne    addr_limit_check_failed
>         ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
>         tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
>         beq     no_work_pending
> @@ -106,6 +114,9 @@ ENTRY(ret_to_user)
>  ret_slow_syscall:
>         disable_irq_notrace                     @ disable interrupts
>  ENTRY(ret_to_user_from_irq)
> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
> +       cmp     r2, #TASK_SIZE
> +       blne    addr_limit_check_failed
>         ldr     r1, [tsk, #TI_FLAGS]
>         tst     r1, #_TIF_WORK_MASK
>         bne     slow_work_pending
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 5814298ef0b7..b67ae12503f3 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -14,6 +14,7 @@
>  #include <linux/uaccess.h>
>  #include <linux/tracehook.h>
>  #include <linux/uprobes.h>
> +#include <linux/syscalls.h>
>
>  #include <asm/elf.h>
>  #include <asm/cacheflush.h>
> @@ -673,3 +674,9 @@ struct page *get_signal_page(void)
>
>         return page;
>  }
> +
> +/* Defer to generic check */
> +asmlinkage void addr_limit_check_failed(void)
> +{
> +       addr_limit_user_check();
> +}
> --
> 2.14.1.480.gb18f417b89-goog
>



-- 
Thomas

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

* Re: [PATCH v3 3/4] arm/syscalls: Optimize address limit check
       [not found]     ` <CAJcbSZG1b7ObJAv6Kmp-fR3vZRg7AdbcgqDceGB95r-72Yv0yg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-08-29 14:32       ` Thomas Garnier
       [not found]         ` <CAJcbSZEd10fMp6OSgSYv_Wmt=wX5fw_Gu-_N=fM_QmP==wUMew-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Garnier @ 2017-08-29 14:32 UTC (permalink / raw)
  To: Al Viro, Dave Hansen, Arnd Bergmann, Thomas Gleixner,
	Thomas Garnier, Yonghong Song, David Howells, Russell King,
	Kees Cook, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon
  Cc: Linux API, LKML, Linux ARM, Kernel Hardening, Lothar Waßmann

On Tue, Aug 22, 2017 at 9:42 AM, Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
> On Mon, Aug 14, 2017 at 2:37 PM, Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
>> Disable the generic address limit check in favor of an architecture
>> specific optimized implementation. The generic implementation using
>> pending work flags did not work well with ARM and alignment faults.
>>
>> The address limit is checked on each syscall return path to user-mode
>> path as well as the irq user-mode return function. If the address limit
>> was changed, a function is called to report data corruption (stopping
>> the kernel or process based on configuration).
>>
>> The address limit check has to be done before any pending work because
>> they can reset the address limit and the process is killed using a
>> SIGKILL signal. For example the lkdtm address limit check does not work
>> because the signal to kill the process will reset the user-mode address
>> limit.
>>
>> Signed-off-by: Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>
> Any feedback?

CCing LW-AvR2QvxeiV7DiMYJYoSAnRvVK+yQ3ZXh@public.gmane.org who experienced the same issue this patch
proposal fix.

Russel: Any feedback?

>
>> ---
>>  arch/arm/kernel/entry-common.S | 11 +++++++++++
>>  arch/arm/kernel/signal.c       |  7 +++++++
>>  2 files changed, 18 insertions(+)
>>
>> diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
>> index 0b60adf4a5d9..99c908226065 100644
>> --- a/arch/arm/kernel/entry-common.S
>> +++ b/arch/arm/kernel/entry-common.S
>> @@ -12,6 +12,7 @@
>>  #include <asm/unistd.h>
>>  #include <asm/ftrace.h>
>>  #include <asm/unwind.h>
>> +#include <asm/memory.h>
>>  #ifdef CONFIG_AEABI
>>  #include <asm/unistd-oabi.h>
>>  #endif
>> @@ -48,10 +49,14 @@ ret_fast_syscall:
>>   UNWIND(.fnstart       )
>>   UNWIND(.cantunwind    )
>>         disable_irq_notrace                     @ disable interrupts
>> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
>> +       cmp     r2, #TASK_SIZE
>> +       blne    addr_limit_check_failed
>>         ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
>>         tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
>>         bne     fast_work_pending
>>
>> +
>>         /* perform architecture specific actions before user return */
>>         arch_ret_to_user r1, lr
>>
>> @@ -74,6 +79,9 @@ ret_fast_syscall:
>>   UNWIND(.cantunwind    )
>>         str     r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
>>         disable_irq_notrace                     @ disable interrupts
>> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
>> +       cmp     r2, #TASK_SIZE
>> +       blne    addr_limit_check_failed
>>         ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
>>         tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
>>         beq     no_work_pending
>> @@ -106,6 +114,9 @@ ENTRY(ret_to_user)
>>  ret_slow_syscall:
>>         disable_irq_notrace                     @ disable interrupts
>>  ENTRY(ret_to_user_from_irq)
>> +       ldr     r2, [tsk, #TI_ADDR_LIMIT]
>> +       cmp     r2, #TASK_SIZE
>> +       blne    addr_limit_check_failed
>>         ldr     r1, [tsk, #TI_FLAGS]
>>         tst     r1, #_TIF_WORK_MASK
>>         bne     slow_work_pending
>> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
>> index 5814298ef0b7..b67ae12503f3 100644
>> --- a/arch/arm/kernel/signal.c
>> +++ b/arch/arm/kernel/signal.c
>> @@ -14,6 +14,7 @@
>>  #include <linux/uaccess.h>
>>  #include <linux/tracehook.h>
>>  #include <linux/uprobes.h>
>> +#include <linux/syscalls.h>
>>
>>  #include <asm/elf.h>
>>  #include <asm/cacheflush.h>
>> @@ -673,3 +674,9 @@ struct page *get_signal_page(void)
>>
>>         return page;
>>  }
>> +
>> +/* Defer to generic check */
>> +asmlinkage void addr_limit_check_failed(void)
>> +{
>> +       addr_limit_user_check();
>> +}
>> --
>> 2.14.1.480.gb18f417b89-goog
>>
>
>
>
> --
> Thomas



-- 
Thomas

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

* Re: [PATCH v3 3/4] arm/syscalls: Optimize address limit check
       [not found]         ` <CAJcbSZEd10fMp6OSgSYv_Wmt=wX5fw_Gu-_N=fM_QmP==wUMew-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-08-29 19:54           ` Kees Cook
  2017-09-05 10:46             ` Leonard Crestez
  0 siblings, 1 reply; 8+ messages in thread
From: Kees Cook @ 2017-08-29 19:54 UTC (permalink / raw)
  To: Thomas Gleixner, Thomas Garnier, Russell King
  Cc: Al Viro, Dave Hansen, Arnd Bergmann, Yonghong Song,
	David Howells, Andy Lutomirski, Will Drewry, Dave Martin,
	Catalin Marinas, Will Deacon, Linux API, LKML, Linux ARM,
	Kernel Hardening, Lothar Waßmann

On Tue, Aug 29, 2017 at 7:32 AM, Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
> On Tue, Aug 22, 2017 at 9:42 AM, Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
>> On Mon, Aug 14, 2017 at 2:37 PM, Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
>>> Disable the generic address limit check in favor of an architecture
>>> specific optimized implementation. The generic implementation using
>>> pending work flags did not work well with ARM and alignment faults.
>>>
>>> The address limit is checked on each syscall return path to user-mode
>>> path as well as the irq user-mode return function. If the address limit
>>> was changed, a function is called to report data corruption (stopping
>>> the kernel or process based on configuration).
>>>
>>> The address limit check has to be done before any pending work because
>>> they can reset the address limit and the process is killed using a
>>> SIGKILL signal. For example the lkdtm address limit check does not work
>>> because the signal to kill the process will reset the user-mode address
>>> limit.
>>>
>>> Signed-off-by: Thomas Garnier <thgarnie-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>>
>> Any feedback?
>
> CCing LW-AvR2QvxeiV7DiMYJYoSAnRvVK+yQ3ZXh@public.gmane.org who experienced the same issue this patch
> proposal fix.
>
> Russell: Any feedback?

These implement Russell's suggestion. An Ack here would be nice. :) I
can't throw these into the ARM patch tracker because they depend on
stuff in -next (and the commit that needs to be reverted is in tglx's
tree).

Regardless, these all test out correctly for me, so:

Reviewed-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Tested-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

In a perfect world, these 4 patches should go together with the other
address limit check patches in tglx's tree. Thomas (Gleixner), can you
update your tree for the merge window? At the very least, we need to
revert 73ac5d6a2b6ac ("arm/syscalls: Check address limit on user-mode
return"), which has caused infinite loops in some cases. Better to
take all 4 patches in this series, though.

Thanks!

-Kees

-- 
Kees Cook
Pixel Security

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

* Re: [PATCH v3 3/4] arm/syscalls: Optimize address limit check
  2017-08-29 19:54           ` Kees Cook
@ 2017-09-05 10:46             ` Leonard Crestez
  0 siblings, 0 replies; 8+ messages in thread
From: Leonard Crestez @ 2017-09-05 10:46 UTC (permalink / raw)
  To: Kees Cook, Thomas Gleixner, Thomas Garnier, Russell King, Ingo Molnar
  Cc: Will Drewry, Arnd Bergmann, Kernel Hardening, Catalin Marinas,
	Will Deacon, LKML, Andy Lutomirski, David Howells, Dave Hansen,
	Al Viro, Linux API, Yonghong Song, Dave Martin, Linux ARM,
	Lothar Waßmann

On Tue, 2017-08-29 at 12:54 -0700, Kees Cook wrote:
> On Tue, Aug 29, 2017 at 7:32 AM, Thomas Garnier <thgarnie@google.com> wrote:
> > On Tue, Aug 22, 2017 at 9:42 AM, Thomas Garnier <thgarnie@google.com> wrote:
> > > On Mon, Aug 14, 2017 at 2:37 PM, Thomas Garnier <thgarnie@google.com> wrote:
> > > > 
> > > > Disable the generic address limit check in favor of an architecture
> > > > specific optimized implementation. The generic implementation using
> > > > pending work flags did not work well with ARM and alignment faults.
> > > > 
> > > > The address limit is checked on each syscall return path to user-mode
> > > > path as well as the irq user-mode return function. If the address limit
> > > > was changed, a function is called to report data corruption (stopping
> > > > the kernel or process based on configuration).
> > > > 
> > > > The address limit check has to be done before any pending work because
> > > > they can reset the address limit and the process is killed using a
> > > > SIGKILL signal. For example the lkdtm address limit check does not work
> > > > because the signal to kill the process will reset the user-mode address
> > > > limit.
> > > > 
> > > > Signed-off-by: Thomas Garnier <thgarnie@google.com>

> > > Any feedback?

> > CCing LW@karo-electronics.de who experienced the same issue this patch
> > proposal fix.
> > 
> > Russell: Any feedback?

> These implement Russell's suggestion. An Ack here would be nice. :) I
> can't throw these into the ARM patch tracker because they depend on
> stuff in -next (and the commit that needs to be reverted is in tglx's
> tree).
> 
> Regardless, these all test out correctly for me, so:
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Tested-by: Kees Cook <keescook@chromium.org>
> 
> In a perfect world, these 4 patches should go together with the other
> address limit check patches in tglx's tree. Thomas (Gleixner), can you
> update your tree for the merge window? At the very least, we need to
> revert 73ac5d6a2b6ac ("arm/syscalls: Check address limit on user-mode
> return"), which has caused infinite loops in some cases. Better to
> take all 4 patches in this series, though.

I also reported this infinite loop issue, several weeks ago:

https://lkml.org/lkml/2017/7/18/702

It seems that no fix was committed since then and the buggy patch made
it's way into Linus's tree after the 4.13 release.

Perhaps when there is long debate about the "proper" fix the original
patch should be reverted first, separately? In this particular case the
series fixing the bug actually includes the revert.

Anyway, I check that this v3 works on my board which was reproducing
the issue while booting from nfs (imx6sl-evk). The most likely reason
it's easy to reproduce here is a network driver issue where headers are
not correctly aligned to 4. This causes lots of alignment faults.

Tested-by: Leonard Crestez <leonard.crestez@nxp.com>

--
Regards,
Leonard

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

end of thread, other threads:[~2017-09-05 10:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-14 21:37 [PATCH v3 1/4] syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check Thomas Garnier
2017-08-14 21:37 ` [PATCH v3 2/4] Revert "arm/syscalls: Check address limit on user-mode return" Thomas Garnier
2017-08-14 21:37 ` [PATCH v3 3/4] arm/syscalls: Optimize address limit check Thomas Garnier
2017-08-22 16:42   ` Thomas Garnier
     [not found]     ` <CAJcbSZG1b7ObJAv6Kmp-fR3vZRg7AdbcgqDceGB95r-72Yv0yg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-29 14:32       ` Thomas Garnier
     [not found]         ` <CAJcbSZEd10fMp6OSgSYv_Wmt=wX5fw_Gu-_N=fM_QmP==wUMew-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-29 19:54           ` Kees Cook
2017-09-05 10:46             ` Leonard Crestez
2017-08-14 21:37 ` [PATCH v3 4/4] arm64/syscalls: Move address limit check in loop Thomas Garnier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).