Skip to content

Commit

Permalink
Fix review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
lazar-mitrovic committed Oct 29, 2021
1 parent 74ff3eb commit 2aee05e
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@
import java.util.Set;
import java.util.StringJoiner;

import com.oracle.svm.core.BaseProcessPropertiesSupport;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.ProcessProperties;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.impl.ProcessPropertiesSupport;
import org.graalvm.util.DirectAnnotationAccess;

import com.oracle.svm.core.RuntimeAssertionsSupport;
Expand Down Expand Up @@ -327,7 +329,6 @@ public void setModule(Object module) {
this.module = module;
}

static final boolean IS_EXECUTABLE = ImageInfo.isExecutable();
/**
* Final fields in substituted classes are treated as implicitly RecomputeFieldValue even when
* not annotated with @RecomputeFieldValue. Their name must not match a field in the original
Expand All @@ -336,21 +337,19 @@ public void setModule(Object module) {
static final LazyFinalReference<java.security.ProtectionDomain> allPermDomainReference = new LazyFinalReference<>(() -> {
java.security.Permissions perms = new java.security.Permissions();
perms.add(SecurityConstants.ALL_PERMISSION);
URL url = null;
CodeSource cs = null;

if (IS_EXECUTABLE) {
if (ImageSingletons.lookup(ProcessPropertiesSupport.class) instanceof BaseProcessPropertiesSupport) {
// Try to use executable image's name as code source for the class.
// The file location can be used by Java code to determine its location on disk, similar
// to argv[0].
try {
url = new File(ProcessProperties.getExecutableName()).toURI().toURL();
cs = new CodeSource(new File(ProcessProperties.getExecutableName()).toURI().toURL(), (Certificate[]) null);
} catch (MalformedURLException e) {
// This should not really happen; the file is cannonicalized, absolute, so it should
// always have file:// URL.
}
}

CodeSource cs = new CodeSource(url, (Certificate[]) null);
return new java.security.ProtectionDomain(cs, perms);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,70 +35,90 @@
import java.util.ArrayDeque;
import java.util.Objects;

@InternalVMMethod
@SuppressWarnings({"unused"})
public class AccessControllerUtil {
/**
* Stack for storing AccessControlContexts. Used in conjunction with
* {@code StackAccessControlContextVisitor}.
*/
class PrivilegedStack {

public static final AccessControlContext DISALLOWED_CONTEXT_MARKER;
public static class StackElement {
protected AccessControlContext context;
protected Class<?> caller;

static {
try {
DISALLOWED_CONTEXT_MARKER = ReflectionUtil.lookupConstructor(AccessControlContext.class, ProtectionDomain[].class, boolean.class).newInstance(new ProtectionDomain[0], true);
} catch (ReflectiveOperationException ex) {
throw VMError.shouldNotReachHere(ex);
StackElement(AccessControlContext context, Class<?> caller) {
this.context = context;
this.caller = caller;
}

public AccessControlContext getContext() {
return context;
}

public Class<?> getCaller() {
return caller;
}
}

public static class PrivilegedStack {
/* Local AccessControlContext stack */
private static final FastThreadLocalObject<ArrayDeque<StackElement>> stack;

public static class StackElement {
protected AccessControlContext context;
protected Class<?> caller;
static {

StackElement(AccessControlContext context, Class<?> caller) {
this.context = context;
this.caller = caller;
}
@SuppressWarnings("unchecked")
Class<ArrayDeque<StackElement>> cls = (Class<ArrayDeque<StackElement>>) (Object) ArrayDeque.class;
stack = FastThreadLocalFactory.createObject(cls, "AccessControlContextStack");
}

public AccessControlContext getContext() {
return context;
}
@SuppressWarnings("unchecked")
private static ArrayDeque<StackElement> getStack() {
ensureInitialized();
return stack.get();
}

public Class<?> getCaller() {
return caller;
}
private static void ensureInitialized() {
if (stack.get() == null) {
ArrayDeque<StackElement> tmp = new ArrayDeque<>();
stack.set(tmp);
}
}

@SuppressWarnings("rawtypes") private static final FastThreadLocalObject<ArrayDeque> stack = FastThreadLocalFactory.createObject(ArrayDeque.class, "AccessControlContextStack");
public static void push(AccessControlContext context, Class<?> caller) {
getStack().push(new StackElement(context, caller));
}

@SuppressWarnings("unchecked")
private static ArrayDeque<StackElement> getStack() {
ArrayDeque<StackElement> tmp = stack.get();
if (tmp == null) {
tmp = new ArrayDeque<>();
stack.set(tmp);
}
return tmp;
}
public static void pop() {
getStack().pop();
}

public static void push(AccessControlContext context, Class<?> caller) {
getStack().push(new StackElement(context, caller));
}
public static AccessControlContext peekContext() {
return Objects.requireNonNull(getStack().peek()).getContext();
}

public static void pop() {
getStack().pop();
}
public static Class<?> peekCaller() {
return Objects.requireNonNull(getStack().peek()).getCaller();
}

public static AccessControlContext peekContext() {
return Objects.requireNonNull(getStack().peek()).getContext();
}
public static int length() {
return getStack().size();
}
}

public static Class<?> peekCaller() {
return Objects.requireNonNull(getStack().peek()).getCaller();
}
@InternalVMMethod
@SuppressWarnings({"unused"})
public class AccessControllerUtil {

/**
* Instance that is used to mark contexts that were disallowed in
* {@code AccessControlContextReplacerFeature.replaceAccessControlContext()} If this marker is
* passed to {@code AccessController.doPrivileged()} a runtime error will be thrown.
*/
public static final AccessControlContext DISALLOWED_CONTEXT_MARKER;

public static int length() {
return getStack().size();
static {
try {
DISALLOWED_CONTEXT_MARKER = ReflectionUtil.lookupConstructor(AccessControlContext.class, ProtectionDomain[].class, boolean.class).newInstance(new ProtectionDomain[0], true);
} catch (ReflectiveOperationException ex) {
throw VMError.shouldNotReachHere(ex);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,24 @@
*/
package com.oracle.svm.core.jdk;

import static com.oracle.svm.core.snippets.KnownIntrinsics.readCallerStackPointer;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.NeverInline;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
import com.oracle.svm.core.graal.snippets.CEntryPointSnippets;
import com.oracle.svm.core.thread.Target_java_lang_Thread;
import com.oracle.svm.core.util.VMError;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;

import java.net.URL;
import java.security.AccessControlContext;
Expand All @@ -43,24 +60,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.NeverInline;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
import com.oracle.svm.core.thread.Target_java_lang_Thread;
import com.oracle.svm.core.util.VMError;
import static com.oracle.svm.core.snippets.KnownIntrinsics.readCallerStackPointer;

// Checkstyle: stop
import sun.security.jca.ProviderList;
Expand Down Expand Up @@ -108,7 +108,19 @@ static <T> T doPrivileged(PrivilegedExceptionAction<T> action, AccessControlCont
}

@Substitute
@SuppressWarnings("deprecation")
static AccessControlContext getStackAccessControlContext() {
if (!CEntryPointSnippets.isIsolateInitialized()) {
/*
* If isolate still isn't initialized, we can assume that we are so early in the JDK
* initialization that any attempt at stalk walk will fail as not even the basic
* PrintWriter/Logging is available yet. This manifested when
* UseDedicatedVMOperationThread hosted option was set, triggering a runtime crash.
*/
Permissions perms = new Permissions();
perms.add(SecurityConstants.ALL_PERMISSION);
return new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, perms)});
}
return StackAccessControlContextVisitor.getFromStack();
}

Expand All @@ -118,47 +130,47 @@ static AccessControlContext getInheritedAccessControlContext() {
}

@Substitute
@TargetElement(onlyWith = JDK14OrLater.class)
@TargetElement(onlyWith = JDK17OrLater.class)
private static ProtectionDomain getProtectionDomain(final Class<?> caller) {
return caller.getProtectionDomain();
}

@Substitute
@TargetElement(onlyWith = JDK14OrLater.class)
@TargetElement(onlyWith = JDK17OrLater.class)
static <T> T executePrivileged(PrivilegedExceptionAction<T> action, AccessControlContext context, Class<?> caller) throws Throwable {
if (action == null) {
throw new NullPointerException("Null action");
}

AccessControllerUtil.PrivilegedStack.push(context, caller);
PrivilegedStack.push(context, caller);
try {
return action.run();
} catch (Exception e) {
throw AccessControllerUtil.wrapCheckedException(e);
} finally {
AccessControllerUtil.PrivilegedStack.pop();
PrivilegedStack.pop();
}
}

@Substitute
@TargetElement(onlyWith = JDK14OrLater.class)
@TargetElement(onlyWith = JDK17OrLater.class)
static <T> T executePrivileged(PrivilegedAction<T> action, AccessControlContext context, Class<?> caller) throws Throwable {
if (action == null) {
throw new NullPointerException("Null action");
}

AccessControllerUtil.PrivilegedStack.push(context, caller);
PrivilegedStack.push(context, caller);
try {
return action.run();
} catch (Exception e) {
throw AccessControllerUtil.wrapCheckedException(e);
} finally {
AccessControllerUtil.PrivilegedStack.pop();
PrivilegedStack.pop();
}
}

@Substitute
@TargetElement(onlyWith = JDK14OrLater.class)
@TargetElement(onlyWith = JDK17OrLater.class)
@SuppressWarnings({"unused", "deprecation"})
static AccessControlContext checkContext(AccessControlContext context, Class<?> caller) {

Expand All @@ -182,15 +194,19 @@ static AccessControlContext checkContext(AccessControlContext context, Class<?>
@TargetClass(java.security.AccessControlContext.class)
@SuppressWarnings({"unused"})
final class Target_java_security_AccessControlContext {
@Alias protected boolean isPrivileged;
@Alias protected boolean isAuthorized;
@Alias public boolean isPrivileged;
@Alias public boolean isAuthorized;

@Alias
Target_java_security_AccessControlContext(ProtectionDomain[] context, AccessControlContext privilegedContext) {
}

@Substitute
static Debug getDebug() {
/*
* We want to prevent Debug class from being reachable, as this method would return null
* anyways
*/
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.ArrayList;

Expand All @@ -39,8 +38,6 @@
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.NeverInline;
import com.oracle.svm.core.code.FrameInfoQueryResult;
import com.oracle.svm.core.graal.snippets.CEntryPointSnippets;
import com.oracle.svm.core.jdk.AccessControllerUtil.PrivilegedStack;
import com.oracle.svm.core.snippets.KnownIntrinsics;
import com.oracle.svm.core.stack.JavaStackFrameVisitor;
import com.oracle.svm.core.stack.JavaStackWalker;
Expand All @@ -51,10 +48,6 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;

// Checkstyle: stop
import sun.security.util.SecurityConstants;
// Checkstyle: resume

public class StackTraceUtils {

private static final Class<?>[] NO_CLASSES = new Class<?>[0];
Expand Down Expand Up @@ -370,11 +363,6 @@ public boolean visitFrame(final FrameInfoQueryResult frameInfo) {
@NeverInline("Starting a stack walk in the caller frame")
@SuppressWarnings({"deprecation"}) // deprecated starting JDK 17
public static AccessControlContext getFromStack() {
if (!CEntryPointSnippets.isIsolateInitialized()) {
Permissions perms = new Permissions();
perms.add(SecurityConstants.ALL_PERMISSION);
return new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, perms)});
}
StackAccessControlContextVisitor visitor = new StackAccessControlContextVisitor();
JavaStackWalker.walkCurrentThread(KnownIntrinsics.readCallerStackPointer(), visitor);
Target_java_security_AccessControlContext wrapper;
Expand Down
Loading

0 comments on commit 2aee05e

Please sign in to comment.