Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.oracle.svm.core.posix.PosixUtils;
import com.oracle.svm.core.posix.headers.darwin.DarwinTime;
import com.oracle.svm.core.util.BasedOnJDKFile;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

import jdk.internal.misc.Unsafe;

Expand Down Expand Up @@ -138,7 +139,7 @@ final class Target_java_util_prefs_FileSystemPreferences {
final class IsJavaUtilPrefsPresent implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
var prefsMod = ModuleLayer.boot().findModule("java.prefs");
var prefsMod = ResolvedJavaModuleLayer.boot().findModule("java.prefs");
return prefsMod.isPresent();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.LogUtils;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.asm.amd64.AMD64Assembler;
Expand Down Expand Up @@ -975,7 +976,7 @@ public static boolean hasFramePointer() {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
if ("llvm".equals(newValue)) {
boolean isLLVMBackendMissing = ModuleLayer.boot().findModule("org.graalvm.nativeimage.llvm").isEmpty();
boolean isLLVMBackendMissing = ResolvedJavaModuleLayer.boot().findModule("org.graalvm.nativeimage.llvm").isEmpty();
if (isLLVMBackendMissing) {
throw UserError.invalidOptionValue(CompilerBackend, newValue,
"The LLVM backend for GraalVM Native Image is missing and needs to be built from source. " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@
import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.util.HostModuleUtil;
import com.oracle.svm.util.ResolvedJavaModule;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

@AutomaticallyRegisteredFeature
@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class JavaNetHttpFeature extends JNIRegistrationUtil implements InternalFeature {

private static Optional<Module> requiredModule() {
return ModuleLayer.boot().findModule("java.net.http");
private static Optional<ResolvedJavaModule> requiredModule() {
return ResolvedJavaModuleLayer.boot().findModule("java.net.http");
}

@Override
Expand All @@ -54,7 +57,7 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {

@Override
public void afterRegistration(AfterRegistrationAccess access) {
JavaNetHttpFeature.class.getModule().addReads(requiredModule().get());
HostModuleUtil.addReads(JavaNetHttpFeature.class, requiredModule().get());
}

@Override
Expand All @@ -80,8 +83,8 @@ private static void registerInitFiltersAccess(DuringAnalysisAccess a) {
@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
class SimpleWebServerFeature implements InternalFeature {

private static Optional<Module> requiredModule() {
return ModuleLayer.boot().findModule("jdk.httpserver");
private static Optional<ResolvedJavaModule> requiredModule() {
return ResolvedJavaModuleLayer.boot().findModule("jdk.httpserver");
}

@Override
Expand All @@ -91,7 +94,7 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {

@Override
public void afterRegistration(AfterRegistrationAccess access) {
SimpleWebServerFeature.class.getModule().addReads(requiredModule().get());
HostModuleUtil.addReads(SimpleWebServerFeature.class, requiredModule().get());

RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
rci.initializeAtRunTime("sun.net.httpserver.simpleserver", "Allocates InetAddress in class initializers");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

/**
* These substitutions are necessary because the static initializations of these fields are copies
Expand Down Expand Up @@ -101,6 +102,6 @@ final class Target_sun_misc_Unsafe {
class JdkUnsupportedIsEnabled implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return ModuleLayer.boot().findModule("jdk.unsupported").isPresent();
return ResolvedJavaModuleLayer.boot().findModule("jdk.unsupported").isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.util.HostModuleUtil;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

/**
* Note that sun.rmi.transport.GC is initialized at build-time to avoid including the rmi library,
Expand All @@ -55,9 +57,9 @@ class JavaRMIModuleAvailable implements BooleanSupplier {
private static final boolean hasModule;

static {
var module = ModuleLayer.boot().findModule("java.rmi");
var module = ResolvedJavaModuleLayer.boot().findModule("java.rmi");
if (module.isPresent()) {
JavaRMIModuleAvailable.class.getModule().addReads(module.get());
HostModuleUtil.addReads(JavaRMIModuleAvailable.class, module.get());
}
hasModule = module.isPresent();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
import java.util.function.BooleanSupplier;

import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.HostModuleUtil;
import com.oracle.svm.util.ReflectionUtil;
import com.oracle.svm.util.ResolvedJavaModule;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

public class ManagementAgentModule {

Expand All @@ -42,9 +45,9 @@ public class ManagementAgentModule {
static final String CONFIG_FILE_OPEN_FAILED;

static {
Optional<Module> agentModule = ModuleLayer.boot().findModule("jdk.management.agent");
Optional<ResolvedJavaModule> agentModule = ResolvedJavaModuleLayer.boot().findModule("jdk.management.agent");
if (agentModule.isPresent()) {
ManagementAgentModule.class.getModule().addReads(agentModule.get());
HostModuleUtil.addReads(ManagementAgentModule.class, agentModule.get());
var agentClass = ReflectionUtil.lookupClass(false, "jdk.internal.agent.Agent");
agentStartAgent = ReflectionUtil.lookupMethod(agentClass, "startAgent");
agentError = ReflectionUtil.lookupMethod(agentClass, "error", String.class, String.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
import com.oracle.svm.core.thread.ThreadListener;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.HostModuleUtil;
import com.oracle.svm.util.ResolvedJavaModuleLayer;
import com.sun.jmx.mbeanserver.MXBeanLookup;

import jdk.graal.compiler.api.replacements.Fold;
Expand Down Expand Up @@ -297,9 +299,9 @@ private synchronized PlatformManagedObject getFlightRecorderMXBean() {
@Platforms(Platform.HOSTED_ONLY.class)
@SuppressWarnings("unchecked")
private static Class<? extends PlatformManagedObject> getFlightRecorderMXBeanClass() {
var jfrModule = ModuleLayer.boot().findModule("jdk.management.jfr");
var jfrModule = ResolvedJavaModuleLayer.boot().findModule("jdk.management.jfr");
if (jfrModule.isPresent()) {
ManagementSupport.class.getModule().addReads(jfrModule.get());
HostModuleUtil.addReads(ManagementSupport.class, jfrModule.get());
try {
return (Class<? extends PlatformManagedObject>) Class.forName("jdk.management.jfr.FlightRecorderMXBean", false, Object.class.getClassLoader());
} catch (ClassNotFoundException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@
*/
package com.oracle.svm.hosted;

import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
import com.oracle.svm.util.ReflectionUtil;

import org.graalvm.collections.EconomicMap;
import org.graalvm.nativeimage.ImageSingletons;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
Expand All @@ -54,6 +48,13 @@
import java.util.ResourceBundle;
import java.util.Set;

import org.graalvm.collections.EconomicMap;
import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
import com.oracle.svm.util.ReflectionUtil;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

import jdk.internal.access.JavaLangAccess;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.misc.Unsafe;
Expand Down Expand Up @@ -99,7 +100,7 @@ public static DynamicAccessDetectionSupport instance() {

public DynamicAccessDetectionSupport(AnalysisMetaAccess metaAccess) {
this.metaAccess = metaAccess;
boolean jdkUnsupportedModulePresent = ModuleLayer.boot().findModule("jdk.unsupported").isPresent();
boolean jdkUnsupportedModulePresent = ResolvedJavaModuleLayer.boot().findModule("jdk.unsupported").isPresent();

put(reflectionMethods, Class.class, Set.of(
new MethodSignature("forName", String.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ public void registerReachabilityHandler(Consumer<DuringAnalysisAccess> callback,
case Class<?> clazz -> getMetaAccess().lookupJavaType(clazz);
case Field field -> getMetaAccess().lookupJavaField(field);
case Executable executable -> getMetaAccess().lookupJavaMethod(executable);
case AnalysisElement ae -> ae;
default -> throw UserError.abort("'registerReachabilityHandler' called with an element that is not a Class, Field, or Executable: %s",
trigger.getClass().getTypeName());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,33 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.hosted.FeatureImpl.AfterAnalysisAccessImpl;
import com.oracle.svm.util.JVMCIReflectionUtil;
import com.oracle.svm.util.LogUtils;
import com.oracle.svm.util.ResolvedJavaPackage;

import jdk.vm.ci.meta.ResolvedJavaType;

/**
* A feature that detects whether a native image may be vulnerable to Log4Shell.
Expand All @@ -67,14 +71,8 @@ public class Log4ShellFeature implements InternalFeature {
/* Different versions of log4j overload all these methods. */
private static final Set<String> targetMethods = Set.of("debug", "error", "fatal", "info", "log", "trace", "warn");

private static Optional<String> getPomVersion(Class<?> log4jClass) {
ProtectionDomain pd = log4jClass.getProtectionDomain();
CodeSource cs = pd.getCodeSource();

if (cs == null) {
return Optional.empty();
}
URL location = cs.getLocation();
private static Optional<String> getPomVersion(ResolvedJavaType log4jClass) {
URL location = JVMCIReflectionUtil.getOrigin(log4jClass);
if (location == null) {
return Optional.empty();
}
Expand Down Expand Up @@ -148,20 +146,20 @@ private static boolean vulnerableLog4jTwo(String[] components) {
return false;
}

private AfterAnalysisAccess afterAnalysisAccess;
private AfterAnalysisAccessImpl afterAnalysisAccess;

@Override
public void afterAnalysis(AfterAnalysisAccess access) {
this.afterAnalysisAccess = access;
this.afterAnalysisAccess = (AfterAnalysisAccessImpl) access;
}

public String getUserWarning() {
Class<?> log4jClass = afterAnalysisAccess.findClassByName(log4jClassName);
AnalysisType log4jClass = afterAnalysisAccess.findTypeByName(log4jClassName);
if (log4jClass == null) {
return null;
}

Package log4jPackage = log4jClass.getPackage();
ResolvedJavaPackage log4jPackage = JVMCIReflectionUtil.getPackage(log4jClass);
String version = log4jPackage.getImplementationVersion();

if (version == null) {
Expand All @@ -186,21 +184,21 @@ public String getUserWarning() {
Set<String> vulnerableMethods = new HashSet<>();

if (("1".equals(components[0]) && vulnerableLog4jOne(components)) || ("2".equals(components[0]) && vulnerableLog4jTwo(components))) {
for (Method method : log4jClass.getMethods()) {
for (AnalysisMethod method : log4jClass.getDeclaredMethods(false)) {
String methodName = method.getName();
if (targetMethods.contains(methodName) && (afterAnalysisAccess.isReachable(method) || (afterAnalysisAccess.reachableMethodOverrides(method).size() > 0))) {
vulnerableMethods.add(method.getDeclaringClass().getName() + "." + method.getName());
if (targetMethods.contains(methodName) && (afterAnalysisAccess.isReachable(method) || (!afterAnalysisAccess.reachableMethodOverrides(method).isEmpty()))) {
vulnerableMethods.add(method.getDeclaringClass().toClassName() + "." + method.getName());
}
}
}

if (vulnerableMethods.size() == 0) {
if (vulnerableMethods.isEmpty()) {
return null;
}

StringBuilder renderedErrorMessage = new StringBuilder(String.format(log4jVulnerableErrorMessage));
for (String method : vulnerableMethods) {
renderedErrorMessage.append(System.lineSeparator() + " - " + method);
renderedErrorMessage.append(System.lineSeparator()).append(" - ").append(method);
}
return renderedErrorMessage.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,19 @@
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import com.oracle.svm.util.HostModuleUtil;
import com.oracle.svm.util.ReflectionUtil;
import com.oracle.svm.util.ResolvedJavaModule;
import com.oracle.svm.util.ResolvedJavaModuleLayer;

import jdk.graal.compiler.options.Option;
import jdk.graal.compiler.options.OptionType;

@AutomaticallyRegisteredFeature
public class LoggingFeature implements InternalFeature {

private static Optional<Module> requiredModule() {
return ModuleLayer.boot().findModule("java.logging");
private static Optional<ResolvedJavaModule> requiredModule() {
return ResolvedJavaModuleLayer.boot().findModule("java.logging");
}

public static class Options {
Expand All @@ -74,7 +77,7 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {

@Override
public void afterRegistration(AfterRegistrationAccess access) {
LoggingFeature.class.getModule().addReads(requiredModule().get());
HostModuleUtil.addReads(LoggingFeature.class, requiredModule().get());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor;
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;
import com.oracle.svm.util.ResolvedJavaModuleLayer;
import com.oracle.svm.util.TypeResult;

import jdk.graal.compiler.debug.Assertions;
Expand Down Expand Up @@ -205,20 +206,20 @@ public static class Options {
KeyStore.class, Mac.class, MessageDigest.class, SSLContext.class,
SecretKeyFactory.class, SecureRandom.class, Signature.class, TrustManagerFactory.class));

if (ModuleLayer.boot().findModule("java.security.sasl").isPresent()) {
if (ResolvedJavaModuleLayer.boot().findModule("java.security.sasl").isPresent()) {
classList.add(ReflectionUtil.lookupClass(false, "javax.security.sasl.SaslClientFactory"));
classList.add(ReflectionUtil.lookupClass(false, "javax.security.sasl.SaslServerFactory"));
}
if (ModuleLayer.boot().findModule("java.xml.crypto").isPresent()) {
if (ResolvedJavaModuleLayer.boot().findModule("java.xml.crypto").isPresent()) {
classList.add(ReflectionUtil.lookupClass(false, "javax.xml.crypto.dsig.TransformService"));
classList.add(ReflectionUtil.lookupClass(false, "javax.xml.crypto.dsig.XMLSignatureFactory"));
classList.add(ReflectionUtil.lookupClass(false, "javax.xml.crypto.dsig.keyinfo.KeyInfoFactory"));
}
if (ModuleLayer.boot().findModule("java.smartcardio").isPresent()) {
if (ResolvedJavaModuleLayer.boot().findModule("java.smartcardio").isPresent()) {
classList.add(ReflectionUtil.lookupClass(false, "javax.smartcardio.TerminalFactory"));
}

isMscapiModulePresent = ModuleLayer.boot().findModule("jdk.crypto.mscapi").isPresent();
isMscapiModulePresent = ResolvedJavaModuleLayer.boot().findModule("jdk.crypto.mscapi").isPresent();

knownServices = Collections.unmodifiableList(classList);
}
Expand Down
Loading