diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java index c87839f82a63..83b76ba57c94 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -672,6 +672,7 @@ public final class Builder { private Map arguments; private Predicate hostClassFilter; private Boolean allowHostAccess; + private Boolean allowNativeAccess; private Boolean allowCreateThread; private boolean allowAllAccess; private Boolean allowIO; @@ -750,6 +751,16 @@ public Builder allowHostAccess(boolean enabled) { return this; } + /** + * Allows guest languages to access the native interface. + * + * @since 1.0 + */ + public Builder allowNativeAccess(boolean enabled) { + this.allowNativeAccess = enabled; + return this; + } + /** * If true allows guest languages to create new threads. Default is * false. If {@link #allowAllAccess(boolean) all access} is set to @@ -932,6 +943,9 @@ public Context build() { if (allowHostAccess == null) { allowHostAccess = allowAllAccess; } + if (allowNativeAccess == null) { + allowNativeAccess = allowAllAccess; + } if (allowCreateThread == null) { allowCreateThread = allowAllAccess; } @@ -958,11 +972,11 @@ public Context build() { } engineBuilder.setBoundEngine(true); engine = engineBuilder.build(); - return engine.impl.createContext(null, null, null, allowHostAccess, allowCreateThread, allowIO, + return engine.impl.createContext(null, null, null, allowHostAccess, allowNativeAccess, allowCreateThread, allowIO, allowHostClassLoading, hostClassFilter, Collections.emptyMap(), arguments == null ? Collections.emptyMap() : arguments, onlyLanguages, customFileSystem); } else { - return engine.impl.createContext(out, err, in, allowHostAccess, allowCreateThread, allowIO, + return engine.impl.createContext(out, err, in, allowHostAccess, allowNativeAccess, allowCreateThread, allowIO, allowHostClassLoading, hostClassFilter, options == null ? Collections.emptyMap() : options, arguments == null ? Collections.emptyMap() : arguments, onlyLanguages, customFileSystem); } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java index 7d2a8a4800b9..312649031fd9 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,7 +260,7 @@ protected AbstractEngineImpl(AbstractPolyglotImpl impl) { public abstract OptionDescriptors getOptions(); - public abstract Context createContext(OutputStream out, OutputStream err, InputStream in, boolean allowHostAccess, + public abstract Context createContext(OutputStream out, OutputStream err, InputStream in, boolean allowHostAccess, boolean allowNativeAccess, boolean allowCreateThread, boolean allowHostIO, boolean allowHostClassLoading, Predicate classFilter, Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem); diff --git a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotContextImpl.java index 83670c5c00ca..20c31499a0bb 100644 --- a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,6 +109,7 @@ static final class SingleContextState { Predicate classFilter; // effectively final boolean hostAccessAllowed; // effectively final boolean hostClassLoadingAllowed; // effectively final + boolean nativeAccessAllowed; // effectively final @CompilationFinal boolean createThreadAllowed; // map from class to language index @@ -138,6 +139,7 @@ private PolyglotContextImpl() { OutputStream err, InputStream in, boolean hostAccessAllowed, + boolean nativeAccessAllowed, boolean createThreadAllowed, boolean hostClassLoadingAllowed, Predicate classFilter, @@ -149,7 +151,7 @@ private PolyglotContextImpl() { this.parent = null; this.engine = engine; this.fileSystem = fileSystem; - patchInstance(out, err, in, hostAccessAllowed, createThreadAllowed, hostClassLoadingAllowed, classFilter, applicationArguments, allowedPublicLanguages); + patchInstance(out, err, in, hostAccessAllowed, nativeAccessAllowed, createThreadAllowed, hostClassLoadingAllowed, classFilter, applicationArguments, allowedPublicLanguages); Collection languages = engine.idToLanguage.values(); this.contexts = new PolyglotLanguageContext[languages.size() + 1]; PolyglotLanguageContext hostContext = new PolyglotLanguageContext(this, engine.hostLanguage, null, applicationArguments.get(PolyglotEngineImpl.HOST_LANGUAGE_ID), @@ -218,6 +220,7 @@ static void disposeStaticContext(PolyglotContextImpl context) { this.parent = creator.context; this.hostAccessAllowed = parent.hostAccessAllowed; this.hostClassLoadingAllowed = parent.hostClassLoadingAllowed; + this.nativeAccessAllowed = parent.nativeAccessAllowed; this.createThreadAllowed = parent.createThreadAllowed; this.applicationArguments = parent.applicationArguments; this.classFilter = parent.classFilter; @@ -993,10 +996,10 @@ PolyglotThreadInfo getCurrentThreadInfo() { } boolean patch(OutputStream newOut, OutputStream newErr, InputStream newIn, boolean newHostAccessAllowed, - boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate newClassFilter, + boolean newNativeAccessAllowed, boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate newClassFilter, Map newOptions, Map newApplicationArguments, Set newAllowedPublicLanguages, FileSystem newFileSystem) { CompilerAsserts.neverPartOfCompilation(); - patchInstance(newOut, newErr, newIn, newHostAccessAllowed, newCreateThreadAllowed, newHostClassLoadingAllowed, newClassFilter, newApplicationArguments, newAllowedPublicLanguages); + patchInstance(newOut, newErr, newIn, newHostAccessAllowed, newNativeAccessAllowed, newCreateThreadAllowed, newHostClassLoadingAllowed, newClassFilter, newApplicationArguments, newAllowedPublicLanguages); ((FileSystems.PreInitializeContextFileSystem) fileSystem).patchDelegate(newFileSystem); final Map> optionsByLanguage = new HashMap<>(); for (String optionKey : newOptions.keySet()) { @@ -1024,9 +1027,10 @@ boolean patch(OutputStream newOut, OutputStream newErr, InputStream newIn, boole } private void patchInstance(OutputStream newOut, OutputStream newErr, InputStream newIn, boolean newHostAccessAllowed, - boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate newClassFilter, + boolean newNativeAccessAllowed, boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate newClassFilter, Map newApplicationArguments, Set newAllowedPublicLanguages) { this.hostAccessAllowed = newHostAccessAllowed; + this.nativeAccessAllowed = newNativeAccessAllowed; this.createThreadAllowed = newCreateThreadAllowed; this.hostClassLoadingAllowed = newHostClassLoadingAllowed; this.applicationArguments = newApplicationArguments; diff --git a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java index 281e9ccc596c..f1e5d8bf70ed 100644 --- a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java +++ b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1013,6 +1013,11 @@ public boolean isHostAccessAllowed(Object vmObject, Env env) { return false; } + @Override + public boolean isNativeAccessAllowed(Object vmObject, Env env) { + return false; + } + @Override public Object lookupHostSymbol(Object vmObject, Env env, String symbolName) { return null; diff --git a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngineImpl.java index d1b322c4203b..0065cd5036b9 100644 --- a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -874,7 +874,7 @@ public String getImplementationName() { @Override @SuppressWarnings({"all"}) public synchronized Context createContext(OutputStream out, OutputStream err, InputStream in, boolean allowHostAccess, - boolean allowCreateThread, boolean allowHostIO, boolean allowHostClassLoading, + boolean allowNativeAccess, boolean allowCreateThread, boolean allowHostIO, boolean allowHostClassLoading, Predicate classFilter, Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem) { checkState(); if (boundEngine && preInitializedContext == null && !contexts.isEmpty()) { @@ -899,7 +899,7 @@ public synchronized Context createContext(OutputStream out, OutputStream err, In if (contextImpl != null) { boolean patchResult; try { - patchResult = contextImpl.patch(out, err, in, allowHostAccess, allowCreateThread, allowHostClassLoading, classFilter, options, arguments, allowedLanguages, fs); + patchResult = contextImpl.patch(out, err, in, allowHostAccess, allowNativeAccess, allowCreateThread, allowHostClassLoading, classFilter, options, arguments, allowedLanguages, fs); } catch (RuntimeException re) { contextImpl.closeImpl(false, false); PolyglotContextImpl.disposeStaticContext(null); @@ -912,7 +912,7 @@ public synchronized Context createContext(OutputStream out, OutputStream err, In } } if (contextImpl == null) { - contextImpl = new PolyglotContextImpl(this, out, err, in, allowHostAccess, allowCreateThread, allowHostClassLoading, classFilter, options, arguments, allowedLanguages, fs); + contextImpl = new PolyglotContextImpl(this, out, err, in, allowHostAccess, allowNativeAccess, allowCreateThread, allowHostClassLoading, classFilter, options, arguments, allowedLanguages, fs); addContext(contextImpl); } Context api = impl.getAPIAccess().newContext(contextImpl); diff --git a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotImpl.java b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotImpl.java index e0d85ae8be9d..1e1aeaa966ef 100644 --- a/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotImpl.java +++ b/truffle/src/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -551,6 +551,12 @@ public boolean isHostAccessAllowed(Object vmObject, Env env) { return context.context.hostAccessAllowed; } + @Override + public boolean isNativeAccessAllowed(Object vmObject, Env env) { + PolyglotLanguageContext context = (PolyglotLanguageContext) vmObject; + return context.context.nativeAccessAllowed; + } + @Override @TruffleBoundary public void exportSymbol(Object vmObject, String symbolName, Object value) { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 13cd2c570ac8..063d100bc766 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1520,6 +1520,17 @@ public Throwable asHostException(Throwable exception) { return AccessAPI.engineAccess().asHostException(exception); } + /** + * Returns true if access to native code is generally allowed. If this method + * returns false then loading native libraries with the Truffle NFI will fail. + * + * @since 1.0 + */ + @TruffleBoundary + public boolean isNativeAccessAllowed() { + return AccessAPI.engineAccess().isNativeAccessAllowed(vmObject, this); + } + /** * Allows it to be determined if this {@link org.graalvm.polyglot.Context} can execute code * written in a language with a given MIME type. diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index b8a42897227d..7739e53c39bf 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -227,6 +227,8 @@ public final void detachOutputConsumer(DispatchOutputStream dos, OutputStream ou public abstract boolean isHostAccessAllowed(Object vmObject, Env env); + public abstract boolean isNativeAccessAllowed(Object vmObject, Env env); + public abstract Object createInternalContext(Object vmObject, Map config, TruffleContext spiContext); public abstract void initializeInternalContext(Object vmObject, Object contextImpl); diff --git a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java index e81742050efa..f25b271772c0 100644 --- a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java +++ b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java @@ -84,6 +84,10 @@ private static class LoadLibraryNode extends RootNode { @Override public Object execute(VirtualFrame frame) { + if (!ctxRef.get().env.isNativeAccessAllowed()) { + CompilerDirectives.transferToInterpreter(); + throw new UnsatisfiedLinkError("Access to native code is not allowed."); + } if (cached == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); cached = ctxRef.get().loadLibrary(name, flags); @@ -94,12 +98,19 @@ public Object execute(VirtualFrame frame) { private static class GetDefaultLibraryNode extends RootNode { - GetDefaultLibraryNode() { - super(null); + private final ContextReference ctxRef; + + GetDefaultLibraryNode(NFILanguageImpl language) { + super(language); + this.ctxRef = language.getContextReference(); } @Override public Object execute(VirtualFrame frame) { + if (!ctxRef.get().env.isNativeAccessAllowed()) { + CompilerDirectives.transferToInterpreter(); + throw new UnsatisfiedLinkError("Access to native code is not allowed."); + } return LibFFILibrary.createDefault(); } } @@ -112,7 +123,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { NFIContext ctx = getContextReference().get(); if (descriptor.isDefaultLibrary()) { - root = new GetDefaultLibraryNode(); + root = new GetDefaultLibraryNode(this); } else { int flags = 0; boolean lazyOrNow = false;