userfaultfd_k.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * include/linux/userfaultfd_k.h
  4. *
  5. * Copyright (C) 2015 Red Hat, Inc.
  6. *
  7. */
  8. #ifndef _LINUX_USERFAULTFD_K_H
  9. #define _LINUX_USERFAULTFD_K_H
  10. #ifdef CONFIG_USERFAULTFD
  11. #include <linux/userfaultfd.h> /* linux/include/uapi/linux/userfaultfd.h */
  12. #include <linux/fcntl.h>
  13. #include <linux/mm.h>
  14. #include <linux/swap.h>
  15. #include <linux/swapops.h>
  16. #include <asm-generic/pgtable_uffd.h>
  17. #include <linux/hugetlb_inline.h>
  18. /* The set of all possible UFFD-related VM flags. */
  19. #define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_WP | VM_UFFD_MINOR)
  20. /*
  21. * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining
  22. * new flags, since they might collide with O_* ones. We want
  23. * to re-use O_* flags that couldn't possibly have a meaning
  24. * from userfaultfd, in order to leave a free define-space for
  25. * shared O_* flags.
  26. */
  27. #define UFFD_CLOEXEC O_CLOEXEC
  28. #define UFFD_NONBLOCK O_NONBLOCK
  29. #define UFFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
  30. #define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)
  31. extern int sysctl_unprivileged_userfaultfd;
  32. extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason);
  33. /*
  34. * The mode of operation for __mcopy_atomic and its helpers.
  35. *
  36. * This is almost an implementation detail (mcopy_atomic below doesn't take this
  37. * as a parameter), but it's exposed here because memory-kind-specific
  38. * implementations (e.g. hugetlbfs) need to know the mode of operation.
  39. */
  40. enum mcopy_atomic_mode {
  41. /* A normal copy_from_user into the destination range. */
  42. MCOPY_ATOMIC_NORMAL,
  43. /* Don't copy; map the destination range to the zero page. */
  44. MCOPY_ATOMIC_ZEROPAGE,
  45. /* Just install pte(s) with the existing page(s) in the page cache. */
  46. MCOPY_ATOMIC_CONTINUE,
  47. };
  48. extern int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
  49. struct vm_area_struct *dst_vma,
  50. unsigned long dst_addr, struct page *page,
  51. bool newly_allocated, bool wp_copy);
  52. extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
  53. unsigned long src_start, unsigned long len,
  54. atomic_t *mmap_changing, __u64 mode);
  55. extern ssize_t mfill_zeropage(struct mm_struct *dst_mm,
  56. unsigned long dst_start,
  57. unsigned long len,
  58. atomic_t *mmap_changing);
  59. extern ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long dst_start,
  60. unsigned long len, atomic_t *mmap_changing);
  61. extern int mwriteprotect_range(struct mm_struct *dst_mm,
  62. unsigned long start, unsigned long len,
  63. bool enable_wp, atomic_t *mmap_changing);
  64. extern void uffd_wp_range(struct mm_struct *dst_mm, struct vm_area_struct *vma,
  65. unsigned long start, unsigned long len, bool enable_wp);
  66. /* mm helpers */
  67. static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
  68. struct vm_userfaultfd_ctx vm_ctx)
  69. {
  70. return vma->vm_userfaultfd_ctx.ctx == vm_ctx.ctx;
  71. }
  72. /*
  73. * Never enable huge pmd sharing on some uffd registered vmas:
  74. *
  75. * - VM_UFFD_WP VMAs, because write protect information is per pgtable entry.
  76. *
  77. * - VM_UFFD_MINOR VMAs, because otherwise we would never get minor faults for
  78. * VMAs which share huge pmds. (If you have two mappings to the same
  79. * underlying pages, and fault in the non-UFFD-registered one with a write,
  80. * with huge pmd sharing this would *also* setup the second UFFD-registered
  81. * mapping, and we'd not get minor faults.)
  82. */
  83. static inline bool uffd_disable_huge_pmd_share(struct vm_area_struct *vma)
  84. {
  85. return vma->vm_flags & (VM_UFFD_WP | VM_UFFD_MINOR);
  86. }
  87. /*
  88. * Don't do fault around for either WP or MINOR registered uffd range. For
  89. * MINOR registered range, fault around will be a total disaster and ptes can
  90. * be installed without notifications; for WP it should mostly be fine as long
  91. * as the fault around checks for pte_none() before the installation, however
  92. * to be super safe we just forbid it.
  93. */
  94. static inline bool uffd_disable_fault_around(struct vm_area_struct *vma)
  95. {
  96. return vma->vm_flags & (VM_UFFD_WP | VM_UFFD_MINOR);
  97. }
  98. static inline bool userfaultfd_missing(struct vm_area_struct *vma)
  99. {
  100. return vma->vm_flags & VM_UFFD_MISSING;
  101. }
  102. static inline bool userfaultfd_wp(struct vm_area_struct *vma)
  103. {
  104. return vma->vm_flags & VM_UFFD_WP;
  105. }
  106. static inline bool userfaultfd_minor(struct vm_area_struct *vma)
  107. {
  108. return vma->vm_flags & VM_UFFD_MINOR;
  109. }
  110. static inline bool userfaultfd_pte_wp(struct vm_area_struct *vma,
  111. pte_t pte)
  112. {
  113. return userfaultfd_wp(vma) && pte_uffd_wp(pte);
  114. }
  115. static inline bool userfaultfd_huge_pmd_wp(struct vm_area_struct *vma,
  116. pmd_t pmd)
  117. {
  118. return userfaultfd_wp(vma) && pmd_uffd_wp(pmd);
  119. }
  120. static inline bool userfaultfd_armed(struct vm_area_struct *vma)
  121. {
  122. return vma->vm_flags & __VM_UFFD_FLAGS;
  123. }
  124. static inline bool vma_can_userfault(struct vm_area_struct *vma,
  125. unsigned long vm_flags)
  126. {
  127. if ((vm_flags & VM_UFFD_MINOR) &&
  128. (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
  129. return false;
  130. #ifndef CONFIG_PTE_MARKER_UFFD_WP
  131. /*
  132. * If user requested uffd-wp but not enabled pte markers for
  133. * uffd-wp, then shmem & hugetlbfs are not supported but only
  134. * anonymous.
  135. */
  136. if ((vm_flags & VM_UFFD_WP) && !vma_is_anonymous(vma))
  137. return false;
  138. #endif
  139. return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
  140. vma_is_shmem(vma);
  141. }
  142. extern int dup_userfaultfd(struct vm_area_struct *, struct list_head *);
  143. extern void dup_userfaultfd_complete(struct list_head *);
  144. extern void mremap_userfaultfd_prep(struct vm_area_struct *,
  145. struct vm_userfaultfd_ctx *);
  146. extern void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *,
  147. unsigned long from, unsigned long to,
  148. unsigned long len);
  149. extern bool userfaultfd_remove(struct vm_area_struct *vma,
  150. unsigned long start,
  151. unsigned long end);
  152. extern int userfaultfd_unmap_prep(struct vm_area_struct *vma,
  153. unsigned long start, unsigned long end, struct list_head *uf);
  154. extern void userfaultfd_unmap_complete(struct mm_struct *mm,
  155. struct list_head *uf);
  156. #else /* CONFIG_USERFAULTFD */
  157. /* mm helpers */
  158. static inline vm_fault_t handle_userfault(struct vm_fault *vmf,
  159. unsigned long reason)
  160. {
  161. return VM_FAULT_SIGBUS;
  162. }
  163. static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
  164. struct vm_userfaultfd_ctx vm_ctx)
  165. {
  166. return true;
  167. }
  168. static inline bool userfaultfd_missing(struct vm_area_struct *vma)
  169. {
  170. return false;
  171. }
  172. static inline bool userfaultfd_wp(struct vm_area_struct *vma)
  173. {
  174. return false;
  175. }
  176. static inline bool userfaultfd_minor(struct vm_area_struct *vma)
  177. {
  178. return false;
  179. }
  180. static inline bool userfaultfd_pte_wp(struct vm_area_struct *vma,
  181. pte_t pte)
  182. {
  183. return false;
  184. }
  185. static inline bool userfaultfd_huge_pmd_wp(struct vm_area_struct *vma,
  186. pmd_t pmd)
  187. {
  188. return false;
  189. }
  190. static inline bool userfaultfd_armed(struct vm_area_struct *vma)
  191. {
  192. return false;
  193. }
  194. static inline int dup_userfaultfd(struct vm_area_struct *vma,
  195. struct list_head *l)
  196. {
  197. return 0;
  198. }
  199. static inline void dup_userfaultfd_complete(struct list_head *l)
  200. {
  201. }
  202. static inline void mremap_userfaultfd_prep(struct vm_area_struct *vma,
  203. struct vm_userfaultfd_ctx *ctx)
  204. {
  205. }
  206. static inline void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *ctx,
  207. unsigned long from,
  208. unsigned long to,
  209. unsigned long len)
  210. {
  211. }
  212. static inline bool userfaultfd_remove(struct vm_area_struct *vma,
  213. unsigned long start,
  214. unsigned long end)
  215. {
  216. return true;
  217. }
  218. static inline int userfaultfd_unmap_prep(struct vm_area_struct *vma,
  219. unsigned long start, unsigned long end,
  220. struct list_head *uf)
  221. {
  222. return 0;
  223. }
  224. static inline void userfaultfd_unmap_complete(struct mm_struct *mm,
  225. struct list_head *uf)
  226. {
  227. }
  228. static inline bool uffd_disable_fault_around(struct vm_area_struct *vma)
  229. {
  230. return false;
  231. }
  232. #endif /* CONFIG_USERFAULTFD */
  233. static inline bool pte_marker_entry_uffd_wp(swp_entry_t entry)
  234. {
  235. #ifdef CONFIG_PTE_MARKER_UFFD_WP
  236. return is_pte_marker_entry(entry) &&
  237. (pte_marker_get(entry) & PTE_MARKER_UFFD_WP);
  238. #else
  239. return false;
  240. #endif
  241. }
  242. static inline bool pte_marker_uffd_wp(pte_t pte)
  243. {
  244. #ifdef CONFIG_PTE_MARKER_UFFD_WP
  245. swp_entry_t entry;
  246. if (!is_swap_pte(pte))
  247. return false;
  248. entry = pte_to_swp_entry(pte);
  249. return pte_marker_entry_uffd_wp(entry);
  250. #else
  251. return false;
  252. #endif
  253. }
  254. /*
  255. * Returns true if this is a swap pte and was uffd-wp wr-protected in either
  256. * forms (pte marker or a normal swap pte), false otherwise.
  257. */
  258. static inline bool pte_swp_uffd_wp_any(pte_t pte)
  259. {
  260. #ifdef CONFIG_PTE_MARKER_UFFD_WP
  261. if (!is_swap_pte(pte))
  262. return false;
  263. if (pte_swp_uffd_wp(pte))
  264. return true;
  265. if (pte_marker_uffd_wp(pte))
  266. return true;
  267. #endif
  268. return false;
  269. }
  270. #endif /* _LINUX_USERFAULTFD_K_H */