| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
- From: Tim Chen <[email protected]>
- Date: Tue, 7 Nov 2017 13:52:42 -0800
- Subject: [PATCH] x86/mm: Only set IBPB when the new thread cannot ptrace
- current thread
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- CVE-2017-5753
- CVE-2017-5715
- To reduce overhead of setting IBPB, we only do that when
- the new thread cannot ptrace the current one. If the new
- thread has ptrace capability on current thread, it is safe.
- Signed-off-by: Tim Chen <[email protected]>
- Signed-off-by: Andy Whitcroft <[email protected]>
- Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
- (cherry picked from commit 65941af723059ffeeca269b99ab51b3c9e320751)
- Signed-off-by: Fabian Grünbichler <[email protected]>
- ---
- include/linux/ptrace.h | 6 ++++++
- arch/x86/mm/tlb.c | 5 ++++-
- kernel/ptrace.c | 18 ++++++++++++++----
- 3 files changed, 24 insertions(+), 5 deletions(-)
- diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
- index 0e5fcc11b1b8..d6afefd5465b 100644
- --- a/include/linux/ptrace.h
- +++ b/include/linux/ptrace.h
- @@ -63,12 +63,15 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
- #define PTRACE_MODE_NOAUDIT 0x04
- #define PTRACE_MODE_FSCREDS 0x08
- #define PTRACE_MODE_REALCREDS 0x10
- +#define PTRACE_MODE_NOACCESS_CHK 0x20
-
- /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
- #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
- #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
- #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
- #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
- +#define PTRACE_MODE_IBPB (PTRACE_MODE_ATTACH | PTRACE_MODE_NOAUDIT \
- + | PTRACE_MODE_NOACCESS_CHK | PTRACE_MODE_REALCREDS)
-
- /**
- * ptrace_may_access - check whether the caller is permitted to access
- @@ -86,6 +89,9 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
- */
- extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
-
- +extern int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
- + unsigned int mode);
- +
- static inline int ptrace_reparented(struct task_struct *child)
- {
- return !same_thread_group(child->real_parent, child->parent);
- diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
- index bb3ded3a4e5f..301e6efbc514 100644
- --- a/arch/x86/mm/tlb.c
- +++ b/arch/x86/mm/tlb.c
- @@ -6,6 +6,7 @@
- #include <linux/interrupt.h>
- #include <linux/export.h>
- #include <linux/cpu.h>
- +#include <linux/ptrace.h>
-
- #include <asm/tlbflush.h>
- #include <asm/mmu_context.h>
- @@ -219,7 +220,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
- u16 new_asid;
- bool need_flush;
-
- - if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
- + /* Null tsk means switching to kernel, so that's safe */
- + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && tsk &&
- + ___ptrace_may_access(tsk, current, PTRACE_MODE_IBPB))
- native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB);
-
- if (IS_ENABLED(CONFIG_VMAP_STACK)) {
- diff --git a/kernel/ptrace.c b/kernel/ptrace.c
- index 60f356d91060..f2f0f1aeabaf 100644
- --- a/kernel/ptrace.c
- +++ b/kernel/ptrace.c
- @@ -268,9 +268,10 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
- }
-
- /* Returns 0 on success, -errno on denial. */
- -static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
- +int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
- + unsigned int mode)
- {
- - const struct cred *cred = current_cred(), *tcred;
- + const struct cred *cred = __task_cred(cur), *tcred;
- struct mm_struct *mm;
- kuid_t caller_uid;
- kgid_t caller_gid;
- @@ -290,7 +291,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
- */
-
- /* Don't let security modules deny introspection */
- - if (same_thread_group(task, current))
- + if (same_thread_group(task, cur))
- return 0;
- rcu_read_lock();
- if (mode & PTRACE_MODE_FSCREDS) {
- @@ -328,7 +329,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
- !ptrace_has_cap(mm->user_ns, mode)))
- return -EPERM;
-
- - return security_ptrace_access_check(task, mode);
- + if (!(mode & PTRACE_MODE_NOACCESS_CHK))
- + return security_ptrace_access_check(task, mode);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL_GPL(___ptrace_may_access);
- +
- +static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
- +{
- + return ___ptrace_may_access(current, task, mode);
- }
-
- bool ptrace_may_access(struct task_struct *task, unsigned int mode)
- --
- 2.14.2
|