exception-tables.rst 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. .. SPDX-License-Identifier: GPL-2.0
  2. ===============================
  3. Kernel level exception handling
  4. ===============================
  5. Commentary by Joerg Pommnitz <[email protected]>
  6. When a process runs in kernel mode, it often has to access user
  7. mode memory whose address has been passed by an untrusted program.
  8. To protect itself the kernel has to verify this address.
  9. In older versions of Linux this was done with the
  10. int verify_area(int type, const void * addr, unsigned long size)
  11. function (which has since been replaced by access_ok()).
  12. This function verified that the memory area starting at address
  13. 'addr' and of size 'size' was accessible for the operation specified
  14. in type (read or write). To do this, verify_read had to look up the
  15. virtual memory area (vma) that contained the address addr. In the
  16. normal case (correctly working program), this test was successful.
  17. It only failed for a few buggy programs. In some kernel profiling
  18. tests, this normally unneeded verification used up a considerable
  19. amount of time.
  20. To overcome this situation, Linus decided to let the virtual memory
  21. hardware present in every Linux-capable CPU handle this test.
  22. How does this work?
  23. Whenever the kernel tries to access an address that is currently not
  24. accessible, the CPU generates a page fault exception and calls the
  25. page fault handler::
  26. void exc_page_fault(struct pt_regs *regs, unsigned long error_code)
  27. in arch/x86/mm/fault.c. The parameters on the stack are set up by
  28. the low level assembly glue in arch/x86/entry/entry_32.S. The parameter
  29. regs is a pointer to the saved registers on the stack, error_code
  30. contains a reason code for the exception.
  31. exc_page_fault() first obtains the inaccessible address from the CPU
  32. control register CR2. If the address is within the virtual address
  33. space of the process, the fault probably occurred, because the page
  34. was not swapped in, write protected or something similar. However,
  35. we are interested in the other case: the address is not valid, there
  36. is no vma that contains this address. In this case, the kernel jumps
  37. to the bad_area label.
  38. There it uses the address of the instruction that caused the exception
  39. (i.e. regs->eip) to find an address where the execution can continue
  40. (fixup). If this search is successful, the fault handler modifies the
  41. return address (again regs->eip) and returns. The execution will
  42. continue at the address in fixup.
  43. Where does fixup point to?
  44. Since we jump to the contents of fixup, fixup obviously points
  45. to executable code. This code is hidden inside the user access macros.
  46. I have picked the get_user() macro defined in arch/x86/include/asm/uaccess.h
  47. as an example. The definition is somewhat hard to follow, so let's peek at
  48. the code generated by the preprocessor and the compiler. I selected
  49. the get_user() call in drivers/char/sysrq.c for a detailed examination.
  50. The original code in sysrq.c line 587::
  51. get_user(c, buf);
  52. The preprocessor output (edited to become somewhat readable)::
  53. (
  54. {
  55. long __gu_err = - 14 , __gu_val = 0;
  56. const __typeof__(*( ( buf ) )) *__gu_addr = ((buf));
  57. if (((((0 + current_set[0])->tss.segment) == 0x18 ) ||
  58. (((sizeof(*(buf))) <= 0xC0000000UL) &&
  59. ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
  60. do {
  61. __gu_err = 0;
  62. switch ((sizeof(*(buf)))) {
  63. case 1:
  64. __asm__ __volatile__(
  65. "1: mov" "b" " %2,%" "b" "1\n"
  66. "2:\n"
  67. ".section .fixup,\"ax\"\n"
  68. "3: movl %3,%0\n"
  69. " xor" "b" " %" "b" "1,%" "b" "1\n"
  70. " jmp 2b\n"
  71. ".section __ex_table,\"a\"\n"
  72. " .align 4\n"
  73. " .long 1b,3b\n"
  74. ".text" : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
  75. ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ;
  76. break;
  77. case 2:
  78. __asm__ __volatile__(
  79. "1: mov" "w" " %2,%" "w" "1\n"
  80. "2:\n"
  81. ".section .fixup,\"ax\"\n"
  82. "3: movl %3,%0\n"
  83. " xor" "w" " %" "w" "1,%" "w" "1\n"
  84. " jmp 2b\n"
  85. ".section __ex_table,\"a\"\n"
  86. " .align 4\n"
  87. " .long 1b,3b\n"
  88. ".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
  89. ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err ));
  90. break;
  91. case 4:
  92. __asm__ __volatile__(
  93. "1: mov" "l" " %2,%" "" "1\n"
  94. "2:\n"
  95. ".section .fixup,\"ax\"\n"
  96. "3: movl %3,%0\n"
  97. " xor" "l" " %" "" "1,%" "" "1\n"
  98. " jmp 2b\n"
  99. ".section __ex_table,\"a\"\n"
  100. " .align 4\n" " .long 1b,3b\n"
  101. ".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
  102. ( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err));
  103. break;
  104. default:
  105. (__gu_val) = __get_user_bad();
  106. }
  107. } while (0) ;
  108. ((c)) = (__typeof__(*((buf))))__gu_val;
  109. __gu_err;
  110. }
  111. );
  112. WOW! Black GCC/assembly magic. This is impossible to follow, so let's
  113. see what code gcc generates::
  114. > xorl %edx,%edx
  115. > movl current_set,%eax
  116. > cmpl $24,788(%eax)
  117. > je .L1424
  118. > cmpl $-1073741825,64(%esp)
  119. > ja .L1423
  120. > .L1424:
  121. > movl %edx,%eax
  122. > movl 64(%esp),%ebx
  123. > #APP
  124. > 1: movb (%ebx),%dl /* this is the actual user access */
  125. > 2:
  126. > .section .fixup,"ax"
  127. > 3: movl $-14,%eax
  128. > xorb %dl,%dl
  129. > jmp 2b
  130. > .section __ex_table,"a"
  131. > .align 4
  132. > .long 1b,3b
  133. > .text
  134. > #NO_APP
  135. > .L1423:
  136. > movzbl %dl,%esi
  137. The optimizer does a good job and gives us something we can actually
  138. understand. Can we? The actual user access is quite obvious. Thanks
  139. to the unified address space we can just access the address in user
  140. memory. But what does the .section stuff do?????
  141. To understand this we have to look at the final kernel::
  142. > objdump --section-headers vmlinux
  143. >
  144. > vmlinux: file format elf32-i386
  145. >
  146. > Sections:
  147. > Idx Name Size VMA LMA File off Algn
  148. > 0 .text 00098f40 c0100000 c0100000 00001000 2**4
  149. > CONTENTS, ALLOC, LOAD, READONLY, CODE
  150. > 1 .fixup 000016bc c0198f40 c0198f40 00099f40 2**0
  151. > CONTENTS, ALLOC, LOAD, READONLY, CODE
  152. > 2 .rodata 0000f127 c019a5fc c019a5fc 0009b5fc 2**2
  153. > CONTENTS, ALLOC, LOAD, READONLY, DATA
  154. > 3 __ex_table 000015c0 c01a9724 c01a9724 000aa724 2**2
  155. > CONTENTS, ALLOC, LOAD, READONLY, DATA
  156. > 4 .data 0000ea58 c01abcf0 c01abcf0 000abcf0 2**4
  157. > CONTENTS, ALLOC, LOAD, DATA
  158. > 5 .bss 00018e21 c01ba748 c01ba748 000ba748 2**2
  159. > ALLOC
  160. > 6 .comment 00000ec4 00000000 00000000 000ba748 2**0
  161. > CONTENTS, READONLY
  162. > 7 .note 00001068 00000ec4 00000ec4 000bb60c 2**0
  163. > CONTENTS, READONLY
  164. There are obviously 2 non standard ELF sections in the generated object
  165. file. But first we want to find out what happened to our code in the
  166. final kernel executable::
  167. > objdump --disassemble --section=.text vmlinux
  168. >
  169. > c017e785 <do_con_write+c1> xorl %edx,%edx
  170. > c017e787 <do_con_write+c3> movl 0xc01c7bec,%eax
  171. > c017e78c <do_con_write+c8> cmpl $0x18,0x314(%eax)
  172. > c017e793 <do_con_write+cf> je c017e79f <do_con_write+db>
  173. > c017e795 <do_con_write+d1> cmpl $0xbfffffff,0x40(%esp,1)
  174. > c017e79d <do_con_write+d9> ja c017e7a7 <do_con_write+e3>
  175. > c017e79f <do_con_write+db> movl %edx,%eax
  176. > c017e7a1 <do_con_write+dd> movl 0x40(%esp,1),%ebx
  177. > c017e7a5 <do_con_write+e1> movb (%ebx),%dl
  178. > c017e7a7 <do_con_write+e3> movzbl %dl,%esi
  179. The whole user memory access is reduced to 10 x86 machine instructions.
  180. The instructions bracketed in the .section directives are no longer
  181. in the normal execution path. They are located in a different section
  182. of the executable file::
  183. > objdump --disassemble --section=.fixup vmlinux
  184. >
  185. > c0199ff5 <.fixup+10b5> movl $0xfffffff2,%eax
  186. > c0199ffa <.fixup+10ba> xorb %dl,%dl
  187. > c0199ffc <.fixup+10bc> jmp c017e7a7 <do_con_write+e3>
  188. And finally::
  189. > objdump --full-contents --section=__ex_table vmlinux
  190. >
  191. > c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0 ................
  192. > c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0 ................
  193. > c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0 ................
  194. or in human readable byte order::
  195. > c01aa7c4 c017c093 c0199fe0 c017c097 c017c099 ................
  196. > c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5 ................
  197. ^^^^^^^^^^^^^^^^^
  198. this is the interesting part!
  199. > c01aa7e4 c0180a08 c019a001 c0180a0a c019a004 ................
  200. What happened? The assembly directives::
  201. .section .fixup,"ax"
  202. .section __ex_table,"a"
  203. told the assembler to move the following code to the specified
  204. sections in the ELF object file. So the instructions::
  205. 3: movl $-14,%eax
  206. xorb %dl,%dl
  207. jmp 2b
  208. ended up in the .fixup section of the object file and the addresses::
  209. .long 1b,3b
  210. ended up in the __ex_table section of the object file. 1b and 3b
  211. are local labels. The local label 1b (1b stands for next label 1
  212. backward) is the address of the instruction that might fault, i.e.
  213. in our case the address of the label 1 is c017e7a5:
  214. the original assembly code: > 1: movb (%ebx),%dl
  215. and linked in vmlinux : > c017e7a5 <do_con_write+e1> movb (%ebx),%dl
  216. The local label 3 (backwards again) is the address of the code to handle
  217. the fault, in our case the actual value is c0199ff5:
  218. the original assembly code: > 3: movl $-14,%eax
  219. and linked in vmlinux : > c0199ff5 <.fixup+10b5> movl $0xfffffff2,%eax
  220. If the fixup was able to handle the exception, control flow may be returned
  221. to the instruction after the one that triggered the fault, ie. local label 2b.
  222. The assembly code::
  223. > .section __ex_table,"a"
  224. > .align 4
  225. > .long 1b,3b
  226. becomes the value pair::
  227. > c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5 ................
  228. ^this is ^this is
  229. 1b 3b
  230. c017e7a5,c0199ff5 in the exception table of the kernel.
  231. So, what actually happens if a fault from kernel mode with no suitable
  232. vma occurs?
  233. #. access to invalid address::
  234. > c017e7a5 <do_con_write+e1> movb (%ebx),%dl
  235. #. MMU generates exception
  236. #. CPU calls exc_page_fault()
  237. #. exc_page_fault() calls do_user_addr_fault()
  238. #. do_user_addr_fault() calls kernelmode_fixup_or_oops()
  239. #. kernelmode_fixup_or_oops() calls fixup_exception() (regs->eip == c017e7a5);
  240. #. fixup_exception() calls search_exception_tables()
  241. #. search_exception_tables() looks up the address c017e7a5 in the
  242. exception table (i.e. the contents of the ELF section __ex_table)
  243. and returns the address of the associated fault handle code c0199ff5.
  244. #. fixup_exception() modifies its own return address to point to the fault
  245. handle code and returns.
  246. #. execution continues in the fault handling code.
  247. #. a) EAX becomes -EFAULT (== -14)
  248. b) DL becomes zero (the value we "read" from user space)
  249. c) execution continues at local label 2 (address of the
  250. instruction immediately after the faulting user access).
  251. The steps 8a to 8c in a certain way emulate the faulting instruction.
  252. That's it, mostly. If you look at our example, you might ask why
  253. we set EAX to -EFAULT in the exception handler code. Well, the
  254. get_user() macro actually returns a value: 0, if the user access was
  255. successful, -EFAULT on failure. Our original code did not test this
  256. return value, however the inline assembly code in get_user() tries to
  257. return -EFAULT. GCC selected EAX to return this value.
  258. NOTE:
  259. Due to the way that the exception table is built and needs to be ordered,
  260. only use exceptions for code in the .text section. Any other section
  261. will cause the exception table to not be sorted correctly, and the
  262. exceptions will fail.
  263. Things changed when 64-bit support was added to x86 Linux. Rather than
  264. double the size of the exception table by expanding the two entries
  265. from 32-bits to 64 bits, a clever trick was used to store addresses
  266. as relative offsets from the table itself. The assembly code changed
  267. from::
  268. .long 1b,3b
  269. to:
  270. .long (from) - .
  271. .long (to) - .
  272. and the C-code that uses these values converts back to absolute addresses
  273. like this::
  274. ex_insn_addr(const struct exception_table_entry *x)
  275. {
  276. return (unsigned long)&x->insn + x->insn;
  277. }
  278. In v4.6 the exception table entry was expanded with a new field "handler".
  279. This is also 32-bits wide and contains a third relative function
  280. pointer which points to one of:
  281. 1) ``int ex_handler_default(const struct exception_table_entry *fixup)``
  282. This is legacy case that just jumps to the fixup code
  283. 2) ``int ex_handler_fault(const struct exception_table_entry *fixup)``
  284. This case provides the fault number of the trap that occurred at
  285. entry->insn. It is used to distinguish page faults from machine
  286. check.
  287. More functions can easily be added.
  288. CONFIG_BUILDTIME_TABLE_SORT allows the __ex_table section to be sorted post
  289. link of the kernel image, via a host utility scripts/sorttable. It will set the
  290. symbol main_extable_sort_needed to 0, avoiding sorting the __ex_table section
  291. at boot time. With the exception table sorted, at runtime when an exception
  292. occurs we can quickly lookup the __ex_table entry via binary search.
  293. This is not just a boot time optimization, some architectures require this
  294. table to be sorted in order to handle exceptions relatively early in the boot
  295. process. For example, i386 makes use of this form of exception handling before
  296. paging support is even enabled!