0278-x86-mm-Only-set-IBPB-when-the-new-thread-cannot-ptra.patch 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Tim Chen <[email protected]>
  3. Date: Tue, 7 Nov 2017 13:52:42 -0800
  4. Subject: [PATCH] x86/mm: Only set IBPB when the new thread cannot ptrace
  5. current thread
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5753
  10. CVE-2017-5715
  11. To reduce overhead of setting IBPB, we only do that when
  12. the new thread cannot ptrace the current one. If the new
  13. thread has ptrace capability on current thread, it is safe.
  14. Signed-off-by: Tim Chen <[email protected]>
  15. Signed-off-by: Andy Whitcroft <[email protected]>
  16. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  17. (cherry picked from commit 65941af723059ffeeca269b99ab51b3c9e320751)
  18. Signed-off-by: Fabian Grünbichler <[email protected]>
  19. ---
  20. include/linux/ptrace.h | 6 ++++++
  21. arch/x86/mm/tlb.c | 5 ++++-
  22. kernel/ptrace.c | 18 ++++++++++++++----
  23. 3 files changed, 24 insertions(+), 5 deletions(-)
  24. diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
  25. index 0e5fcc11b1b8..d6afefd5465b 100644
  26. --- a/include/linux/ptrace.h
  27. +++ b/include/linux/ptrace.h
  28. @@ -63,12 +63,15 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
  29. #define PTRACE_MODE_NOAUDIT 0x04
  30. #define PTRACE_MODE_FSCREDS 0x08
  31. #define PTRACE_MODE_REALCREDS 0x10
  32. +#define PTRACE_MODE_NOACCESS_CHK 0x20
  33. /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
  34. #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
  35. #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
  36. #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
  37. #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
  38. +#define PTRACE_MODE_IBPB (PTRACE_MODE_ATTACH | PTRACE_MODE_NOAUDIT \
  39. + | PTRACE_MODE_NOACCESS_CHK | PTRACE_MODE_REALCREDS)
  40. /**
  41. * ptrace_may_access - check whether the caller is permitted to access
  42. @@ -86,6 +89,9 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
  43. */
  44. extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
  45. +extern int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
  46. + unsigned int mode);
  47. +
  48. static inline int ptrace_reparented(struct task_struct *child)
  49. {
  50. return !same_thread_group(child->real_parent, child->parent);
  51. diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
  52. index bb3ded3a4e5f..301e6efbc514 100644
  53. --- a/arch/x86/mm/tlb.c
  54. +++ b/arch/x86/mm/tlb.c
  55. @@ -6,6 +6,7 @@
  56. #include <linux/interrupt.h>
  57. #include <linux/export.h>
  58. #include <linux/cpu.h>
  59. +#include <linux/ptrace.h>
  60. #include <asm/tlbflush.h>
  61. #include <asm/mmu_context.h>
  62. @@ -219,7 +220,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
  63. u16 new_asid;
  64. bool need_flush;
  65. - if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
  66. + /* Null tsk means switching to kernel, so that's safe */
  67. + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && tsk &&
  68. + ___ptrace_may_access(tsk, current, PTRACE_MODE_IBPB))
  69. native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB);
  70. if (IS_ENABLED(CONFIG_VMAP_STACK)) {
  71. diff --git a/kernel/ptrace.c b/kernel/ptrace.c
  72. index 60f356d91060..f2f0f1aeabaf 100644
  73. --- a/kernel/ptrace.c
  74. +++ b/kernel/ptrace.c
  75. @@ -268,9 +268,10 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
  76. }
  77. /* Returns 0 on success, -errno on denial. */
  78. -static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
  79. +int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
  80. + unsigned int mode)
  81. {
  82. - const struct cred *cred = current_cred(), *tcred;
  83. + const struct cred *cred = __task_cred(cur), *tcred;
  84. struct mm_struct *mm;
  85. kuid_t caller_uid;
  86. kgid_t caller_gid;
  87. @@ -290,7 +291,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
  88. */
  89. /* Don't let security modules deny introspection */
  90. - if (same_thread_group(task, current))
  91. + if (same_thread_group(task, cur))
  92. return 0;
  93. rcu_read_lock();
  94. if (mode & PTRACE_MODE_FSCREDS) {
  95. @@ -328,7 +329,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
  96. !ptrace_has_cap(mm->user_ns, mode)))
  97. return -EPERM;
  98. - return security_ptrace_access_check(task, mode);
  99. + if (!(mode & PTRACE_MODE_NOACCESS_CHK))
  100. + return security_ptrace_access_check(task, mode);
  101. +
  102. + return 0;
  103. +}
  104. +EXPORT_SYMBOL_GPL(___ptrace_may_access);
  105. +
  106. +static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
  107. +{
  108. + return ___ptrace_may_access(current, task, mode);
  109. }
  110. bool ptrace_may_access(struct task_struct *task, unsigned int mode)
  111. --
  112. 2.14.2