From c8a352553b36c116a6a5dda8dc7a61297e55bdcd Mon Sep 17 00:00:00 2001 From: Chia-Che Tsai Date: Fri, 20 Sep 2019 22:33:52 -0500 Subject: [PATCH] [Pal/Linux-SGX] Change manifest option sgx.enable_[avx|avx512|mpx] to sgx.require_[avx|avx512|mpx] This commit allows setting the AVX, AVX512, and MPX bits in SIGSTRUCT.xfrms dynamically unless the features are specifically enabled in the manifest via sgx.require_[avx|avx512|mpx]=1 options. If the bits are set in SIGSTRUCT.xfrms but the CPU feature(s) are not available on the platform, the enclave initialization (EINIT) should fail. In addition, the xfrms and xfrmmask fields in the EINITTOKEN must match with SIGSTRUCT. --- .../oldwiki/Graphene-SGX-Manifest-Syntax.md | 12 +++++++ Pal/regression/AvxDisable.c | 9 ++--- Pal/src/host/Linux-SGX/sgx_framework.c | 5 --- .../host/Linux-SGX/signer/pal-sgx-get-token | 33 +++++++++++++++++++ Pal/src/host/Linux-SGX/signer/pal-sgx-sign | 2 +- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/Documentation/oldwiki/Graphene-SGX-Manifest-Syntax.md b/Documentation/oldwiki/Graphene-SGX-Manifest-Syntax.md index 0398ffe8..59d1839b 100644 --- a/Documentation/oldwiki/Graphene-SGX-Manifest-Syntax.md +++ b/Documentation/oldwiki/Graphene-SGX-Manifest-Syntax.md @@ -32,6 +32,18 @@ threads are destroyed). This syntax specifies whether the enclave can be debugged. Set it to 1 for a debug enclave and to 0 for a production enclave. +### Optional CPU features (AVX, AVX512, MPX) + + sgx.require_avx=[1|0] + sgx.require_avx512=[1|0] + sgx.require_mpx=[1|0] + (Default: 0) + +This syntax ensures that the CPU features are available and enabled for the enclave. If the options +are set in the manifest but the features are unavailable on the platform, enclave initialization +should fail. If the options are unset, enclave initialization should succeed even if these features +are unavailable on the platform. + ### ISV Product ID and SVN sgx.isvprodid=[NUM] diff --git a/Pal/regression/AvxDisable.c b/Pal/regression/AvxDisable.c index c90b277f..235762d1 100644 --- a/Pal/regression/AvxDisable.c +++ b/Pal/regression/AvxDisable.c @@ -13,12 +13,7 @@ int main() { __m256 result = _mm256_sub_ps(evens, odds); /* Display the elements of the result vector */ - float f = result[0]; - - PAL_HANDLE file1 = DkStreamOpen("file:avxRes", PAL_ACCESS_RDWR, 0, 0, 0); - if (file1) { - DkStreamWrite(file1, 0, sizeof(f), &f, NULL); - DkObjectClose(file1); - } + pal_printf("Result: %d %d %d %d %d %d %d %d\n", (int)result[0], (int)result[1], (int)result[2], + (int)result[3], (int)result[4], (int)result[5], (int)result[6], (int)result[7]); return 1; } diff --git a/Pal/src/host/Linux-SGX/sgx_framework.c b/Pal/src/host/Linux-SGX/sgx_framework.c index f8108ebc..64fc4ed4 100644 --- a/Pal/src/host/Linux-SGX/sgx_framework.c +++ b/Pal/src/host/Linux-SGX/sgx_framework.c @@ -159,11 +159,6 @@ int create_enclave(sgx_arch_secs_t * secs, secs->misc_select = token->masked_misc_select_le; memcpy(&secs->attributes, &token->body.attributes, sizeof(sgx_attributes_t)); - // Enable AVX and AVX512 - // [2019-09-18] TODO(dep): This alone is not enough to get the fully optional behavior we will want. - // Leave this here for future work in another PR - // secs->attributes.xfrm |= SGX_XFRM_AVX; - /* Do not initialize secs->mr_signer and secs->mr_enclave here as they are * not used by ECREATE to populate the internal SECS. SECS's mr_enclave is * computed dynamically and SECS's mr_signer is populated based on the diff --git a/Pal/src/host/Linux-SGX/signer/pal-sgx-get-token b/Pal/src/host/Linux-SGX/signer/pal-sgx-get-token index c4c6bff9..df758390 100755 --- a/Pal/src/host/Linux-SGX/signer/pal-sgx-get-token +++ b/Pal/src/host/Linux-SGX/signer/pal-sgx-get-token @@ -11,6 +11,38 @@ import aesm_pb2 sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) from generated_offsets import * +def set_optional_sgx_features(attr): + """Set optional SGX features if they are available on this machine.""" + optional_sgx_features = { + SGX_XFRM_AVX: "avx", + SGX_XFRM_AVX512: "avx512f", + SGX_XFRM_MPX: "mpx", + } + + cpu_features = "" + with open("/proc/cpuinfo", "r") as f: + for line in f: + if line.startswith("flags"): + cpu_features = line.split(":")[1].strip().split() + break + else: + raise Exception("Failed to parse CPU flags") + + xfrms = int.from_bytes(attr['xfrms'], byteorder='little') + xfrmmask = int.from_bytes(attr['xfrm_mask'], byteorder='little') + + new_xfrms = 0 + for (bits, feature) in optional_sgx_features.items(): + # Check if SIGSTRUCT allows enabling an optional CPU feature. + # If all the xfrm bits for a feature, after applying xfrmmask, are set in xfrms, + # we can set the remaining bits if the feature is available. + # If the xfrmmask includes all the required xfrm bits, then these bits cannot be + # changed in xfrm (need to stay the same as signed). + if xfrms & (bits & xfrmmask) == (bits & xfrmmask) and feature in cpu_features: + new_xfrms |= xfrms | bits + + attr['xfrms'] = new_xfrms.to_bytes(length=8, byteorder='little') + def read_sigstruct(sig): """Reading Sigstruct.""" @@ -97,6 +129,7 @@ def main(args=None): args = argparser.parse_args(args) attr = read_sigstruct(args.sig.read()) + set_optional_sgx_features(attr) print("Attributes:") print(" mr_enclave: %s" % attr['enclave_hash'].hex()) diff --git a/Pal/src/host/Linux-SGX/signer/pal-sgx-sign b/Pal/src/host/Linux-SGX/signer/pal-sgx-sign index fec0a987..505ee02a 100755 --- a/Pal/src/host/Linux-SGX/signer/pal-sgx-sign +++ b/Pal/src/host/Linux-SGX/signer/pal-sgx-sign @@ -170,7 +170,7 @@ def get_enclave_attributes(manifest): 'debug': 'FLAG_DEBUG', 'require_avx': 'XFRM_AVX', 'require_avx512': 'XFRM_AVX512', - 'enable_mpx': 'XFRM_MPX', + 'require_mpx': 'XFRM_MPX', 'support_exinfo': 'MISC_EXINFO', }