Skip to content

Commit 54de197

Browse files
committed
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()
2 parents c76431e + f2f2272 commit 54de197

11 files changed

Lines changed: 210 additions & 49 deletions

File tree

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@
499499
#define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */
500500
#define X86_FEATURE_ABMC (21*32+15) /* Assignable Bandwidth Monitoring Counters */
501501
#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 */
502503

503504
#define X86_FEATURE_SDCIAE (21*32+18) /* L3 Smart Data Cache Injection Allocation Enforcement */
504505

arch/x86/include/asm/sgx.h

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2-
/**
2+
/*
33
* Copyright(c) 2016-20 Intel Corporation.
44
*
55
* Intel Software Guard Extensions (SGX) support.
@@ -28,21 +28,22 @@
2828
#define SGX_CPUID_EPC_MASK GENMASK(3, 0)
2929

3030
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,
4647
};
4748

4849
/**
@@ -65,22 +66,28 @@ enum sgx_encls_function {
6566

6667
/**
6768
* enum sgx_return_code - The return code type for ENCLS, ENCLU and ENCLV
68-
* %SGX_EPC_PAGE_CONFLICT: Page is being written by other ENCLS function.
69-
* %SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not
69+
* @SGX_EPC_PAGE_CONFLICT: Page is being written by other ENCLS function.
70+
* @SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not
7071
* been completed yet.
71-
* %SGX_CHILD_PRESENT SECS has child pages present in the EPC.
72-
* %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's
72+
* @SGX_CHILD_PRESENT: SECS has child pages present in the EPC.
73+
* @SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's
7374
* public key does not match IA32_SGXLEPUBKEYHASH.
74-
* %SGX_PAGE_NOT_MODIFIABLE: The EPC page cannot be modified because it
75+
* @SGX_PAGE_NOT_MODIFIABLE: The EPC page cannot be modified because it
7576
* is in the PENDING or MODIFIED state.
76-
* %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received
77+
* @SGX_INSUFFICIENT_ENTROPY: Insufficient entropy in RNG.
78+
* @SGX_NO_UPDATE: EUPDATESVN could not update the CPUSVN because the
79+
* current SVN was not newer than CPUSVN. This is the most
80+
* common error code returned by EUPDATESVN.
81+
* @SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received
7782
*/
7883
enum sgx_return_code {
7984
SGX_EPC_PAGE_CONFLICT = 7,
8085
SGX_NOT_TRACKED = 11,
8186
SGX_CHILD_PRESENT = 13,
8287
SGX_INVALID_EINITTOKEN = 16,
8388
SGX_PAGE_NOT_MODIFIABLE = 20,
89+
SGX_INSUFFICIENT_ENTROPY = 29,
90+
SGX_NO_UPDATE = 31,
8491
SGX_UNMASKED_EVENT = 128,
8592
};
8693

@@ -89,7 +96,7 @@ enum sgx_return_code {
8996

9097
/**
9198
* enum sgx_miscselect - additional information to an SSA frame
92-
* %SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame.
99+
* @SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame.
93100
*
94101
* Save State Area (SSA) is a stack inside the enclave used to store processor
95102
* state when an exception or interrupt occurs. This enum defines additional
@@ -105,17 +112,17 @@ enum sgx_miscselect {
105112
#define SGX_SSA_MISC_EXINFO_SIZE 16
106113

107114
/**
108-
* enum sgx_attributes - 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
115+
* enum sgx_attribute - 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
113120
* attestation.
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
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
116123
* sign cryptographic tokens that can be passed to
117124
* EINIT as an authorization to run an enclave.
118-
* %SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an
125+
* @SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an
119126
* asynchronous exit has occurred.
120127
*/
121128
enum sgx_attribute {
@@ -188,7 +195,7 @@ struct sgx_secs {
188195

189196
/**
190197
* enum sgx_tcs_flags - execution flags for TCS
191-
* %SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints
198+
* @SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints
192199
* inside an enclave. It is cleared by EADD but can
193200
* be set later with EDBGWR.
194201
*/
@@ -253,11 +260,11 @@ struct sgx_pageinfo {
253260

254261
/**
255262
* enum sgx_page_type - bits in the SECINFO flags defining the page type
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
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
261268
*
262269
* Make sure when making changes to this enum that its values can still fit
263270
* in the bitfield within &struct sgx_encl_page
@@ -275,14 +282,14 @@ enum sgx_page_type {
275282

276283
/**
277284
* enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo
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
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
286293
*/
287294
enum sgx_secinfo_flags {
288295
SGX_SECINFO_R = BIT(0),

arch/x86/include/uapi/asm/sgx.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
/**
1212
* 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
1414
* ENCLS[EEXTEND] operations.
1515
*/
1616
enum sgx_page_flags {
@@ -143,6 +143,12 @@ struct sgx_enclave_run;
143143
/**
144144
* typedef sgx_enclave_user_handler_t - Exit handler function accepted by
145145
* __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
146152
* @run: The run instance given by the caller
147153
*
148154
* The register parameters contain the snapshot of their values at enclave
@@ -166,7 +172,7 @@ typedef int (*sgx_enclave_user_handler_t)(long rdi, long rsi, long rdx,
166172
* @exception_addr: The address that triggered the exception
167173
* @user_handler: User provided callback run on exception
168174
* @user_data: Data passed to the user handler
169-
* @reserved Reserved for future extensions
175+
* @reserved: Reserved for future extensions
170176
*
171177
* If @user_handler is provided, the handler will be invoked on all return paths
172178
* of the normal flow. The user handler may transfer control, e.g. via a

arch/x86/kernel/cpu/cpuid-deps.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static const struct cpuid_dep cpuid_deps[] = {
8080
{ X86_FEATURE_SGX_LC, X86_FEATURE_SGX },
8181
{ X86_FEATURE_SGX1, X86_FEATURE_SGX },
8282
{ X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
83+
{ X86_FEATURE_SGX_EUPDATESVN, X86_FEATURE_SGX1 },
8384
{ X86_FEATURE_SGX_EDECCSSA, X86_FEATURE_SGX1 },
8485
{ X86_FEATURE_XFD, X86_FEATURE_XSAVES },
8586
{ X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },

arch/x86/kernel/cpu/scattered.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static const struct cpuid_bit cpuid_bits[] = {
4343
{ X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 },
4444
{ X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 },
4545
{ X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 },
46+
{ X86_FEATURE_SGX_EUPDATESVN, CPUID_EAX, 10, 0x00000012, 0 },
4647
{ X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 },
4748
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
4849
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },

arch/x86/kernel/cpu/sgx/driver.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ u64 sgx_attributes_reserved_mask;
1414
u64 sgx_xfrm_reserved_mask = ~0x3;
1515
u32 sgx_misc_reserved_mask;
1616

17-
static int sgx_open(struct inode *inode, struct file *file)
17+
static int __sgx_open(struct inode *inode, struct file *file)
1818
{
1919
struct sgx_encl *encl;
2020
int ret;
@@ -41,6 +41,23 @@ static int sgx_open(struct inode *inode, struct file *file)
4141
return 0;
4242
}
4343

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+
}
57+
58+
return 0;
59+
}
60+
4461
static int sgx_release(struct inode *inode, struct file *file)
4562
{
4663
struct sgx_encl *encl = file->private_data;

arch/x86/kernel/cpu/sgx/encl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ void sgx_encl_release(struct kref *ref)
765765
WARN_ON_ONCE(encl->secs.epc_page);
766766

767767
kfree(encl);
768+
sgx_dec_usage_count();
768769
}
769770

770771
/*

arch/x86/kernel/cpu/sgx/encls.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,9 @@ static inline int __eaug(struct sgx_pageinfo *pginfo, void *addr)
233233
return __encls_2(EAUG, pginfo, addr);
234234
}
235235

236+
/* Attempt to update CPUSVN at runtime. */
237+
static inline int __eupdatesvn(void)
238+
{
239+
return __encls_ret_1(EUPDATESVN, "");
240+
}
236241
#endif /* _X86_ENCLS_H */

arch/x86/kernel/cpu/sgx/main.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/vmalloc.h>
1717
#include <asm/msr.h>
1818
#include <asm/sgx.h>
19+
#include <asm/archrandom.h>
1920
#include "driver.h"
2021
#include "encl.h"
2122
#include "encls.h"
@@ -917,6 +918,106 @@ int sgx_set_attribute(unsigned long *allowed_attributes,
917918
}
918919
EXPORT_SYMBOL_GPL(sgx_set_attribute);
919920

921+
/* Counter to count the active SGX users */
922+
static int sgx_usage_count;
923+
924+
/**
925+
* sgx_update_svn() - Attempt to call ENCLS[EUPDATESVN].
926+
*
927+
* This instruction attempts to update CPUSVN to the
928+
* currently loaded microcode update SVN and generate new
929+
* cryptographic assets.
930+
*
931+
* Return:
932+
* * %0: - Success or not supported
933+
* * %-EAGAIN: - Can be safely retried, failure is due to lack of
934+
* * entropy in RNG
935+
* * %-EIO: - Unexpected error, retries are not advisable
936+
*/
937+
static int sgx_update_svn(void)
938+
{
939+
int ret;
940+
941+
/*
942+
* If EUPDATESVN is not available, it is ok to
943+
* silently skip it to comply with legacy behavior.
944+
*/
945+
if (!cpu_feature_enabled(X86_FEATURE_SGX_EUPDATESVN))
946+
return 0;
947+
948+
/*
949+
* EPC is guaranteed to be empty when there are no users.
950+
* Ensure we are on our first user before proceeding further.
951+
*/
952+
WARN(sgx_usage_count, "Elevated usage count when calling EUPDATESVN\n");
953+
954+
for (int i = 0; i < RDRAND_RETRY_LOOPS; i++) {
955+
ret = __eupdatesvn();
956+
957+
/* Stop on success or unexpected errors: */
958+
if (ret != SGX_INSUFFICIENT_ENTROPY)
959+
break;
960+
}
961+
962+
switch (ret) {
963+
case 0:
964+
/*
965+
* SVN successfully updated.
966+
* Let users know when the update was successful.
967+
*/
968+
pr_info("SVN updated successfully\n");
969+
return 0;
970+
case SGX_NO_UPDATE:
971+
/*
972+
* SVN update failed since the current SVN is
973+
* not newer than CPUSVN. This is the most
974+
* common case and indicates no harm.
975+
*/
976+
return 0;
977+
case SGX_INSUFFICIENT_ENTROPY:
978+
/*
979+
* SVN update failed due to lack of entropy in DRNG.
980+
* Indicate to userspace that it should retry.
981+
*/
982+
return -EAGAIN;
983+
default:
984+
break;
985+
}
986+
987+
/*
988+
* EUPDATESVN was called when EPC is empty, all other error
989+
* codes are unexpected.
990+
*/
991+
ENCLS_WARN(ret, "EUPDATESVN");
992+
return -EIO;
993+
}
994+
995+
/* Mutex to ensure no concurrent EPC accesses during EUPDATESVN */
996+
static DEFINE_MUTEX(sgx_svn_lock);
997+
998+
int sgx_inc_usage_count(void)
999+
{
1000+
int ret;
1001+
1002+
guard(mutex)(&sgx_svn_lock);
1003+
1004+
if (!sgx_usage_count) {
1005+
ret = sgx_update_svn();
1006+
if (ret)
1007+
return ret;
1008+
}
1009+
1010+
sgx_usage_count++;
1011+
1012+
return 0;
1013+
}
1014+
1015+
void sgx_dec_usage_count(void)
1016+
{
1017+
guard(mutex)(&sgx_svn_lock);
1018+
sgx_usage_count--;
1019+
}
1020+
9201021
static int __init sgx_init(void)
9211022
{
9221023
int ret;

arch/x86/kernel/cpu/sgx/sgx.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ static inline int __init sgx_vepc_init(void)
102102
}
103103
#endif
104104

105+
int sgx_inc_usage_count(void);
106+
void sgx_dec_usage_count(void);
107+
105108
void sgx_update_lepubkeyhash(u64 *lepubkeyhash);
106109

107110
#endif /* _X86_SGX_H */

0 commit comments

Comments
 (0)