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