Skip to content

Commit 4e75697

Browse files
ereshetovahansendc
authored andcommitted
x86/sgx: Implement ENCLS[EUPDATESVN]
All running enclaves and cryptographic assets (such as internal SGX encryption keys) are assumed to be compromised whenever an SGX-related microcode update occurs. To mitigate this assumed compromise the new supervisor SGX instruction ENCLS[EUPDATESVN] can generate fresh cryptographic assets. Before executing EUPDATESVN, all SGX memory must be marked as unused. This requirement ensures that no potentially compromised enclave survives the update and allows the system to safely regenerate cryptographic assets. Add the method to perform ENCLS[EUPDATESVN]. However, until the follow up patch that wires calling sgx_update_svn() from sgx_inc_usage_count(), this code is not reachable. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Kai Huang <kai.huang@intel.com> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Tested-by: Nataliia Bondarevska <bondarn@google.com>
1 parent 7b50283 commit 4e75697

3 files changed

Lines changed: 96 additions & 15 deletions

File tree

arch/x86/include/asm/sgx.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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
/**

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: 75 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,80 @@ 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 __maybe_unused 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+
920995
int sgx_inc_usage_count(void)
921996
{
922997
return 0;

0 commit comments

Comments
 (0)