Skip to content

Commit

Permalink
Add allowlist for known-good JDK contexts.
Browse files Browse the repository at this point in the history
  • Loading branch information
lazar-mitrovic committed Sep 11, 2021
1 parent 762fe00 commit e1e86d4
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.SocketPermission;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.security.AccessControlContext;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
Expand All @@ -48,7 +46,6 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

import org.graalvm.compiler.phases.common.LazyValue;
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.ImageSingletons;
Expand Down Expand Up @@ -363,118 +360,6 @@ public static int getCommonPoolParallelism() {
}
}

/**
* Since AccessControlContextFeature replaces all AccessControlContext objects with
* NO_CONTEXT_SINGLETON, we need to reinitialize them in runtime.
*/

@TargetClass(className = "java.security.AccessController$AccHolder", onlyWith = JDK11OrLater.class)
@SuppressWarnings("unused") //
final class Target_java_security_AccessController_AccHolder {
@Alias @InjectAccessors(AccessControllerUtil.INNOCUOUS_ACC.class) static AccessControlContext innocuousAcc;
}

@TargetClass(className = "java.util.Calendar$CalendarAccessControlContext")
@SuppressWarnings("unused") //
final class Target_java_util_Calendar_CalendarAccessControlContext {
@Alias @InjectAccessors(CalendarAccessControlContextAcc.class) static AccessControlContext INSTANCE;
}

class CalendarAccessControlContextAcc {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(
new RuntimePermission("accessClassInPackage.sun.util.calendar")));

static AccessControlContext get() {
return acc.get();
}
}

@TargetClass(className = "java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory", onlyWith = JDK11OrLater.class)
@SuppressWarnings("unused") //
final class Target_java_util_concurrent_ForkJoinPool_DefaultForkJoinWorkerThreadFactory {
@Alias @InjectAccessors(DefaultForkJoinWorkerThreadFactoryAcc.class) static AccessControlContext ACC;
}

class DefaultForkJoinWorkerThreadFactoryAcc {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(
new RuntimePermission("getClassLoader"),
new RuntimePermission("setContextClassLoader")));

static AccessControlContext get() {
return acc.get();
}
}

@TargetClass(className = "java.util.concurrent.ForkJoinPool$InnocuousForkJoinWorkerThreadFactory", onlyWith = JDK11OrLater.class)
@SuppressWarnings("unused") //
final class Target_java_util_concurrent_ForkJoinPool_InnocuousForkJoinWorkerThreadFactory {
@Alias @InjectAccessors(InnocuousForkJoinWorkerThreadFactoryAcc.class) static AccessControlContext ACC;
}

class InnocuousForkJoinWorkerThreadFactoryAcc {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(
new RuntimePermission("modifyThread"),
new RuntimePermission("enableContextClassLoaderOverride"),
new RuntimePermission("modifyThreadGroup"),
new RuntimePermission("getClassLoader"),
new RuntimePermission("setContextClassLoader")));

static AccessControlContext get() {
return acc.get();
}
}

@TargetClass(className = "java.util.concurrent.ForkJoinWorkerThread")
@SuppressWarnings("unused") //
final class Target_java_util_concurrent_ForkJoinWorkerThread {
@Alias @InjectAccessors(AccessControllerUtil.INNOCUOUS_ACC.class) static AccessControlContext INNOCUOUS_ACC;
}

@TargetClass(className = "sun.misc.InnocuousThread", onlyWith = JDK8OrEarlier.class)
@SuppressWarnings("unused") //
final class Target_sun_misc_InnocuousThread {
@Alias @InjectAccessors(AccessControllerUtil.INNOCUOUS_ACC.class) static AccessControlContext ACC;
}

@TargetClass(className = "jdk.internal.misc.InnocuousThread", onlyWith = JDK11OrLater.class)
@SuppressWarnings("unused") //
final class Target_jdk_internal_misc_InnocuousThread {
@Alias @InjectAccessors(AccessControllerUtil.INNOCUOUS_ACC.class) static AccessControlContext ACC;
}

@TargetClass(className = "javax.management.Monitor", onlyWith = PlatformHasClass.class)
@SuppressWarnings("unused") //
final class Target_javax_management_Monitor {
@Alias @InjectAccessors(AccessControllerUtil.NO_PERMISSIONS_CONTEXT.class) static AccessControlContext noPermissionsACC;
}

@TargetClass(className = "java.rmi.activation.ActivationID")
@SuppressWarnings("unused") //
final class Target_java_rmi_activation_ActivationID {
@Alias @InjectAccessors(AccessControllerUtil.NO_PERMISSIONS_CONTEXT.class) static AccessControlContext NOPERMS_ACC;
}

@TargetClass(className = "sun.rmi.transport.DGCCClient", onlyWith = PlatformHasClass.class)
@SuppressWarnings("unused") //
final class Target_sun_rmi_transport_DGCCClient {
@Alias @InjectAccessors(SocketAcc.class) static AccessControlContext SOCKET_ACC;
}

class SocketAcc {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(
new SocketPermission("*", "connect,resolve")));

static AccessControlContext get() {
return acc.get();
}
}

@TargetClass(className = "sun.rmi.transport.tcp.TCPTransport")
@SuppressWarnings("unused") //
final class Target_sun_rmi_transport_tcp_TCPTransport {
@Alias @InjectAccessors(AccessControllerUtil.NO_PERMISSIONS_CONTEXT.class) static AccessControlContext NOPERMS_ACC;
}

/**
* An injected field to replace ForkJoinPool.common.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.security.Provider;
import java.security.SecureRandom;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -48,7 +49,6 @@

import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import org.graalvm.compiler.phases.common.LazyValue;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand Down Expand Up @@ -199,50 +199,6 @@ class AccessControllerUtil {
}
}

static class INNOCUOUS_ACC {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, null)}));

static AccessControlContext get() {
return acc.get();
}

static void set(AccessControlContext ctx) {
}
}

static class NO_PERMISSIONS_CONTEXT {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(new Permission[0]));

static AccessControlContext get() {
return acc.get();
}

static void set(AccessControlContext ctx) {
}
}

static class GET_CLASS_LOADER_CONTEXT {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(new RuntimePermission("getClassLoader")));

static AccessControlContext get() {
return acc.get();
}

static void set(AccessControlContext ctx) {
}
}

static class GET_LOOKUP_CONTEXT {
static LazyValue<AccessControlContext> acc = new LazyValue<>(() -> AccessControllerUtil.contextWithPermissions(new RuntimePermission("dynalink.getLookup")));

static AccessControlContext get() {
return acc.get();
}

static void set(AccessControlContext ctx) {
}
}

public static class PrivilegedStack {

public static class StackElement {
Expand Down Expand Up @@ -296,14 +252,6 @@ public static int length() {
}
}

public static AccessControlContext contextWithPermissions(Permission... perms) {
Permissions permissions = new Permissions();
for (Permission perm : perms) {
permissions.add(perm);
}
return new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, permissions)});
}

static Throwable wrapCheckedException(Throwable ex) {
if (ex instanceof Exception && !(ex instanceof RuntimeException)) {
return new PrivilegedActionException((Exception) ex);
Expand All @@ -316,13 +264,42 @@ static Throwable wrapCheckedException(Throwable ex) {
@AutomaticFeature
@SuppressWarnings({"unused"})
class AccessControlContextFeature implements Feature {

static List<AccessControlContext> allowedContexts;

static void allowContextIfExists(String className, String fieldName) {
try {
allowedContexts.add(ReflectionUtil.readStaticField(Class.forName(className), fieldName));
} catch (ReflectiveOperationException e) {
// JDK doesn't include this AccessControlContext, so we just skip it.
}
}
static {
allowedContexts = new ArrayList<>();
allowContextIfExists("java.security.AccessController$AccHolder", "innocuousAcc");
allowContextIfExists("java.util.concurrent.ForkJoinWorkerThread", "INNOCUOUS_ACC");
allowContextIfExists("sun.misc.InnocuousThread", "ACC");
allowContextIfExists("jdk.internal.misc.InnocuousThread", "ACC");
allowContextIfExists("java.util.Calendar$CalendarAccessControlContext", "INSTANCE");
allowContextIfExists("sun.rmi.transport.tcp.TCPTransport", "NOPERMS_ACC");
allowContextIfExists("java.rmi.activation.ActivationID", "NOPERMS_ACC");
allowContextIfExists("sun.rmi.transport.DGCCClient", "SOCKET_ACC");
allowContextIfExists("java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory", "ACC");
allowContextIfExists("java.util.concurrent.ForkJoinPool$InnocuousForkJoinWorkerThreadFactory", "ACC");
allowContextIfExists("javax.management.monitor.Monitor", "noPermissionsACC");
}

@Override
public void duringSetup(DuringSetupAccess access) {
access.registerObjectReplacer(AccessControlContextFeature::replaceAccessControlContext);
}

private static Object replaceAccessControlContext(Object obj) {
if (obj instanceof AccessControlContext) {
AccessControlContext acc = (AccessControlContext) obj;
if (allowedContexts.contains(acc)) {
return acc;
}
return AccessControllerUtil.NO_CONTEXT_SINGLETON;
}
return obj;
Expand Down

0 comments on commit e1e86d4

Please sign in to comment.