You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
6.6 KiB

  1. 1. Design
  2. The goal of MPROTECT is to help prevent the introduction of new executable
  3. code into the task's address space. This is accomplished by restricting the
  4. mmap() and mprotect() interfaces.
  5. The restrictions prevent
  6. - creating executable anonymous mappings
  7. - creating executable/writable file mappings
  8. - making an executable/read-only file mapping writable except for performing
  9. relocations on an ET_DYN ELF file (non-PIC shared library)
  10. - making a non-executable mapping executable
  11. To understand the restrictions consider the writability/executability of a
  12. mapping as state information. This state is stored in the vma structure in
  13. the vm_flags field and determines whether the given area (and consequently
  14. each page covered by it) is currently writable/executable and/or can be
  15. made writable/executable (by using mprotect() on the area). The flags that
  16. describe each attribute are: VM_WRITE, VM_EXEC, VM_MAYWRITE and VM_MAYEXEC.
  17. These four attributes mean that any mapping (vma) can be in 16 different
  18. states (for our discussion at least, we ignore the other attributes here),
  19. and our goal can be achieved by restricting what state a vma can be in or
  20. change to throughout its lifetime.
  21. Introducing new executable code into a mapping is impossible in any of the
  22. following ('good') states:
  23. VM_WRITE
  26. VM_EXEC
  29. In every other state it is either possible to directly write new executable
  30. code into the mapping or the mapping can be changed by mprotect() so that
  31. it becomes writable/executable.
  32. Note that the default kernel behaviour does already prevent certain states
  33. (in particular, a mapping cannot have VM_WRITE and VM_EXEC without also
  34. having VM_MAYWRITE and VM_MAYEXEC, respectively) so this leaves us with
  35. 4 good states:
  40. Let's see now what kind of mappings the kernel creates and what MPROTECT
  41. has to change in them:
  42. - anonymous mappings (stack, brk() and mmap() controlled heap): these
  43. are created in the VM_WRITE | VM_EXEC | VM_MAYWRITE | VM_MAYEXEC state
  44. which is not a good state. Since these mappings have to be writable, we
  45. can only change the executable status (this will still break real life
  46. applications, see later what could be done about them), MPROTECT simply
  47. changes their state to VM_WRITE | VM_MAYWRITE,
  48. - shared memory mappings: these are created in the VM_WRITE | VM_MAYWRITE
  49. state which is a good state,
  50. - file mappings: similarly to anonymous mappings, these can be created in
  51. all the bad states (list omitted for brevity), in particular the kernel
  52. grants VM_MAYWRITE | VM_MAYEXEC to any mapping regardless of what rights
  53. were requested. In order to break as few applications as possible yet
  54. still achieve our goal, we decided to use the following states for file
  55. mappings:
  56. - VM_WRITE | VM_MAYWRITE or VM_MAYWRITE if PROT_WRITE was requested at
  57. mmap() time
  58. - VM_EXEC | VM_MAYEXEC if PROT_WRITE was not requested.
  59. Effectively executable mappings are forced to be non-writable and writable
  60. mappings are forced to be non-executable (including the impossibility to
  61. change this state during their existence). There is one exception to this
  62. which is needed in order for the dynamic linker to be able to perform
  63. relocations on the executable segment of non-PIC ELF files. If one can
  64. ensure that no such libraries exist on his system (libraries should be
  65. PIC anyway), then this exception can be removed. Note that the ET_DYN ELF
  66. executables suggested for use under RANDMMAP should also be PIC (for this
  67. one needs a PIC version of crt1.o however).
  68. The above restrictions ensure that the only way to introduce executable
  69. code into a task's address space is by mapping a file into memory while
  70. requesting PROT_EXEC as well. For an attacker it means that he has to be
  71. able to create/write to a file on the target system before he can mmap()
  72. it into the attacked task's address space. There are various ways of
  73. preventing/detecting such venues of attack but they are beyond the scope
  74. of the PaX project.
  75. As mentioned before, the MPROTECT restrictions break existing applications
  76. that rely on the bad vma states. Most often this means the non-executable
  77. anonymous mappings as they are used for satisfying higher-level memory
  78. allocation requests (such as the malloc() family in C) and are assumed to
  79. be executable (java, gcc trampolines, etc). One way of allowing such
  80. applications to work under MPROTECT would be to extend the mmap() interface
  81. and allow setting the VM_MAY* flags to certain states. The following
  82. example demonstrates how an application would make use of this change:
  84. - generate code into the above area
  85. - mprotect(..., PROT_READ | PROT_EXEC)
  86. Note that PROT_EXEC is neither requested nor allowed in the initial mmap()
  87. call therefore application programmers are forced to call mprotect()
  88. explicitly and hence cannot accidentally violate the MPROTECT policy.
  89. 2. Implementation
  90. The first two restrictions are implemented in do_mmap_pgoff() and do_brk()
  91. in mm/mmap.c while the other two are in sys_mprotect() in mm/mprotect.c
  92. (non-PIC ELF libraries are handled by pax_handle_maywrite()).
  93. Since MPROTECT makes sense only when non-executable pages are enforced as
  94. well, the restrictions are enabled only when either of PAGEEXEC or SEGMEXEC
  95. is enabled for the given task. Furthermore some of the restrictions are
  96. already meaningful/necessary for enforcing just the non-executables pages,
  97. therefore they are applied even if MPROTECT itself is not enabled (but
  98. enabling MPROTECT is necessary to complete the feature).
  99. The special case of allowing non-PIC ELF relocations is managed by
  100. pax_handle_maywrite() in mm/mprotect.c. The logic is quite straightforward,
  101. first we verify that the mapping for which PROT_WRITE was requested is a
  102. candidate for relocations (it has to be an executable file mapping that has
  103. not yet been made writable) then we check that the backing file is an
  104. ET_DYN ELF file whose dynamic table has an entry showing the need for text
  105. relocations. If it is to be allowed we simply change the mapping state that
  106. will have the rest of the do_mprotect() logic allow the request and we also
  107. set the VM_MAYNOTWRITE flag that will disallow further PROT_WRITE requests
  108. on the mapping.