^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PowerPC Memory Protection Keys management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2017, Ram Pai, IBM Corporation.
^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) #ifndef _ASM_POWERPC_KEYS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define _ASM_POWERPC_KEYS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/jump_label.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) extern int num_pkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) extern u32 reserved_allocation_mask; /* bits set for reserved keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) VM_PKEY_BIT3 | VM_PKEY_BIT4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Override any generic PKEY permission defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define PKEY_DISABLE_EXECUTE 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) PKEY_DISABLE_WRITE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) PKEY_DISABLE_EXECUTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/book3s/64/pkeys.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #error "Not supported"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static inline u64 pkey_to_vmflag_bits(u16 pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return (((u64)pkey << VM_PKEY_SHIFT) & ARCH_VM_PKEY_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static inline int vma_pkey(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!mmu_has_feature(MMU_FTR_PKEY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static inline int arch_max_pkey(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return num_pkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define pkey_alloc_mask(pkey) (0x1 << pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define mm_pkey_allocation_map(mm) (mm->context.pkey_allocation_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define __mm_pkey_allocated(mm, pkey) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) mm_pkey_allocation_map(mm) |= pkey_alloc_mask(pkey); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define __mm_pkey_free(mm, pkey) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mm_pkey_allocation_map(mm) &= ~pkey_alloc_mask(pkey); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define __mm_pkey_is_allocated(mm, pkey) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) (mm_pkey_allocation_map(mm) & pkey_alloc_mask(pkey))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define __mm_pkey_is_reserved(pkey) (reserved_allocation_mask & \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) pkey_alloc_mask(pkey))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (pkey < 0 || pkey >= arch_max_pkey())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Reserved keys are never allocated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (__mm_pkey_is_reserved(pkey))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return __mm_pkey_is_allocated(mm, pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Returns a positive, 5-bit key on success, or -1 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Relies on the mmap_lock to protect against concurrency in mm_pkey_alloc() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * mm_pkey_free().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline int mm_pkey_alloc(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Note: this is the one and only place we make sure that the pkey is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * valid as far as the hardware is concerned. The rest of the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * trusts that only good, valid pkeys come out of here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 all_pkeys_mask = (u32)(~(0x0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!mmu_has_feature(MMU_FTR_PKEY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -1;
^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 because ffz()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * behavior is undefined if there are no zeros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = ffz((u32)mm_pkey_allocation_map(mm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __mm_pkey_allocated(mm, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!mmu_has_feature(MMU_FTR_PKEY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return -1;
^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_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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Try to dedicate one of the protection keys to be used as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * execute-only protection key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) extern int execute_only_pkey(struct mm_struct *mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int prot, int pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int prot, int pkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!mmu_has_feature(MMU_FTR_PKEY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^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) * Is this an mprotect_pkey() call? If so, never override the value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * came from the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (pkey != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return pkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return __arch_override_mprotect_pkey(vma, prot, pkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned long init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned long init_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!mmu_has_feature(MMU_FTR_PKEY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * userspace should not change pkey-0 permissions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * pkey-0 is associated with every page in the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * If userspace denies any permission on pkey-0, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * kernel cannot operate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (pkey == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return init_val ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return __arch_set_user_pkey_access(tsk, pkey, init_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static inline bool arch_pkeys_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return mmu_has_feature(MMU_FTR_PKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) extern void pkey_mm_init(struct mm_struct *mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) extern bool arch_supports_pkeys(int cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) extern unsigned int arch_usable_pkeys(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) extern void thread_pkey_regs_save(struct thread_struct *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) extern void thread_pkey_regs_restore(struct thread_struct *new_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct thread_struct *old_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) extern void thread_pkey_regs_init(struct thread_struct *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #endif /*_ASM_POWERPC_KEYS_H */