^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _ASM_X86_PKEYS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_X86_PKEYS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #define ARCH_DEFAULT_PKEY 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * If more than 16 keys are ever supported, a thorough audit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * will be necessary to ensure that the types that store key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * numbers and masks have sufficient capacity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define arch_max_pkey() (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) unsigned long init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static inline bool arch_pkeys_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return boot_cpu_has(X86_FEATURE_OSPKE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Try to dedicate one of the protection keys to be used as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * execute-only protection key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) extern int __execute_only_pkey(struct mm_struct *mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static inline int execute_only_pkey(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (!boot_cpu_has(X86_FEATURE_OSPKE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return ARCH_DEFAULT_PKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return __execute_only_pkey(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int prot, int pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int prot, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!boot_cpu_has(X86_FEATURE_OSPKE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return __arch_override_mprotect_pkey(vma, prot, pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | VM_PKEY_BIT3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define mm_pkey_allocation_map(mm) (mm->context.pkey_allocation_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define mm_set_pkey_allocated(mm, pkey) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) mm_pkey_allocation_map(mm) |= (1U << pkey); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define mm_set_pkey_free(mm, pkey) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) mm_pkey_allocation_map(mm) &= ~(1U << pkey); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * "Allocated" pkeys are those that have been returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * from pkey_alloc() or pkey 0 which is allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * implicitly when the mm is created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (pkey < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (pkey >= arch_max_pkey())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * The exec-only pkey is set in the allocation map, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * is not available to any of the user interfaces like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * mprotect_pkey().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (pkey == mm->context.execute_only_pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return mm_pkey_allocation_map(mm) & (1U << pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Returns a positive, 4-bit key on success, or -1 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int mm_pkey_alloc(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Note: this is the one and only place we make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * that the pkey is valid as far as the hardware is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * concerned. The rest of the kernel trusts that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * only good, valid pkeys come out of here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u16 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Are we out of pkeys? We must handle this specially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * because ffz() behavior is undefined if there are no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * zeros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ret = ffz(mm_pkey_allocation_map(mm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mm_set_pkey_allocated(mm, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int mm_pkey_free(struct mm_struct *mm, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!mm_pkey_is_allocated(mm, pkey))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) mm_set_pkey_free(mm, pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned long init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) extern void copy_init_pkru_to_fpregs(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static inline int vma_pkey(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long vma_pkey_mask = VM_PKEY_BIT0 | VM_PKEY_BIT1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) VM_PKEY_BIT2 | VM_PKEY_BIT3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return (vma->vm_flags & vma_pkey_mask) >> VM_PKEY_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #endif /*_ASM_X86_PKEYS_H */