0143-x86-dumpstack-Add-get_stack_info-support-for-the-SYS.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. From 45b01b77bd3529e761bca6de0f0ed79549377479 Mon Sep 17 00:00:00 2001
  2. From: Andy Lutomirski <[email protected]>
  3. Date: Mon, 4 Dec 2017 15:07:13 +0100
  4. Subject: [PATCH 143/242] x86/dumpstack: Add get_stack_info() support for the
  5. SYSENTER stack
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. get_stack_info() doesn't currently know about the SYSENTER stack, so
  11. unwinding will fail if we entered the kernel on the SYSENTER stack
  12. and haven't fully switched off. Teach get_stack_info() about the
  13. SYSENTER stack.
  14. With future patches applied that run part of the entry code on the
  15. SYSENTER stack and introduce an intentional BUG(), I would get:
  16. PANIC: double fault, error_code: 0x0
  17. ...
  18. RIP: 0010:do_error_trap+0x33/0x1c0
  19. ...
  20. Call Trace:
  21. Code: ...
  22. With this patch, I get:
  23. PANIC: double fault, error_code: 0x0
  24. ...
  25. Call Trace:
  26. <SYSENTER>
  27. ? async_page_fault+0x36/0x60
  28. ? invalid_op+0x22/0x40
  29. ? async_page_fault+0x36/0x60
  30. ? sync_regs+0x3c/0x40
  31. ? sync_regs+0x2e/0x40
  32. ? error_entry+0x6c/0xd0
  33. ? async_page_fault+0x36/0x60
  34. </SYSENTER>
  35. Code: ...
  36. which is a lot more informative.
  37. Signed-off-by: Andy Lutomirski <[email protected]>
  38. Signed-off-by: Thomas Gleixner <[email protected]>
  39. Reviewed-by: Borislav Petkov <[email protected]>
  40. Cc: Boris Ostrovsky <[email protected]>
  41. Cc: Borislav Petkov <[email protected]>
  42. Cc: Borislav Petkov <[email protected]>
  43. Cc: Brian Gerst <[email protected]>
  44. Cc: Dave Hansen <[email protected]>
  45. Cc: Dave Hansen <[email protected]>
  46. Cc: David Laight <[email protected]>
  47. Cc: Denys Vlasenko <[email protected]>
  48. Cc: Eduardo Valentin <[email protected]>
  49. Cc: Greg KH <[email protected]>
  50. Cc: H. Peter Anvin <[email protected]>
  51. Cc: Josh Poimboeuf <[email protected]>
  52. Cc: Juergen Gross <[email protected]>
  53. Cc: Linus Torvalds <[email protected]>
  54. Cc: Peter Zijlstra <[email protected]>
  55. Cc: Rik van Riel <[email protected]>
  56. Cc: Will Deacon <[email protected]>
  57. Cc: [email protected]
  58. Cc: [email protected]
  59. Cc: [email protected]
  60. Cc: [email protected]
  61. Link: https://lkml.kernel.org/r/[email protected]
  62. Signed-off-by: Ingo Molnar <[email protected]>
  63. (cherry picked from commit 33a2f1a6c4d7c0a02d1c006fb0379cc5ca3b96bb)
  64. Signed-off-by: Andy Whitcroft <[email protected]>
  65. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  66. (cherry picked from commit 72e90cc5463cf882c5f9508817029d85b317f2b5)
  67. Signed-off-by: Fabian Grünbichler <[email protected]>
  68. ---
  69. arch/x86/include/asm/stacktrace.h | 3 +++
  70. arch/x86/kernel/dumpstack.c | 19 +++++++++++++++++++
  71. arch/x86/kernel/dumpstack_32.c | 6 ++++++
  72. arch/x86/kernel/dumpstack_64.c | 6 ++++++
  73. 4 files changed, 34 insertions(+)
  74. diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
  75. index 2e41c50ddf47..95f999576131 100644
  76. --- a/arch/x86/include/asm/stacktrace.h
  77. +++ b/arch/x86/include/asm/stacktrace.h
  78. @@ -15,6 +15,7 @@ enum stack_type {
  79. STACK_TYPE_TASK,
  80. STACK_TYPE_IRQ,
  81. STACK_TYPE_SOFTIRQ,
  82. + STACK_TYPE_SYSENTER,
  83. STACK_TYPE_EXCEPTION,
  84. STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
  85. };
  86. @@ -27,6 +28,8 @@ struct stack_info {
  87. bool in_task_stack(unsigned long *stack, struct task_struct *task,
  88. struct stack_info *info);
  89. +bool in_sysenter_stack(unsigned long *stack, struct stack_info *info);
  90. +
  91. int get_stack_info(unsigned long *stack, struct task_struct *task,
  92. struct stack_info *info, unsigned long *visit_mask);
  93. diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
  94. index 695cdce5dfc8..c211cbdff709 100644
  95. --- a/arch/x86/kernel/dumpstack.c
  96. +++ b/arch/x86/kernel/dumpstack.c
  97. @@ -43,6 +43,25 @@ bool in_task_stack(unsigned long *stack, struct task_struct *task,
  98. return true;
  99. }
  100. +bool in_sysenter_stack(unsigned long *stack, struct stack_info *info)
  101. +{
  102. + struct tss_struct *tss = this_cpu_ptr(&cpu_tss);
  103. +
  104. + /* Treat the canary as part of the stack for unwinding purposes. */
  105. + void *begin = &tss->SYSENTER_stack_canary;
  106. + void *end = (void *)&tss->SYSENTER_stack + sizeof(tss->SYSENTER_stack);
  107. +
  108. + if ((void *)stack < begin || (void *)stack >= end)
  109. + return false;
  110. +
  111. + info->type = STACK_TYPE_SYSENTER;
  112. + info->begin = begin;
  113. + info->end = end;
  114. + info->next_sp = NULL;
  115. +
  116. + return true;
  117. +}
  118. +
  119. static void printk_stack_address(unsigned long address, int reliable,
  120. char *log_lvl)
  121. {
  122. diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
  123. index e5f0b40e66d2..3160bf2d100e 100644
  124. --- a/arch/x86/kernel/dumpstack_32.c
  125. +++ b/arch/x86/kernel/dumpstack_32.c
  126. @@ -25,6 +25,9 @@ const char *stack_type_name(enum stack_type type)
  127. if (type == STACK_TYPE_SOFTIRQ)
  128. return "SOFTIRQ";
  129. + if (type == STACK_TYPE_SYSENTER)
  130. + return "SYSENTER";
  131. +
  132. return NULL;
  133. }
  134. @@ -92,6 +95,9 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
  135. if (task != current)
  136. goto unknown;
  137. + if (in_sysenter_stack(stack, info))
  138. + goto recursion_check;
  139. +
  140. if (in_hardirq_stack(stack, info))
  141. goto recursion_check;
  142. diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
  143. index 3e1471d57487..f5107b659f86 100644
  144. --- a/arch/x86/kernel/dumpstack_64.c
  145. +++ b/arch/x86/kernel/dumpstack_64.c
  146. @@ -36,6 +36,9 @@ const char *stack_type_name(enum stack_type type)
  147. if (type == STACK_TYPE_IRQ)
  148. return "IRQ";
  149. + if (type == STACK_TYPE_SYSENTER)
  150. + return "SYSENTER";
  151. +
  152. if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
  153. return exception_stack_names[type - STACK_TYPE_EXCEPTION];
  154. @@ -114,6 +117,9 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
  155. if (in_irq_stack(stack, info))
  156. goto recursion_check;
  157. + if (in_sysenter_stack(stack, info))
  158. + goto recursion_check;
  159. +
  160. goto unknown;
  161. recursion_check:
  162. --
  163. 2.14.2