pkeys.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * PowerPC Memory Protection Keys management
  4. *
  5. * Copyright 2017, Ram Pai, IBM Corporation.
  6. */
  7. #ifndef _ASM_POWERPC_KEYS_H
  8. #define _ASM_POWERPC_KEYS_H
  9. #include <linux/jump_label.h>
  10. #include <asm/firmware.h>
  11. extern int num_pkey;
  12. extern u32 reserved_allocation_mask; /* bits set for reserved keys */
  13. #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \
  14. VM_PKEY_BIT3 | VM_PKEY_BIT4)
  15. /* Override any generic PKEY permission defines */
  16. #define PKEY_DISABLE_EXECUTE 0x4
  17. #define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | \
  18. PKEY_DISABLE_WRITE | \
  19. PKEY_DISABLE_EXECUTE)
  20. #ifdef CONFIG_PPC_BOOK3S_64
  21. #include <asm/book3s/64/pkeys.h>
  22. #else
  23. #error "Not supported"
  24. #endif
  25. static inline u64 pkey_to_vmflag_bits(u16 pkey)
  26. {
  27. return (((u64)pkey << VM_PKEY_SHIFT) & ARCH_VM_PKEY_FLAGS);
  28. }
  29. static inline int vma_pkey(struct vm_area_struct *vma)
  30. {
  31. if (!mmu_has_feature(MMU_FTR_PKEY))
  32. return 0;
  33. return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT;
  34. }
  35. static inline int arch_max_pkey(void)
  36. {
  37. return num_pkey;
  38. }
  39. #define pkey_alloc_mask(pkey) (0x1 << pkey)
  40. #define mm_pkey_allocation_map(mm) (mm->context.pkey_allocation_map)
  41. #define __mm_pkey_allocated(mm, pkey) { \
  42. mm_pkey_allocation_map(mm) |= pkey_alloc_mask(pkey); \
  43. }
  44. #define __mm_pkey_free(mm, pkey) { \
  45. mm_pkey_allocation_map(mm) &= ~pkey_alloc_mask(pkey); \
  46. }
  47. #define __mm_pkey_is_allocated(mm, pkey) \
  48. (mm_pkey_allocation_map(mm) & pkey_alloc_mask(pkey))
  49. #define __mm_pkey_is_reserved(pkey) (reserved_allocation_mask & \
  50. pkey_alloc_mask(pkey))
  51. static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
  52. {
  53. if (pkey < 0 || pkey >= arch_max_pkey())
  54. return false;
  55. /* Reserved keys are never allocated. */
  56. if (__mm_pkey_is_reserved(pkey))
  57. return false;
  58. return __mm_pkey_is_allocated(mm, pkey);
  59. }
  60. /*
  61. * Returns a positive, 5-bit key on success, or -1 on failure.
  62. * Relies on the mmap_lock to protect against concurrency in mm_pkey_alloc() and
  63. * mm_pkey_free().
  64. */
  65. static inline int mm_pkey_alloc(struct mm_struct *mm)
  66. {
  67. /*
  68. * Note: this is the one and only place we make sure that the pkey is
  69. * valid as far as the hardware is concerned. The rest of the kernel
  70. * trusts that only good, valid pkeys come out of here.
  71. */
  72. u32 all_pkeys_mask = (u32)(~(0x0));
  73. int ret;
  74. if (!mmu_has_feature(MMU_FTR_PKEY))
  75. return -1;
  76. /*
  77. * Are we out of pkeys? We must handle this specially because ffz()
  78. * behavior is undefined if there are no zeros.
  79. */
  80. if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
  81. return -1;
  82. ret = ffz((u32)mm_pkey_allocation_map(mm));
  83. __mm_pkey_allocated(mm, ret);
  84. return ret;
  85. }
  86. static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
  87. {
  88. if (!mmu_has_feature(MMU_FTR_PKEY))
  89. return -1;
  90. if (!mm_pkey_is_allocated(mm, pkey))
  91. return -EINVAL;
  92. __mm_pkey_free(mm, pkey);
  93. return 0;
  94. }
  95. /*
  96. * Try to dedicate one of the protection keys to be used as an
  97. * execute-only protection key.
  98. */
  99. extern int execute_only_pkey(struct mm_struct *mm);
  100. extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
  101. int prot, int pkey);
  102. static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
  103. int prot, int pkey)
  104. {
  105. if (!mmu_has_feature(MMU_FTR_PKEY))
  106. return 0;
  107. /*
  108. * Is this an mprotect_pkey() call? If so, never override the value that
  109. * came from the user.
  110. */
  111. if (pkey != -1)
  112. return pkey;
  113. return __arch_override_mprotect_pkey(vma, prot, pkey);
  114. }
  115. extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
  116. unsigned long init_val);
  117. static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
  118. unsigned long init_val)
  119. {
  120. if (!mmu_has_feature(MMU_FTR_PKEY))
  121. return -EINVAL;
  122. /*
  123. * userspace should not change pkey-0 permissions.
  124. * pkey-0 is associated with every page in the kernel.
  125. * If userspace denies any permission on pkey-0, the
  126. * kernel cannot operate.
  127. */
  128. if (pkey == 0)
  129. return init_val ? -EINVAL : 0;
  130. return __arch_set_user_pkey_access(tsk, pkey, init_val);
  131. }
  132. static inline bool arch_pkeys_enabled(void)
  133. {
  134. return mmu_has_feature(MMU_FTR_PKEY);
  135. }
  136. extern void pkey_mm_init(struct mm_struct *mm);
  137. #endif /*_ASM_POWERPC_KEYS_H */