Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86_sgx_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 SGX updates from Dave HansenL
"The main content here is adding support for the new EUPDATESVN SGX
ISA. Before this, folks who updated microcode had to reboot before
enclaves could attest to the new microcode. The new functionality lets
them do this without a reboot.

The rest are some nice, but relatively mundane comment and kernel-doc
fixups.

Summary:

- Allow security version (SVN) updates so enclaves can attest to new
microcode

- Fix kernel docs typos"

* tag 'x86_sgx_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/sgx: Fix a typo in the kernel-doc comment for enum sgx_attribute
x86/sgx: Remove superfluous asterisk from copyright comment in asm/sgx.h
x86/sgx: Document structs and enums with '@', not '%'
x86/sgx: Add kernel-doc descriptions for params passed to vDSO user handler
x86/sgx: Add a missing colon in kernel-doc markup for "struct sgx_enclave_run"
x86/sgx: Enable automatic SVN updates for SGX enclaves
x86/sgx: Implement ENCLS[EUPDATESVN]
x86/sgx: Define error codes for use by ENCLS[EUPDATESVN]
x86/cpufeatures: Add X86_FEATURE_SGX_EUPDATESVN feature flag
x86/sgx: Introduce functions to count the sgx_(vepc_)open()

+210 -49
+1
arch/x86/include/asm/cpufeatures.h
··· 499 499 #define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */ 500 500 #define X86_FEATURE_ABMC (21*32+15) /* Assignable Bandwidth Monitoring Counters */ 501 501 #define X86_FEATURE_MSR_IMM (21*32+16) /* MSR immediate form instructions */ 502 + #define X86_FEATURE_SGX_EUPDATESVN (21*32+17) /* Support for ENCLS[EUPDATESVN] instruction */ 502 503 503 504 #define X86_FEATURE_SDCIAE (21*32+18) /* L3 Smart Data Cache Injection Allocation Enforcement */ 504 505
+52 -45
arch/x86/include/asm/sgx.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - /** 2 + /* 3 3 * Copyright(c) 2016-20 Intel Corporation. 4 4 * 5 5 * Intel Software Guard Extensions (SGX) support. ··· 28 28 #define SGX_CPUID_EPC_MASK GENMASK(3, 0) 29 29 30 30 enum sgx_encls_function { 31 - ECREATE = 0x00, 32 - EADD = 0x01, 33 - EINIT = 0x02, 34 - EREMOVE = 0x03, 35 - EDGBRD = 0x04, 36 - EDGBWR = 0x05, 37 - EEXTEND = 0x06, 38 - ELDU = 0x08, 39 - EBLOCK = 0x09, 40 - EPA = 0x0A, 41 - EWB = 0x0B, 42 - ETRACK = 0x0C, 43 - EAUG = 0x0D, 44 - EMODPR = 0x0E, 45 - EMODT = 0x0F, 31 + ECREATE = 0x00, 32 + EADD = 0x01, 33 + EINIT = 0x02, 34 + EREMOVE = 0x03, 35 + EDGBRD = 0x04, 36 + EDGBWR = 0x05, 37 + EEXTEND = 0x06, 38 + ELDU = 0x08, 39 + EBLOCK = 0x09, 40 + EPA = 0x0A, 41 + EWB = 0x0B, 42 + ETRACK = 0x0C, 43 + EAUG = 0x0D, 44 + EMODPR = 0x0E, 45 + EMODT = 0x0F, 46 + EUPDATESVN = 0x18, 46 47 }; 47 48 48 49 /** ··· 66 65 67 66 /** 68 67 * enum sgx_return_code - The return code type for ENCLS, ENCLU and ENCLV 69 - * %SGX_EPC_PAGE_CONFLICT: Page is being written by other ENCLS function. 70 - * %SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not 68 + * @SGX_EPC_PAGE_CONFLICT: Page is being written by other ENCLS function. 69 + * @SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not 71 70 * been completed yet. 72 - * %SGX_CHILD_PRESENT SECS has child pages present in the EPC. 73 - * %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's 71 + * @SGX_CHILD_PRESENT: SECS has child pages present in the EPC. 72 + * @SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's 74 73 * public key does not match IA32_SGXLEPUBKEYHASH. 75 - * %SGX_PAGE_NOT_MODIFIABLE: The EPC page cannot be modified because it 74 + * @SGX_PAGE_NOT_MODIFIABLE: The EPC page cannot be modified because it 76 75 * is in the PENDING or MODIFIED state. 77 - * %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received 76 + * @SGX_INSUFFICIENT_ENTROPY: Insufficient entropy in RNG. 77 + * @SGX_NO_UPDATE: EUPDATESVN could not update the CPUSVN because the 78 + * current SVN was not newer than CPUSVN. This is the most 79 + * common error code returned by EUPDATESVN. 80 + * @SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received 78 81 */ 79 82 enum sgx_return_code { 80 83 SGX_EPC_PAGE_CONFLICT = 7, ··· 86 81 SGX_CHILD_PRESENT = 13, 87 82 SGX_INVALID_EINITTOKEN = 16, 88 83 SGX_PAGE_NOT_MODIFIABLE = 20, 84 + SGX_INSUFFICIENT_ENTROPY = 29, 85 + SGX_NO_UPDATE = 31, 89 86 SGX_UNMASKED_EVENT = 128, 90 87 }; 91 88 ··· 96 89 97 90 /** 98 91 * enum sgx_miscselect - additional information to an SSA frame 99 - * %SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame. 92 + * @SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame. 100 93 * 101 94 * Save State Area (SSA) is a stack inside the enclave used to store processor 102 95 * state when an exception or interrupt occurs. This enum defines additional ··· 112 105 #define SGX_SSA_MISC_EXINFO_SIZE 16 113 106 114 107 /** 115 - * enum sgx_attributes - the attributes field in &struct sgx_secs 116 - * %SGX_ATTR_INIT: Enclave can be entered (is initialized). 117 - * %SGX_ATTR_DEBUG: Allow ENCLS(EDBGRD) and ENCLS(EDBGWR). 118 - * %SGX_ATTR_MODE64BIT: Tell that this a 64-bit enclave. 119 - * %SGX_ATTR_PROVISIONKEY: Allow to use provisioning keys for remote 108 + * enum sgx_attribute - the attributes field in &struct sgx_secs 109 + * @SGX_ATTR_INIT: Enclave can be entered (is initialized). 110 + * @SGX_ATTR_DEBUG: Allow ENCLS(EDBGRD) and ENCLS(EDBGWR). 111 + * @SGX_ATTR_MODE64BIT: Tell that this a 64-bit enclave. 112 + * @SGX_ATTR_PROVISIONKEY: Allow to use provisioning keys for remote 120 113 * attestation. 121 - * %SGX_ATTR_KSS: Allow to use key separation and sharing (KSS). 122 - * %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to 114 + * @SGX_ATTR_KSS: Allow to use key separation and sharing (KSS). 115 + * @SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to 123 116 * sign cryptographic tokens that can be passed to 124 117 * EINIT as an authorization to run an enclave. 125 - * %SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an 118 + * @SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an 126 119 * asynchronous exit has occurred. 127 120 */ 128 121 enum sgx_attribute { ··· 195 188 196 189 /** 197 190 * enum sgx_tcs_flags - execution flags for TCS 198 - * %SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints 191 + * @SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints 199 192 * inside an enclave. It is cleared by EADD but can 200 193 * be set later with EDBGWR. 201 194 */ ··· 260 253 261 254 /** 262 255 * enum sgx_page_type - bits in the SECINFO flags defining the page type 263 - * %SGX_PAGE_TYPE_SECS: a SECS page 264 - * %SGX_PAGE_TYPE_TCS: a TCS page 265 - * %SGX_PAGE_TYPE_REG: a regular page 266 - * %SGX_PAGE_TYPE_VA: a VA page 267 - * %SGX_PAGE_TYPE_TRIM: a page in trimmed state 256 + * @SGX_PAGE_TYPE_SECS: a SECS page 257 + * @SGX_PAGE_TYPE_TCS: a TCS page 258 + * @SGX_PAGE_TYPE_REG: a regular page 259 + * @SGX_PAGE_TYPE_VA: a VA page 260 + * @SGX_PAGE_TYPE_TRIM: a page in trimmed state 268 261 * 269 262 * Make sure when making changes to this enum that its values can still fit 270 263 * in the bitfield within &struct sgx_encl_page ··· 282 275 283 276 /** 284 277 * enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo 285 - * %SGX_SECINFO_R: allow read 286 - * %SGX_SECINFO_W: allow write 287 - * %SGX_SECINFO_X: allow execution 288 - * %SGX_SECINFO_SECS: a SECS page 289 - * %SGX_SECINFO_TCS: a TCS page 290 - * %SGX_SECINFO_REG: a regular page 291 - * %SGX_SECINFO_VA: a VA page 292 - * %SGX_SECINFO_TRIM: a page in trimmed state 278 + * @SGX_SECINFO_R: allow read 279 + * @SGX_SECINFO_W: allow write 280 + * @SGX_SECINFO_X: allow execution 281 + * @SGX_SECINFO_SECS: a SECS page 282 + * @SGX_SECINFO_TCS: a TCS page 283 + * @SGX_SECINFO_REG: a regular page 284 + * @SGX_SECINFO_VA: a VA page 285 + * @SGX_SECINFO_TRIM: a page in trimmed state 293 286 */ 294 287 enum sgx_secinfo_flags { 295 288 SGX_SECINFO_R = BIT(0),
+8 -2
arch/x86/include/uapi/asm/sgx.h
··· 10 10 11 11 /** 12 12 * enum sgx_page_flags - page control flags 13 - * %SGX_PAGE_MEASURE: Measure the page contents with a sequence of 13 + * @SGX_PAGE_MEASURE: Measure the page contents with a sequence of 14 14 * ENCLS[EEXTEND] operations. 15 15 */ 16 16 enum sgx_page_flags { ··· 143 143 /** 144 144 * typedef sgx_enclave_user_handler_t - Exit handler function accepted by 145 145 * __vdso_sgx_enter_enclave() 146 + * @rdi: RDI at the time of EEXIT, undefined on AEX 147 + * @rsi: RSI at the time of EEXIT, undefined on AEX 148 + * @rdx: RDX at the time of EEXIT, undefined on AEX 149 + * @rsp: RSP (untrusted) at the time of EEXIT or AEX 150 + * @r8: R8 at the time of EEXIT, undefined on AEX 151 + * @r9: R9 at the time of EEXIT, undefined on AEX 146 152 * @run: The run instance given by the caller 147 153 * 148 154 * The register parameters contain the snapshot of their values at enclave ··· 172 166 * @exception_addr: The address that triggered the exception 173 167 * @user_handler: User provided callback run on exception 174 168 * @user_data: Data passed to the user handler 175 - * @reserved Reserved for future extensions 169 + * @reserved: Reserved for future extensions 176 170 * 177 171 * If @user_handler is provided, the handler will be invoked on all return paths 178 172 * of the normal flow. The user handler may transfer control, e.g. via a
+1
arch/x86/kernel/cpu/cpuid-deps.c
··· 80 80 { X86_FEATURE_SGX_LC, X86_FEATURE_SGX }, 81 81 { X86_FEATURE_SGX1, X86_FEATURE_SGX }, 82 82 { X86_FEATURE_SGX2, X86_FEATURE_SGX1 }, 83 + { X86_FEATURE_SGX_EUPDATESVN, X86_FEATURE_SGX1 }, 83 84 { X86_FEATURE_SGX_EDECCSSA, X86_FEATURE_SGX1 }, 84 85 { X86_FEATURE_XFD, X86_FEATURE_XSAVES }, 85 86 { X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
+1
arch/x86/kernel/cpu/scattered.c
··· 43 43 { X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 }, 44 44 { X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 }, 45 45 { X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 }, 46 + { X86_FEATURE_SGX_EUPDATESVN, CPUID_EAX, 10, 0x00000012, 0 }, 46 47 { X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 }, 47 48 { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, 48 49 { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
+18 -1
arch/x86/kernel/cpu/sgx/driver.c
··· 14 14 u64 sgx_xfrm_reserved_mask = ~0x3; 15 15 u32 sgx_misc_reserved_mask; 16 16 17 - static int sgx_open(struct inode *inode, struct file *file) 17 + static int __sgx_open(struct inode *inode, struct file *file) 18 18 { 19 19 struct sgx_encl *encl; 20 20 int ret; ··· 37 37 } 38 38 39 39 file->private_data = encl; 40 + 41 + return 0; 42 + } 43 + 44 + static int sgx_open(struct inode *inode, struct file *file) 45 + { 46 + int ret; 47 + 48 + ret = sgx_inc_usage_count(); 49 + if (ret) 50 + return ret; 51 + 52 + ret = __sgx_open(inode, file); 53 + if (ret) { 54 + sgx_dec_usage_count(); 55 + return ret; 56 + } 40 57 41 58 return 0; 42 59 }
+1
arch/x86/kernel/cpu/sgx/encl.c
··· 765 765 WARN_ON_ONCE(encl->secs.epc_page); 766 766 767 767 kfree(encl); 768 + sgx_dec_usage_count(); 768 769 } 769 770 770 771 /*
+5
arch/x86/kernel/cpu/sgx/encls.h
··· 233 233 return __encls_2(EAUG, pginfo, addr); 234 234 } 235 235 236 + /* Attempt to update CPUSVN at runtime. */ 237 + static inline int __eupdatesvn(void) 238 + { 239 + return __encls_ret_1(EUPDATESVN, ""); 240 + } 236 241 #endif /* _X86_ENCLS_H */
+101
arch/x86/kernel/cpu/sgx/main.c
··· 16 16 #include <linux/vmalloc.h> 17 17 #include <asm/msr.h> 18 18 #include <asm/sgx.h> 19 + #include <asm/archrandom.h> 19 20 #include "driver.h" 20 21 #include "encl.h" 21 22 #include "encls.h" ··· 917 916 return 0; 918 917 } 919 918 EXPORT_SYMBOL_GPL(sgx_set_attribute); 919 + 920 + /* Counter to count the active SGX users */ 921 + static int sgx_usage_count; 922 + 923 + /** 924 + * sgx_update_svn() - Attempt to call ENCLS[EUPDATESVN]. 925 + * 926 + * This instruction attempts to update CPUSVN to the 927 + * currently loaded microcode update SVN and generate new 928 + * cryptographic assets. 929 + * 930 + * Return: 931 + * * %0: - Success or not supported 932 + * * %-EAGAIN: - Can be safely retried, failure is due to lack of 933 + * * entropy in RNG 934 + * * %-EIO: - Unexpected error, retries are not advisable 935 + */ 936 + static int sgx_update_svn(void) 937 + { 938 + int ret; 939 + 940 + /* 941 + * If EUPDATESVN is not available, it is ok to 942 + * silently skip it to comply with legacy behavior. 943 + */ 944 + if (!cpu_feature_enabled(X86_FEATURE_SGX_EUPDATESVN)) 945 + return 0; 946 + 947 + /* 948 + * EPC is guaranteed to be empty when there are no users. 949 + * Ensure we are on our first user before proceeding further. 950 + */ 951 + WARN(sgx_usage_count, "Elevated usage count when calling EUPDATESVN\n"); 952 + 953 + for (int i = 0; i < RDRAND_RETRY_LOOPS; i++) { 954 + ret = __eupdatesvn(); 955 + 956 + /* Stop on success or unexpected errors: */ 957 + if (ret != SGX_INSUFFICIENT_ENTROPY) 958 + break; 959 + } 960 + 961 + switch (ret) { 962 + case 0: 963 + /* 964 + * SVN successfully updated. 965 + * Let users know when the update was successful. 966 + */ 967 + pr_info("SVN updated successfully\n"); 968 + return 0; 969 + case SGX_NO_UPDATE: 970 + /* 971 + * SVN update failed since the current SVN is 972 + * not newer than CPUSVN. This is the most 973 + * common case and indicates no harm. 974 + */ 975 + return 0; 976 + case SGX_INSUFFICIENT_ENTROPY: 977 + /* 978 + * SVN update failed due to lack of entropy in DRNG. 979 + * Indicate to userspace that it should retry. 980 + */ 981 + return -EAGAIN; 982 + default: 983 + break; 984 + } 985 + 986 + /* 987 + * EUPDATESVN was called when EPC is empty, all other error 988 + * codes are unexpected. 989 + */ 990 + ENCLS_WARN(ret, "EUPDATESVN"); 991 + return -EIO; 992 + } 993 + 994 + /* Mutex to ensure no concurrent EPC accesses during EUPDATESVN */ 995 + static DEFINE_MUTEX(sgx_svn_lock); 996 + 997 + int sgx_inc_usage_count(void) 998 + { 999 + int ret; 1000 + 1001 + guard(mutex)(&sgx_svn_lock); 1002 + 1003 + if (!sgx_usage_count) { 1004 + ret = sgx_update_svn(); 1005 + if (ret) 1006 + return ret; 1007 + } 1008 + 1009 + sgx_usage_count++; 1010 + 1011 + return 0; 1012 + } 1013 + 1014 + void sgx_dec_usage_count(void) 1015 + { 1016 + guard(mutex)(&sgx_svn_lock); 1017 + sgx_usage_count--; 1018 + } 920 1019 921 1020 static int __init sgx_init(void) 922 1021 {
+3
arch/x86/kernel/cpu/sgx/sgx.h
··· 102 102 } 103 103 #endif 104 104 105 + int sgx_inc_usage_count(void); 106 + void sgx_dec_usage_count(void); 107 + 105 108 void sgx_update_lepubkeyhash(u64 *lepubkeyhash); 106 109 107 110 #endif /* _X86_SGX_H */
+19 -1
arch/x86/kernel/cpu/sgx/virt.c
··· 255 255 xa_destroy(&vepc->page_array); 256 256 kfree(vepc); 257 257 258 + sgx_dec_usage_count(); 258 259 return 0; 259 260 } 260 261 261 - static int sgx_vepc_open(struct inode *inode, struct file *file) 262 + static int __sgx_vepc_open(struct inode *inode, struct file *file) 262 263 { 263 264 struct sgx_vepc *vepc; 264 265 ··· 270 269 xa_init(&vepc->page_array); 271 270 272 271 file->private_data = vepc; 272 + 273 + return 0; 274 + } 275 + 276 + static int sgx_vepc_open(struct inode *inode, struct file *file) 277 + { 278 + int ret; 279 + 280 + ret = sgx_inc_usage_count(); 281 + if (ret) 282 + return ret; 283 + 284 + ret = __sgx_vepc_open(inode, file); 285 + if (ret) { 286 + sgx_dec_usage_count(); 287 + return ret; 288 + } 273 289 274 290 return 0; 275 291 }