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 cba9238815438ee35e0f92a8c7a71b9528cf15fe Author: cengfeng.lzy <[email protected]> AuthorDate: Wed Mar 30 16:33:51 2022 +0800 [Enc] Substitute /dev/random in enclave Summary: JDK reads two specicial files /dev/random or /dev/urandom to get pseudorandom random number, but they may not be available in the enclave environment. So we substitute the reading with native calls. Test Plan: all tests pass Reviewers: lei.yul, jeffery.wsj, sanhong.lsh Issue: https://aone.alibaba-inc.com/v2/project/1072790/task/41639424 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/8760487 --- build.sh | 21 +--- sdk/enclave/pom.xml | 4 +- .../enclave/EnclaveEntry.java | 6 +- .../enclave/EnclaveOptions.java | 11 ++ .../enclave/c/EnclaveEnvironment.java | 15 +++ .../substitutes/NativePRNGSubstitutions.java | 111 +++++++++++++++++++++ .../services/org.graalvm.options.OptionDescriptors | 1 + .../src/main/resources/native/enc_environment.h | 5 + .../enclave/EnclaveTestHelper.java | 1 + .../enclave/NativeImageTest.java | 2 +- .../enclave/RunWithNativeImageTest.java | 16 +++ .../enclave/testservice/MathService.java | 15 ++- .../enclave/testservice/PointMath.java | 1 + .../test/resources/native/enc_invoke_entry_test.c | 12 +++ tools/cicd/Dockerfile | 2 +- tools/cicd/make.sh | 3 +- 16 files changed, 201 insertions(+), 25 deletions(-) diff --git a/build.sh b/build.sh index c4bf999..daf8dd6 100644 --- a/build.sh +++ b/build.sh @@ -8,22 +8,5 @@ cd "${SHELL_FOLDER}" # workspace dir is the same as build.sh path location. WORKDIR="$PWD" -# The necessary GraalVM jars are compiled from [email protected]:graal/SGXGraalVM.git. -# When the patches are accepted by the community, these jars will be gradually replaced by the official jars. -VERSION="enclave-22.0.0" -mkdir jartmp -pushd jartmp > /dev/null -wget https://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.0.0/graal-sdk-enclave-22.0.0.jar - -mvn install:install-file -Dfile=$GRAALVM_HOME/lib/graal/graal-processor.jar -DgroupId=org.graalvm.compiler -DartifactId=graal-processor -Dversion=$VERSION -Dpackaging=jar -mvn install:install-file -Dfile=graal-sdk-enclave-22.0.0.jar -DgroupId=org.graalvm.sdk -DartifactId=graal-sdk -Dversion=$VERSION -Dpackaging=jar -mvn install:install-file -Dfile=$GRAALVM_HOME/lib/svm/builder/svm.jar -DgroupId=org.graalvm.nativeimage -DartifactId=svm -Dversion=$VERSION -Dpackaging=jar -mvn install:install-file -Dfile=$GRAALVM_HOME/lib/svm/builder/objectfile.jar -DgroupId=org.graalvm.nativeimage -DartifactId=objectfile -Dversion=$VERSION -Dpackaging=jar -mvn install:install-file -Dfile=$GRAALVM_HOME/lib/svm/builder/pointsto.jar -DgroupId=org.graalvm.nativeimage -DartifactId=pointsto -Dversion=$VERSION -Dpackaging=jar -mvn install:install-file -Dfile=$GRAALVM_HOME/lib/svm/builder/native-image-base.jar -DgroupId=org.graalvm.nativeimage -DartifactId=native-image-base -Dversion=$VERSION -Dpackaging=jar - -popd > /dev/null -rm -rf jartmp - -cd "${WORKDIR}"/sdk && mvn clean install -cd "${WORKDIR}"/test && mvn -Pnative -e clean package +cd "${WORKDIR}"/sdk && mvn --settings /root/tools/settings.xml clean install +cd "${WORKDIR}"/test && mvn --settings /root/tools/settings.xml -Pnative -e clean package diff --git a/sdk/enclave/pom.xml b/sdk/enclave/pom.xml index eaf153d..354b440 100644 --- a/sdk/enclave/pom.xml +++ b/sdk/enclave/pom.xml @@ -13,7 +13,7 @@ <name>JavaEnclave-Enclave</name> <url></url> <properties> - <graal.version>enclave-22.0.0</graal.version> + <graal.version>enclave-11-22.0.0-0.1.0</graal.version> <svm.maven.version>0.9.10</svm.maven.version> </properties> <profiles> @@ -124,6 +124,8 @@ <additionalJOption>jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED</additionalJOption> <additionalJOption>--add-exports</additionalJOption> <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> </additionalJOptions> </configuration> <version>3.2.0</version> diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveEntry.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveEntry.java index 04d091c..e75d542 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveEntry.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveEntry.java @@ -15,7 +15,11 @@ import org.graalvm.nativeimage.c.type.CTypeConversion; * This class defines the entry points for native image (shared library) deployed in TEE enclave. */ public class EnclaveEntry { - private static CallBacks callBackMethods; + private static volatile CallBacks callBackMethods; + + public static CallBacks getCallBackMethods() { + return callBackMethods; + } @SuppressWarnings("unused") @CEntryPoint(name = "java_loadservice_invoke") diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveOptions.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveOptions.java new file mode 100644 index 0000000..df82f2f --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveOptions.java @@ -0,0 +1,11 @@ +package com.alibaba.confidentialcomputing.enclave; + +import com.oracle.svm.core.option.HostedOptionKey; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionType; + +public class EnclaveOptions { + @Option(help = "Use native function instead of accessing /dev/random /dev/urandom for getting random number.", type = OptionType.User) +// + public static final HostedOptionKey<Boolean> UseNativeGetRandom = new HostedOptionKey<>(true); +} 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 21a9505..9a5ac14 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 @@ -35,6 +35,7 @@ import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer; import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.c.type.VoidPointer; import org.graalvm.word.PointerBase; import java.io.ByteArrayOutputStream; @@ -112,6 +113,12 @@ public class EnclaveEnvironment { @CField("memcpy_char_pointer") void setMemCpyCCharPointerFunctionPointer(MemCpyCCharPointerFunctionPointer functionPointer); + + @CField("get_random_number") + NativeGetRandomNumberFunctionPointer getRandomNumber(); + + @CField("get_random_number") + NativeGetRandomNumberFunctionPointer setRandomNumber(); } public interface ExceptionHandleFunctionPointer extends CFunctionPointer { @@ -123,4 +130,12 @@ public class EnclaveEnvironment { @InvokeCFunctionPointer CCharPointer invoke(CCharPointer source, int length); } + + /** + * A function pointer points to the native function that returns a pseudorandom number. + */ + public interface NativeGetRandomNumberFunctionPointer extends CFunctionPointer { + @InvokeCFunctionPointer + int invoke(VoidPointer data, long size); + } } diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativePRNGSubstitutions.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativePRNGSubstitutions.java new file mode 100644 index 0000000..90a5feb --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativePRNGSubstitutions.java @@ -0,0 +1,111 @@ +package com.alibaba.confidentialcomputing.enclave.substitutes; + +import com.alibaba.confidentialcomputing.enclave.EnclaveEntry; +import com.alibaba.confidentialcomputing.enclave.EnclaveOptions; +import com.alibaba.confidentialcomputing.enclave.c.EnclaveEnvironment; +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; +import org.graalvm.nativeimage.UnmanagedMemory; +import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.c.type.VoidPointer; + +import java.io.File; +import java.io.InputStream; +import java.util.function.BooleanSupplier; + +/** + * JDK reads random seed from two special files {@code /dev/random} and {@code /dev/urandom} on Linux platform. But they + * are not necessarily existed in the enclave environment. So we need to substitute the methods that replies on them with + * a native function that provides the same functionality. + */ +@SuppressWarnings("unused") +public final class NativePRNGSubstitutions { + + static class NoRandomFileInEnclave implements BooleanSupplier { + + @Override + public boolean getAsBoolean() { + return EnclaveOptions.UseNativeGetRandom.getValue(); + } + } + + @TargetClass(className = "sun.security.provider.NativePRNG", innerClass = "Variant", onlyWith = NoRandomFileInEnclave.class) + static final class Target_sun_security_provider_NativePRNG_Variant { + + } + + @TargetClass(className = "sun.security.provider.NativePRNG", onlyWith = NoRandomFileInEnclave.class) + static final class Target_sun_security_provider_NativePRNG { + @Substitute + private static Target_sun_security_provider_NativePRNG_RandomIO initIO(Target_sun_security_provider_NativePRNG_Variant v) { + return new Target_sun_security_provider_NativePRNG_RandomIO(new File("/dev/random"), null); + } + } + + @TargetClass(className = "sun.security.provider.NativePRNG", innerClass = "RandomIO", onlyWith = NoRandomFileInEnclave.class) + static final class Target_sun_security_provider_NativePRNG_RandomIO { + @Alias + File seedFile; + @Alias + byte[] nextBuffer; + @Alias + int bufferSize = 256; + //Checkstyle: stop + @Alias + private Object LOCK_GET_BYTES; + + @Alias + private Object LOCK_GET_SEED; + + @Alias + private Object LOCK_SET_SEED; + //Checkstyle: resume + + /** + * The original {@code sun.security.provider.NativePRNG.RandomIO#RandomIO(File, File)} + * method initializes field {@code sun.security.provider.NativePRNG.RandomIO#seedIn} + * and field {@code sun.security.provider.NativePRNG.RandomIO#nextIn} to two special files {@code /dev/random} + * and {@code /dev/urandom} respectively. However, these two files are not existed in Enclave + * environment, leading to IOException at native image runtime. So we substitute the original method + * to avoid creating InputStream from them. <p> + * The {@code seedIn} and {@code nextIn} fields are only used as input parameter to call + * {@code sun.security.provider.NativePRNG.RandomIO#readFully(InputStream, byte[])} method + * to get random seeds. So we substitute it with {@link Target_sun_security_provider_NativePRNG_RandomIO#readFully(InputStream, byte[])} + * to call the native method that can do the same functionality. + * + * @param seedFile /dev/random file, won't get InputStream from it now. + * @param nextFile /dev/urandom file, will be ignored in the substitution method. + */ + @Substitute + @TargetElement(name = TargetElement.CONSTRUCTOR_NAME) + Target_sun_security_provider_NativePRNG_RandomIO(File seedFile, File nextFile) { + LOCK_GET_BYTES = new Object(); + LOCK_GET_SEED = new Object(); + LOCK_SET_SEED = new Object(); + this.seedFile = seedFile; + nextBuffer = new byte[bufferSize]; + } + + @Substitute + private static void readFully(InputStream in, byte[] data) { + int len = data.length; + EnclaveEnvironment.NativeGetRandomNumberFunctionPointer nativeGetRandomNumberFunctionPointer = EnclaveEntry.getCallBackMethods().getRandomNumber(); + if (nativeGetRandomNumberFunctionPointer.isNonNull()) { + CCharPointer bytes = UnmanagedMemory.malloc(len); + int ret = nativeGetRandomNumberFunctionPointer.invoke((VoidPointer) bytes, len); + if (ret == 0) { + CTypeConversion.asByteBuffer(bytes, len).get(data); + UnmanagedMemory.free(bytes); + } else { + UnmanagedMemory.free(bytes); + throw new RuntimeException("Fail to call the native random method in Enclave. Error code:" + ret); + } + } else { + throw new RuntimeException("Callback function to oe_random is not set."); + } + } + } +} 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 new file mode 100644 index 0000000..234826c --- /dev/null +++ b/sdk/enclave/src/main/resources/META-INF/services/org.graalvm.options.OptionDescriptors @@ -0,0 +1 @@ +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 e6f1e0c..84abaf2 100644 --- a/sdk/enclave/src/main/resources/native/enc_environment.h +++ b/sdk/enclave/src/main/resources/native/enc_environment.h @@ -14,4 +14,9 @@ typedef struct callback_functions_struct{ void (*exception_handler)(char* err_msg, char* stack_trace, char* exception_name); char* (*memcpy_char_pointer)(char* src, int len); + + /* + * Points to an available pseudorandom number generating function. + */ + int (*get_random_number)(void* data, long size); }callbacks_t; diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/EnclaveTestHelper.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/EnclaveTestHelper.java index c51c90f..76f98cc 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/EnclaveTestHelper.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/EnclaveTestHelper.java @@ -65,6 +65,7 @@ public class EnclaveTestHelper { private static EnclaveInvocationResult callEnclaveJNI(Object input, Function<byte[], byte[]> function) throws IOException, ClassNotFoundException { byte[] data = SerializationHelper.serialize(input); byte[] ret = function.apply(data); + assertNotNull(ret, "The returned value must not be null."); return (EnclaveInvocationResult) SerializationHelper.deserialize(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 a9519f6..0ba5557 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 @@ -166,12 +166,12 @@ public abstract class NativeImageTest implements NativeImageTestable { command.add("--libc=musl"); } command.add("--no-fallback"); - // command.add("-H:OutputRelocatableImage=."); command.add("-H:Path=" + SVM_OUT); command.add("-H:+AllowIncompleteClasspath"); 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"); List<String> extraOptions = extraSVMOptions(); if (extraOptions != null && !extraOptions.isEmpty()) { command.addAll(extraOptions); diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/RunWithNativeImageTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/RunWithNativeImageTest.java index 44ad76e..70e7c63 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/RunWithNativeImageTest.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/RunWithNativeImageTest.java @@ -25,6 +25,7 @@ import static com.alibaba.confidentialcomputing.enclave.EnclaveTestHelper.NUMERI import static com.alibaba.confidentialcomputing.enclave.EnclaveTestHelper.POINT_MATH; import static com.alibaba.confidentialcomputing.enclave.EnclaveTestHelper.POINT_MATH_ADD_PARAM_TYPES; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; public class RunWithNativeImageTest { @@ -139,6 +140,21 @@ public class RunWithNativeImageTest { assertEquals(3, ret.y); } + /** + * Test the {@code getRandomNumber} method actually calls the native method {@code int get_native_random_number(void* data, long size)} + * in {@code enc_invoke_entry_test.c} file. It doesn't return a random value, but a fixed byte array. + */ + @Test + public void testCallNativeGetRandomNumber() { + String identity = loadAndGetService(NUMERIC_MATH); + int size = 32; + byte[] ret = (byte[]) call(identity, NUMERIC_MATH, "getRandomNumber", new String[]{"int"}, new Object[]{size}); + assertNotNull(ret); + for (int i = 0; i < size; i++) { + assertEquals(ret[i], i % 256); + } + } + private static String loadAndGetService(String implementation) { return EnclaveTestHelper.loadAndGetService(MATH_SERVICE, implementation, 3); } diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MathService.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MathService.java index 8df60c8..9dbef51 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MathService.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/MathService.java @@ -2,6 +2,9 @@ package com.alibaba.confidentialcomputing.enclave.testservice; import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + @EnclaveService public interface MathService<T> { T add(T x, T y); @@ -10,7 +13,17 @@ public interface MathService<T> { T div(T x, T y); - default int getConstant(){ + default int getConstant() { return 100; } + + default byte[] getRandomNumber(int size) { + SecureRandom secureRandom = null; + try { + secureRandom = SecureRandom.getInstance("NativePRNG"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return secureRandom.generateSeed(size); + } } diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/PointMath.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/PointMath.java index 0805277..7d4a6c4 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/PointMath.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/PointMath.java @@ -15,4 +15,5 @@ public class PointMath implements MathService<Point>{ public Point div(Point x, Point y) { return new Point(x.x / y.x, x.y / y.y); } + } 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 b564181..7a4df9b 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 @@ -17,6 +17,17 @@ typedef int (*enclave_invoke)(graal_isolate_t* isolate, enc_data_t* input, enc_d return dest; } +/* +* Tested by RunWithNativeImageTest.testCallNativeGetRandomNumber. +*/ +int get_native_random_number(void* data, long size){ + char* tm = (char*)data; + for(int i=0;i<size;i++){ + tm[i] = i%256; + } + return 0; +} + static graal_isolatethread_t *thread = NULL; static graal_isolate_t *isolate = NULL; @@ -29,6 +40,7 @@ jboolean isCopy; callbacks_t callback_methods; callback_methods.memcpy_char_pointer=&memcpy_char_pointer; + callback_methods.get_random_number=&get_native_random_number; callback_methods.exception_handler=NULL; // Must explicitly set enc_data_t ret; diff --git a/tools/cicd/Dockerfile b/tools/cicd/Dockerfile index 94d2af4..b430e9b 100644 --- a/tools/cicd/Dockerfile +++ b/tools/cicd/Dockerfile @@ -8,6 +8,7 @@ ENV DEBIAN_FRONTEND noninteractive ADD ["graalvm-enclave-22.0.0.tar", "/root/tools/"] ADD ["x86_64-linux-musl-native.tgz", "/root/tools/"] ADD ["zlib-1.2.12.tar.gz", "/root/tools/"] +ADD ["settings.xml", "/root/tools/"] ENV GRAALVM_HOME "/root/tools/graalvm-enclave-22.0.0" ENV JAVA_HOME "/root/tools/graalvm-enclave-22.0.0" ENV CC "/root/tools/x86_64-linux-musl-native/bin/gcc" @@ -17,5 +18,4 @@ ENV PATH $PATH:"/root/tools/x86_64-linux-musl-native/bin" RUN apt-get update && \ echo -e 'yes\n' | apt-get install -y maven && \ echo -e 'yes\n' | apt-get install -y build-essential libz-dev zlib1g-dev && \ - echo -e 'yes\n' | apt-get install -y wget && \ cd /root/tools/zlib-1.2.12 && ./configure --prefix=/root/tools/x86_64-linux-musl-native --static && make && make install diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh index 50f9d2f..41535ef 100755 --- a/tools/cicd/make.sh +++ b/tools/cicd/make.sh @@ -1,7 +1,7 @@ #!/bin/bash BUILD_IMAGE=javaenclave_build -BUILD_TAG=v0.1.2 +BUILD_TAG=v0.1.3 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) @@ -16,6 +16,7 @@ if [[ "$(docker images -q ${BUILD_IMAGE}:${BUILD_TAG} 2> /dev/null)" == "" ]]; t wget https://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.0.0/graalvm-enclave-22.0.0.tar wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/x86_64-linux-musl-native.tgz wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/zlib-1.2.12.tar.gz + wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/settings_taobao.xml -O settings.xml docker build -t ${BUILD_IMAGE}:${BUILD_TAG} . rm -f graalvm-enclave-22.0.0.tar rm -f x86_64-linux-musl-native.tgz --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
