Skip to content

Commit

Permalink
Introduce permission for accessing native code.
Browse files Browse the repository at this point in the history
  • Loading branch information
rschatz authored and chumer committed Apr 8, 2018
1 parent 6107085 commit 8ff52d6
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 21 deletions.
20 changes: 17 additions & 3 deletions sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -672,6 +672,7 @@ public final class Builder {
private Map<String, String[]> arguments;
private Predicate<String> hostClassFilter;
private Boolean allowHostAccess;
private Boolean allowNativeAccess;
private Boolean allowCreateThread;
private boolean allowAllAccess;
private Boolean allowIO;
Expand Down Expand Up @@ -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 <code>true</code> allows guest languages to create new threads. Default is
* <code>false</code>. If {@link #allowAllAccess(boolean) all access} is set to
Expand Down Expand Up @@ -932,6 +943,9 @@ public Context build() {
if (allowHostAccess == null) {
allowHostAccess = allowAllAccess;
}
if (allowNativeAccess == null) {
allowNativeAccess = allowAllAccess;
}
if (allowCreateThread == null) {
allowCreateThread = allowAllAccess;
}
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<String> classFilter, Map<String, String> options, Map<String, String[]> arguments,
String[] onlyLanguages, FileSystem fileSystem);

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -109,6 +109,7 @@ static final class SingleContextState {
Predicate<String> classFilter; // effectively final
boolean hostAccessAllowed; // effectively final
boolean hostClassLoadingAllowed; // effectively final
boolean nativeAccessAllowed; // effectively final
@CompilationFinal boolean createThreadAllowed;

// map from class to language index
Expand Down Expand Up @@ -138,6 +139,7 @@ private PolyglotContextImpl() {
OutputStream err,
InputStream in,
boolean hostAccessAllowed,
boolean nativeAccessAllowed,
boolean createThreadAllowed,
boolean hostClassLoadingAllowed,
Predicate<String> classFilter,
Expand All @@ -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<PolyglotLanguage> 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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -993,10 +996,10 @@ PolyglotThreadInfo getCurrentThreadInfo() {
}

boolean patch(OutputStream newOut, OutputStream newErr, InputStream newIn, boolean newHostAccessAllowed,
boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate<String> newClassFilter,
boolean newNativeAccessAllowed, boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate<String> newClassFilter,
Map<String, String> newOptions, Map<String, String[]> newApplicationArguments, Set<String> 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<String, Map<String, String>> optionsByLanguage = new HashMap<>();
for (String optionKey : newOptions.keySet()) {
Expand Down Expand Up @@ -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<String> newClassFilter,
boolean newNativeAccessAllowed, boolean newCreateThreadAllowed, boolean newHostClassLoadingAllowed, Predicate<String> newClassFilter,
Map<String, String[]> newApplicationArguments, Set<String> newAllowedPublicLanguages) {
this.hostAccessAllowed = newHostAccessAllowed;
this.nativeAccessAllowed = newNativeAccessAllowed;
this.createThreadAllowed = newCreateThreadAllowed;
this.hostClassLoadingAllowed = newHostClassLoadingAllowed;
this.applicationArguments = newApplicationArguments;
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<String> classFilter, Map<String, String> options, Map<String, String[]> arguments, String[] onlyLanguages, FileSystem fileSystem) {
checkState();
if (boundEngine && preInitializedContext == null && !contexts.isEmpty()) {
Expand All @@ -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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -1520,6 +1520,17 @@ public Throwable asHostException(Throwable exception) {
return AccessAPI.engineAccess().asHostException(exception);
}

/**
* Returns <code>true</code> if access to native code is generally allowed. If this method
* returns <code>false</code> 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<String, Object> config, TruffleContext spiContext);

public abstract void initializeInternalContext(Object vmObject, Object contextImpl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -94,12 +98,19 @@ public Object execute(VirtualFrame frame) {

private static class GetDefaultLibraryNode extends RootNode {

GetDefaultLibraryNode() {
super(null);
private final ContextReference<NFIContext> 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();
}
}
Expand All @@ -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;
Expand Down

0 comments on commit 8ff52d6

Please sign in to comment.