Messages in this thread Patch in this message | | | From | Chris Metcalf <> | Subject | [PATCH v7 09/11] arch/arm64: enable task isolation functionality | Date | Mon, 28 Sep 2015 11:17:24 -0400 |
| |
We need to call task_isolation_enter() from prepare_exit_to_usermode(), so that we can both ensure we do it last before returning to userspace, and we also are able to re-run signal handling, etc., if something occurs while task_isolation_enter() has interrupts enabled. To do this we add _TIF_NOHZ to the _TIF_WORK_MASK if we have CONFIG_TASK_ISOLATION enabled, which brings us into prepare_exit_to_usermode() on all return to userspace. But we don't put _TIF_NOHZ in the flags that we use to loop back and recheck, since we don't need to loop back only because the flag is set. Instead we unconditionally call task_isolation_enter() at the end of the loop if any other work is done.
To make the assembly code continue to be as optimized as before, we renumber the _TIF flags so that both _TIF_WORK_MASK and _TIF_SYSCALL_WORK still have contiguous runs of bits in the immediate operand for the "and" instruction, as required by the ARM64 ISA. Since TIF_NOHZ is in both masks, it must be the middle bit in the contiguous run that starts with the _TIF_WORK_MASK bits and ends with the _TIF_SYSCALL_WORK bits.
We tweak syscall_trace_enter() slightly to carry the "flags" value from current_thread_info()->flags for each of the tests, rather than doing a volatile read from memory for each one. This avoids a small overhead for each test, and in particular avoids that overhead for TIF_NOHZ when TASK_ISOLATION is not enabled.
Also, we have to add an explicit check for STRICT mode in do_mem_abort() to handle the case of page faults, since arm64 does not use the exception_enter() mechanism.
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/arm64/include/asm/thread_info.h | 18 ++++++++++++------ arch/arm64/kernel/ptrace.c | 10 ++++++++-- arch/arm64/kernel/signal.c | 6 +++++- arch/arm64/mm/fault.c | 8 ++++++++ 4 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index dcd06d18a42a..4c36c4ee3528 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -101,11 +101,11 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NEED_RESCHED 1 #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */ -#define TIF_NOHZ 7 -#define TIF_SYSCALL_TRACE 8 -#define TIF_SYSCALL_AUDIT 9 -#define TIF_SYSCALL_TRACEPOINT 10 -#define TIF_SECCOMP 11 +#define TIF_NOHZ 4 +#define TIF_SYSCALL_TRACE 5 +#define TIF_SYSCALL_AUDIT 6 +#define TIF_SYSCALL_TRACEPOINT 7 +#define TIF_SECCOMP 8 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_FREEZE 19 #define TIF_RESTORE_SIGMASK 20 @@ -124,9 +124,15 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_32BIT (1 << TIF_32BIT) -#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ +#define _TIF_WORK_LOOP_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE) +#ifdef CONFIG_TASK_ISOLATION +# define _TIF_WORK_MASK (_TIF_WORK_LOOP_MASK | _TIF_NOHZ) +#else +# define _TIF_WORK_MASK _TIF_WORK_LOOP_MASK +#endif + #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ _TIF_NOHZ) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 1971f491bb90..9113789e9486 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -37,6 +37,7 @@ #include <linux/regset.h> #include <linux/tracehook.h> #include <linux/elf.h> +#include <linux/isolation.h> #include <asm/compat.h> #include <asm/debug-monitors.h> @@ -1240,14 +1241,19 @@ static void tracehook_report_syscall(struct pt_regs *regs, asmlinkage int syscall_trace_enter(struct pt_regs *regs) { + unsigned long work = ACCESS_ONCE(current_thread_info()->flags); + /* Do the secure computing check first; failures should be fast. */ if (secure_computing() == -1) return -1; - if (test_thread_flag(TIF_SYSCALL_TRACE)) + if ((work & _TIF_NOHZ) && task_isolation_strict()) + task_isolation_syscall(regs->syscallno); + + if (work & _TIF_SYSCALL_TRACE) tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); - if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + if (work & _TIF_SYSCALL_TRACEPOINT) trace_sys_enter(regs, regs->syscallno); audit_syscall_entry(regs->syscallno, regs->orig_x0, regs->regs[1], diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index fde59c1139a9..def9166eac9e 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -25,6 +25,7 @@ #include <linux/uaccess.h> #include <linux/tracehook.h> #include <linux/ratelimit.h> +#include <linux/isolation.h> #include <asm/debug-monitors.h> #include <asm/elf.h> @@ -419,10 +420,13 @@ asmlinkage void prepare_exit_to_usermode(struct pt_regs *regs, if (thread_flags & _TIF_FOREIGN_FPSTATE) fpsimd_restore_current_state(); + if (task_isolation_enabled()) + task_isolation_enter(); + local_irq_disable(); thread_flags = READ_ONCE(current_thread_info()->flags) & - _TIF_WORK_MASK; + _TIF_WORK_LOOP_MASK; } while (thread_flags); } diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index aba9ead1384c..01c9ae336887 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -29,6 +29,7 @@ #include <linux/sched.h> #include <linux/highmem.h> #include <linux/perf_event.h> +#include <linux/isolation.h> #include <asm/cpufeature.h> #include <asm/exception.h> @@ -465,6 +466,13 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, const struct fault_info *inf = fault_info + (esr & 63); struct siginfo info; + /* We don't use exception_enter(), so we check strict isolation here. */ + if (IS_ENABLED(CONFIG_TASK_ISOLATION) && + test_thread_flag(TIF_NOHZ) && + task_isolation_strict() && + user_mode(regs)) + task_isolation_exception(); + if (!inf->fn(addr, esr, regs)) return; -- 2.1.2
| |