uaccess.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #ifndef __LINUX_UACCESS_H__
  2. #define __LINUX_UACCESS_H__
  3. #include <linux/preempt.h>
  4. #include <asm/uaccess.h>
  5. /*
  6. * These routines enable/disable the pagefault handler in that
  7. * it will not take any locks and go straight to the fixup table.
  8. *
  9. * They have great resemblance to the preempt_disable/enable calls
  10. * and in fact they are identical; this is because currently there is
  11. * no other way to make the pagefault handlers do this. So we do
  12. * disable preemption but we don't necessarily care about that.
  13. */
  14. static inline void pagefault_disable(void)
  15. {
  16. preempt_count_inc();
  17. /*
  18. * make sure to have issued the store before a pagefault
  19. * can hit.
  20. */
  21. barrier();
  22. }
  23. static inline void pagefault_enable(void)
  24. {
  25. #ifndef CONFIG_PREEMPT
  26. /*
  27. * make sure to issue those last loads/stores before enabling
  28. * the pagefault handler again.
  29. */
  30. barrier();
  31. preempt_count_dec();
  32. #else
  33. preempt_enable();
  34. #endif
  35. }
  36. #ifndef ARCH_HAS_NOCACHE_UACCESS
  37. static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
  38. const void __user *from, unsigned long n)
  39. {
  40. return __copy_from_user_inatomic(to, from, n);
  41. }
  42. static inline unsigned long __copy_from_user_nocache(void *to,
  43. const void __user *from, unsigned long n)
  44. {
  45. return __copy_from_user(to, from, n);
  46. }
  47. #endif /* ARCH_HAS_NOCACHE_UACCESS */
  48. /**
  49. * probe_kernel_address(): safely attempt to read from a location
  50. * @addr: address to read from - its type is type typeof(retval)*
  51. * @retval: read into this variable
  52. *
  53. * Safely read from address @addr into variable @revtal. If a kernel fault
  54. * happens, handle that and return -EFAULT.
  55. * We ensure that the __get_user() is executed in atomic context so that
  56. * do_page_fault() doesn't attempt to take mmap_sem. This makes
  57. * probe_kernel_address() suitable for use within regions where the caller
  58. * already holds mmap_sem, or other locks which nest inside mmap_sem.
  59. * This must be a macro because __get_user() needs to know the types of the
  60. * args.
  61. *
  62. * We don't include enough header files to be able to do the set_fs(). We
  63. * require that the probe_kernel_address() caller will do that.
  64. */
  65. #define probe_kernel_address(addr, retval) \
  66. ({ \
  67. long ret; \
  68. mm_segment_t old_fs = get_fs(); \
  69. \
  70. set_fs(KERNEL_DS); \
  71. pagefault_disable(); \
  72. ret = __copy_from_user_inatomic(&(retval), (__force typeof(retval) __user *)(addr), sizeof(retval)); \
  73. pagefault_enable(); \
  74. set_fs(old_fs); \
  75. ret; \
  76. })
  77. /*
  78. * probe_kernel_read(): safely attempt to read from a location
  79. * @dst: pointer to the buffer that shall take the data
  80. * @src: address to read from
  81. * @size: size of the data chunk
  82. *
  83. * Safely read from address @src to the buffer at @dst. If a kernel fault
  84. * happens, handle that and return -EFAULT.
  85. */
  86. extern long probe_kernel_read(void *dst, const void *src, size_t size);
  87. extern long __probe_kernel_read(void *dst, const void *src, size_t size);
  88. /*
  89. * probe_kernel_write(): safely attempt to write to a location
  90. * @dst: address to write to
  91. * @src: pointer to the data that shall be written
  92. * @size: size of the data chunk
  93. *
  94. * Safely write to address @dst from the buffer at @src. If a kernel fault
  95. * happens, handle that and return -EFAULT.
  96. */
  97. extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
  98. extern long notrace __probe_kernel_write(void *dst, const void *src, size_t size);
  99. #endif /* __LINUX_UACCESS_H__ */