This is an automated email from the ASF dual-hosted git repository. shaojunwang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-java-tee-sdk.git
commit 1a0ad59feb80b7aef68ef2fecea6ae95b5a5f51d Author: cengfeng.lzy <[email protected]> AuthorDate: Fri Apr 1 17:13:11 2022 +0800 [Enc] Get memory info in Enclave Summary: Some Enclave SDKs (e.g. OpenEnclave and TEE) environment don't support all POSIX interfaces defiend in unistd.h. Current known unsupported functions are: 1.sysconf(_SC_PHYS_PAGES()) returns -1. 2.sysconf(_SC_PAGESSIZE()) returns -1. 3.sysconf(_SC_PAGE_SISE()) returns -1. We support getting these data from other native mehtods. Test Plan: all tests pass Reviewers: lei.yul, jeffery.wsj, sanhong.lsh Issue: https://aone.alibaba-inc.com/task/41773325 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/8806784 --- sdk/enclave/pom.xml | 7 +++ .../enclave/c/EnclaveEnvironment.java | 11 ++++ .../enclave/system/EnclaveMemoryFeature.java | 33 +++++++++++ .../enclave/system/EnclavePhysicalMemory.java | 36 ++++++++++++ .../system/EnclaveVirtualMemoryProvider.java | 40 +++++++++++++ .../org.graalvm.compiler.options.OptionDescriptors | 1 + .../services/org.graalvm.options.OptionDescriptors | 1 - .../src/main/resources/native/enc_environment.h | 4 ++ .../enclave/ConfigMemTest.java | 66 ++++++++++++++++++++++ .../enclave/NativeImageTest.java | 12 +++- .../enclave/testservice/EnclaveMem.java | 10 ++++ .../enclave/testservice/MemService.java | 8 +++ ...dentialcomputing.enclave.testservice.MemService | 1 + .../test/resources/native/enc_invoke_entry_test.c | 20 +++++++ test/enclave/pom.xml | 7 +-- 15 files changed, 250 insertions(+), 7 deletions(-) diff --git a/sdk/enclave/pom.xml b/sdk/enclave/pom.xml index 354b440..d818052 100644 --- a/sdk/enclave/pom.xml +++ b/sdk/enclave/pom.xml @@ -81,6 +81,8 @@ <arg>jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider=ALL-UNNAMED</arg> <arg>--add-exports</arg> <arg>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</arg> + <arg>--add-exports</arg> + <arg>jdk.internal.vm.compiler/org.graalvm.compiler.word=ALL-UNNAMED</arg> </compilerArgs> <!--OptionProcessor can automatically generate OptionDescriptor classes at javac time--> <annotationProcessorPaths> @@ -126,6 +128,8 @@ <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider=ALL-UNNAMED</additionalJOption> <additionalJOption>--add-exports</additionalJOption> <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</additionalJOption> + <additionalJOption>--add-exports</additionalJOption> + <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.word=ALL-UNNAMED</additionalJOption> </additionalJOptions> </configuration> <version>3.2.0</version> @@ -167,6 +171,9 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> + <configuration> + <reuseForks>false</reuseForks> + </configuration> </plugin> </plugins> </build> diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/c/EnclaveEnvironment.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/c/EnclaveEnvironment.java index 9a5ac14..cef7283 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/c/EnclaveEnvironment.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/c/EnclaveEnvironment.java @@ -30,6 +30,8 @@ import com.oracle.svm.core.c.libc.TemporaryBuildDirectoryProvider; import com.oracle.svm.core.util.VMError; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.CContext; +import org.graalvm.nativeimage.c.function.CFunction; +import org.graalvm.nativeimage.c.function.CFunction.Transition; import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer; import org.graalvm.nativeimage.c.struct.CField; @@ -138,4 +140,13 @@ public class EnclaveEnvironment { @InvokeCFunctionPointer int invoke(VoidPointer data, long size); } + + @CFunction(value = "physical_page_size") + public native static long getPhysicalPageSize(); + + @CFunction(value = "physical_page_number") + public native static long getPhysicalPageNumber(); + + @CFunction(value = "virtual_page_size", transition = Transition.NO_TRANSITION) + public native static long getVirtualPageSize(); } diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMemoryFeature.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMemoryFeature.java new file mode 100644 index 0000000..efc5109 --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMemoryFeature.java @@ -0,0 +1,33 @@ +package com.alibaba.confidentialcomputing.enclave.system; + +import com.alibaba.confidentialcomputing.enclave.c.EnclaveEnvironment; +import com.alibaba.confidentialcomputing.enclave.system.EnclavePhysicalMemory.PhysicalMemorySupportImpl; +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.os.VirtualMemoryProvider; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; + +/** + * Native image queries the memory page size and heap pages number at runtime with {@code sysconf(_SC_PHYS_PAGES)} and + * {@code sysconf(_SC_PAGESIZE)}, just as POSIX defined. However, such operations are not supported by some enclave SDKs, + * such as OE and TEE. + * We define three custom native methods to get the corresponding memory information: {@link EnclaveEnvironment#getPhysicalPageNumber()}, + * {@link EnclaveEnvironment#getPhysicalPageSize()} and {@link EnclaveEnvironment#getVirtualPageSize()}. They should be + * implemented in native code and linked by out framework. See {@code test/resources/native/enc_invoke_entry_test.c} and + * {@code com.alibaba.confidentialcomputing.enclave.NativeImageTest#compileJNILibrary()} for details. + * <p> + * On the other hand, the original queries from sysconf must be invalided. So the option {@code -H:DisableFeatures=com.oracle.svm.core.posix.linux.LinuxPhysicalMemory$PhysicalMemoryFeature} + * must be set. + */ +@AutomaticFeature +public class EnclaveMemoryFeature implements Feature { + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class); + rci.initializeAtBuildTime("com.alibaba.confidentialcomputing.enclave.system.EnclaveVirtualMemoryProvider", "Native Image classes are always initialized at build time"); + ImageSingletons.add(PhysicalMemorySupportImpl.getPhysicalMemorySupportClass(), new PhysicalMemorySupportImpl()); + ImageSingletons.add(VirtualMemoryProvider.class, new EnclaveVirtualMemoryProvider()); + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java new file mode 100644 index 0000000..35521b5 --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java @@ -0,0 +1,36 @@ +package com.alibaba.confidentialcomputing.enclave.system; + +import com.alibaba.confidentialcomputing.enclave.c.EnclaveEnvironment; +import com.oracle.svm.core.heap.PhysicalMemory; +import com.oracle.svm.core.util.VMError; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; + +import java.util.Properties; + +/** + * Physical memory implementation for Enclave environment. The sysconf(_SC_PAGESIZE()) and + * sysconf(_SC_PHYS_PAGES()) might be invalid in SGX based SDK environment, so we read them from + * custom native methods + */ +public class EnclavePhysicalMemory extends PhysicalMemory { + + static class PhysicalMemorySupportImpl implements PhysicalMemorySupport { + @Override + public UnsignedWord size() { + long numberOfPhysicalMemoryPages = EnclaveEnvironment.getPhysicalPageNumber(); + if (numberOfPhysicalMemoryPages < 0) { + throw VMError.shouldNotReachHere("Physical memory size (number of pages) not available"); + } + long sizeOfAPhysicalMemoryPage = EnclaveEnvironment.getPhysicalPageSize(); + if (sizeOfAPhysicalMemoryPage < 0) { + throw VMError.shouldNotReachHere("Physical memory size ( page size ) not available"); + } + return WordFactory.unsigned(numberOfPhysicalMemoryPages).multiply(WordFactory.unsigned(sizeOfAPhysicalMemoryPage)); + } + + public static Class<PhysicalMemorySupport> getPhysicalMemorySupportClass() { + return PhysicalMemorySupport.class; + } + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveVirtualMemoryProvider.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveVirtualMemoryProvider.java new file mode 100644 index 0000000..287db8d --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveVirtualMemoryProvider.java @@ -0,0 +1,40 @@ +package com.alibaba.confidentialcomputing.enclave.system; + +import com.alibaba.confidentialcomputing.enclave.c.EnclaveEnvironment; +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.CGlobalData; +import com.oracle.svm.core.c.CGlobalDataFactory; +import com.oracle.svm.core.posix.PosixVirtualMemoryProvider; +import com.oracle.svm.core.util.VMError; +import org.graalvm.compiler.word.Word; +import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; + +/** + * Virtual memory implementation for Enclave environment. The {@code sysconf(_SC_PAGE_SIZE())} might be + * invalid in TEE and OE SDK environment, so we read it from a custom native method. + */ +public class EnclaveVirtualMemoryProvider extends PosixVirtualMemoryProvider { + private static final CGlobalData<WordPointer> CACHED_PAGE_SIZE = CGlobalDataFactory.createWord(); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static UnsignedWord getVPageSize() { + Word value = CACHED_PAGE_SIZE.get().read(); + if (value.equal(WordFactory.zero())) { + long queried = EnclaveEnvironment.getVirtualPageSize(); + if (queried == -1L) { + throw VMError.shouldNotReachHere("Virtual memory page size (_SC_PAGE_SIZE) not available"); + } + value = WordFactory.unsigned(queried); + CACHED_PAGE_SIZE.get().write(value); + } + return value; + } + + @Override + @Uninterruptible(reason = "May be called from uninterruptible code.", mayBeInlined = true) + public UnsignedWord getGranularity() { + return getVPageSize(); + } +} diff --git a/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.compiler.options.OptionDescriptors b/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.compiler.options.OptionDescriptors new file mode 100644 index 0000000..c5909f0 --- /dev/null +++ b/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.compiler.options.OptionDescriptors @@ -0,0 +1 @@ +com.alibaba.confidentialcomputing.enclave.EnclaveOptions_OptionDescriptors diff --git a/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.options.OptionDescriptors b/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.options.OptionDescriptors deleted file mode 100644 index 234826c..0000000 --- a/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.options.OptionDescriptors +++ /dev/null @@ -1 +0,0 @@ -com.alibaba.confidentialcomputing.enclave.EnclaveRandomFeature_OptionDescriptors \ No newline at end of file diff --git a/sdk/enclave/src/main/resources/native/enc_environment.h b/sdk/enclave/src/main/resources/native/enc_environment.h index 84abaf2..f7fae35 100644 --- a/sdk/enclave/src/main/resources/native/enc_environment.h +++ b/sdk/enclave/src/main/resources/native/enc_environment.h @@ -20,3 +20,7 @@ typedef struct callback_functions_struct{ */ int (*get_random_number)(void* data, long size); }callbacks_t; + +long physical_page_size(); +long physical_page_number(); +long virtual_page_size(); diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ConfigMemTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ConfigMemTest.java new file mode 100644 index 0000000..32a781e --- /dev/null +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ConfigMemTest.java @@ -0,0 +1,66 @@ +package com.alibaba.confidentialcomputing.enclave; + +import com.alibaba.confidentialcomputing.enclave.testservice.EnclaveMem; +import com.alibaba.confidentialcomputing.enclave.testservice.MemService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ConfigMemTest { + + @TestTarget(ConfigMemTest.class) + static class MemConfigPreparation extends NativeImageTest { + + @Override + public SVMCompileElements specifyTestClasses() { + SVMCompileElements ret = new SVMCompileElements(); + // Specify the service file + ret.addServices("META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.MemService"); + + // Specify the classes need to be statically compiled into native image for this test + ret.addClasses( + MemService.class, EnclaveMem.class + ); + + return ret; + } + + @Override + protected Collection<String> addMacros(){ + return List.of("-DPAGE_SIZE=2048", + "-DHEAP_PAGES=24000"); + } + } + + private static final String MEM_SERVICE = "com.alibaba.confidentialcomputing.enclave.testservice.MemService"; + private static final String ENC_MEM = "com.alibaba.confidentialcomputing.enclave.testservice.EnclaveMem"; + + @BeforeAll + public static void prepareLibraries() { + new MemConfigPreparation().prepareNativeLibraries(); + } + + @BeforeEach + public void setup() { + EnclaveTestHelper.createIsolate(); + } + + @AfterEach + public void teardown() { + EnclaveTestHelper.destroyIsolate(); + } + + @Test + public void test() { + String id = EnclaveTestHelper.loadAndGetService(MEM_SERVICE, ENC_MEM, 1); + long ret = (Long)EnclaveTestHelper.call(id, MEM_SERVICE, ENC_MEM, "getSize", EnclaveTestHelper.EMPTY_STRING_ARRAY, EnclaveTestHelper.EMPTY_OBJECT_ARRAY); + assertEquals(49152000, ret); + } +} diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java index 0ba5557..43e5e37 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java @@ -12,6 +12,8 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; public abstract class NativeImageTest implements NativeImageTestable { @@ -171,7 +173,8 @@ public abstract class NativeImageTest implements NativeImageTestable { command.add("-H:+ReportExceptionStackTraces"); command.add("-H:Name=lib" + SVM_ENCLAVE_LIB); command.add("-H:-DeleteLocalSymbols"); - command.add("-H:DisableFeatures=com.oracle.svm.core.posix.NativeSecureRandomFilesCloser"); + command.add("-H:DisableFeatures=com.oracle.svm.core.posix.NativeSecureRandomFilesCloser," + + "com.oracle.svm.core.posix.linux.LinuxPhysicalMemory$PhysicalMemoryFeature"); List<String> extraOptions = extraSVMOptions(); if (extraOptions != null && !extraOptions.isEmpty()) { command.addAll(extraOptions); @@ -183,7 +186,7 @@ public abstract class NativeImageTest implements NativeImageTestable { System.out.println("###Prepare JNI library ...###"); List<Path> requiredFilePaths = new ArrayList<>(); requiredFilePaths.add(testClassesDir.resolve("native/com_alibaba_confidentialcomputing_enclave_EnclaveTestHelper.h")); - requiredFilePaths.add(testClassesDir.resolve("native/enc_invoke_entry_test.c")); + requiredFilePaths.add(testClassesDir.resolve("native/" + ENC_INVOKE_ENTRY_TEST_C)); requiredFilePaths.add(svmOutputDir.resolve("lib" + SVM_ENCLAVE_LIB + ".h")); requiredFilePaths.add(svmOutputDir.resolve("graal_isolate.h")); requiredFilePaths.add(svmOutputDir.resolve("enc_environment.h")); @@ -200,9 +203,14 @@ public abstract class NativeImageTest implements NativeImageTestable { } else { prepareDynamicLinkingCommand(command); } + command.addAll(addMacros()); executeNewProcess(command, workingDir); } + protected Collection<String> addMacros(){ + return Collections.EMPTY_LIST; + } + private void prepareStaticLinkingCommand(List<String> command) { Path graalvmHome = GRAALVM_HOME.toAbsolutePath(); command.add("gcc"); diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EnclaveMem.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EnclaveMem.java new file mode 100644 index 0000000..778e9f6 --- /dev/null +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EnclaveMem.java @@ -0,0 +1,10 @@ +package com.alibaba.confidentialcomputing.enclave.testservice; + +import com.oracle.svm.core.heap.PhysicalMemory; + +public class EnclaveMem implements MemService{ + @Override + public long getSize() { + return PhysicalMemory.size().rawValue(); + } +} diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MemService.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MemService.java new file mode 100644 index 0000000..784f3fb --- /dev/null +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MemService.java @@ -0,0 +1,8 @@ +package com.alibaba.confidentialcomputing.enclave.testservice; + +import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; + +@EnclaveService +public interface MemService { + long getSize(); +} diff --git a/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.MemService b/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.MemService new file mode 100644 index 0000000..b59e2ee --- /dev/null +++ b/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.MemService @@ -0,0 +1 @@ +com.alibaba.confidentialcomputing.enclave.testservice.EnclaveMem \ No newline at end of file diff --git a/sdk/enclave/src/test/resources/native/enc_invoke_entry_test.c b/sdk/enclave/src/test/resources/native/enc_invoke_entry_test.c index 7a4df9b..840a3bc 100644 --- a/sdk/enclave/src/test/resources/native/enc_invoke_entry_test.c +++ b/sdk/enclave/src/test/resources/native/enc_invoke_entry_test.c @@ -10,6 +10,26 @@ typedef int (*enclave_invoke)(graal_isolate_t* isolate, enc_data_t* input, enc_data_t* result, callbacks_t* callBacks); +long physical_page_size(){ +#ifdef PAGE_SIZE + return PAGE_SIZE; +#else + return 4096; +#endif +} + +long physical_page_number(){ +#ifdef HEAP_PAGES + return HEAP_PAGES; +#else + return 24576; +#endif +} + +long virtual_page_size(){ + return 4096; +} + char* memcpy_char_pointer(char* src, int len){ int size = sizeof(char); char *dest = (char*)malloc(len*size); diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml index 63114bc..0cee904 100644 --- a/test/enclave/pom.xml +++ b/test/enclave/pom.xml @@ -34,7 +34,7 @@ <configuration> <buildArgs> <buildArg>--no-fallback</buildArg> - <buildArg>-H:+RunInEnclave</buildArg> + <buildArg>-H:DisableFeatures=com.oracle.svm.core.posix.NativeSecureRandomFilesCloser,com.alibaba.confidentialcomputing.enclave.system.EnclaveMemoryFeature</buildArg> </buildArgs> </configuration> <phase>test</phase> @@ -50,9 +50,8 @@ <buildArg>--shared</buildArg> <buildArg>--no-fallback</buildArg> <buildArg>--allow-incomplete-classpath</buildArg> - <buildArg>-H:OutputRelocatableImage=.</buildArg> - <buildArg>-H:+RunInEnclave</buildArg> <buildArg>-H:Path=svm-output</buildArg> + <buildArg>-H:DisableFeatures=com.oracle.svm.core.posix.NativeSecureRandomFilesCloser,com.alibaba.confidentialcomputing.enclave.system.EnclaveMemoryFeature</buildArg> <buildArg>-H:ReflectionConfigurationFiles=${project.basedir}/target/native/agent-output/test/reflect-config.json</buildArg> </buildArgs> </configuration> @@ -143,4 +142,4 @@ <scope>test</scope> </dependency> </dependencies> -</project> \ No newline at end of file +</project> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
