Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_X86_PKEYS_H
0003 #define _ASM_X86_PKEYS_H
0004 
0005 /*
0006  * If more than 16 keys are ever supported, a thorough audit
0007  * will be necessary to ensure that the types that store key
0008  * numbers and masks have sufficient capacity.
0009  */
0010 #define arch_max_pkey() (cpu_feature_enabled(X86_FEATURE_OSPKE) ? 16 : 1)
0011 
0012 extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
0013         unsigned long init_val);
0014 
0015 static inline bool arch_pkeys_enabled(void)
0016 {
0017     return cpu_feature_enabled(X86_FEATURE_OSPKE);
0018 }
0019 
0020 /*
0021  * Try to dedicate one of the protection keys to be used as an
0022  * execute-only protection key.
0023  */
0024 extern int __execute_only_pkey(struct mm_struct *mm);
0025 static inline int execute_only_pkey(struct mm_struct *mm)
0026 {
0027     if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
0028         return ARCH_DEFAULT_PKEY;
0029 
0030     return __execute_only_pkey(mm);
0031 }
0032 
0033 extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
0034         int prot, int pkey);
0035 static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
0036         int prot, int pkey)
0037 {
0038     if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
0039         return 0;
0040 
0041     return __arch_override_mprotect_pkey(vma, prot, pkey);
0042 }
0043 
0044 #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | VM_PKEY_BIT3)
0045 
0046 #define mm_pkey_allocation_map(mm)  (mm->context.pkey_allocation_map)
0047 #define mm_set_pkey_allocated(mm, pkey) do {        \
0048     mm_pkey_allocation_map(mm) |= (1U << pkey); \
0049 } while (0)
0050 #define mm_set_pkey_free(mm, pkey) do {         \
0051     mm_pkey_allocation_map(mm) &= ~(1U << pkey);    \
0052 } while (0)
0053 
0054 static inline
0055 bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
0056 {
0057     /*
0058      * "Allocated" pkeys are those that have been returned
0059      * from pkey_alloc() or pkey 0 which is allocated
0060      * implicitly when the mm is created.
0061      */
0062     if (pkey < 0)
0063         return false;
0064     if (pkey >= arch_max_pkey())
0065         return false;
0066     /*
0067      * The exec-only pkey is set in the allocation map, but
0068      * is not available to any of the user interfaces like
0069      * mprotect_pkey().
0070      */
0071     if (pkey == mm->context.execute_only_pkey)
0072         return false;
0073 
0074     return mm_pkey_allocation_map(mm) & (1U << pkey);
0075 }
0076 
0077 /*
0078  * Returns a positive, 4-bit key on success, or -1 on failure.
0079  */
0080 static inline
0081 int mm_pkey_alloc(struct mm_struct *mm)
0082 {
0083     /*
0084      * Note: this is the one and only place we make sure
0085      * that the pkey is valid as far as the hardware is
0086      * concerned.  The rest of the kernel trusts that
0087      * only good, valid pkeys come out of here.
0088      */
0089     u16 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
0090     int ret;
0091 
0092     /*
0093      * Are we out of pkeys?  We must handle this specially
0094      * because ffz() behavior is undefined if there are no
0095      * zeros.
0096      */
0097     if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
0098         return -1;
0099 
0100     ret = ffz(mm_pkey_allocation_map(mm));
0101 
0102     mm_set_pkey_allocated(mm, ret);
0103 
0104     return ret;
0105 }
0106 
0107 static inline
0108 int mm_pkey_free(struct mm_struct *mm, int pkey)
0109 {
0110     if (!mm_pkey_is_allocated(mm, pkey))
0111         return -EINVAL;
0112 
0113     mm_set_pkey_free(mm, pkey);
0114 
0115     return 0;
0116 }
0117 
0118 static inline int vma_pkey(struct vm_area_struct *vma)
0119 {
0120     unsigned long vma_pkey_mask = VM_PKEY_BIT0 | VM_PKEY_BIT1 |
0121                       VM_PKEY_BIT2 | VM_PKEY_BIT3;
0122 
0123     return (vma->vm_flags & vma_pkey_mask) >> VM_PKEY_SHIFT;
0124 }
0125 
0126 #endif /*_ASM_X86_PKEYS_H */