Extract the log4j patch to the HMCL directory

This commit is contained in:
Glavo
2021-12-24 22:50:43 +08:00
committed by Yuhui Huang
parent 130c8d0e89
commit cfa1eedae7
3 changed files with 58 additions and 46 deletions

View File

@@ -328,7 +328,7 @@ public class HMCLGameRepository extends DefaultGameRepository {
vs.setUsesGlobal(true);
}
public LaunchOptions getLaunchOptions(String version, JavaVersion javaVersion, File gameDir, boolean makeLaunchScript) {
public LaunchOptions getLaunchOptions(String version, JavaVersion javaVersion, File gameDir, List<String> javaAgents, boolean makeLaunchScript) {
VersionSetting vs = getVersionSetting(version);
LaunchOptions.Builder builder = new LaunchOptions.Builder()
@@ -359,7 +359,8 @@ public class HMCLGameRepository extends DefaultGameRepository {
.setProcessPriority(vs.getProcessPriority())
.setUseNativeGLFW(vs.isUseNativeGLFW())
.setUseNativeOpenAL(vs.isUseNativeOpenAL())
.setDaemon(!makeLaunchScript && vs.getLauncherVisibility().isDaemon());
.setDaemon(!makeLaunchScript && vs.getLauncherVisibility().isDaemon())
.setJavaAgents(javaAgents);
if (config().hasProxy()) {
builder.setProxy(ProxyManager.getProxy());
if (config().hasProxyAuth()) {

View File

@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.game;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.*;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
import org.jackhuang.hmcl.download.DefaultDependencyManager;
@@ -55,9 +56,13 @@ import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
@@ -124,9 +129,12 @@ public final class LauncherHelper {
Optional<String> gameVersion = repository.getGameVersion(version);
boolean integrityCheck = repository.unmarkVersionLaunchedAbnormally(selectedVersion);
CountDownLatch launchingLatch = new CountDownLatch(1);
List<String> javaAgents = new ArrayList<>(0);
AtomicReference<JavaVersion> javaVersionRef = new AtomicReference<>();
getLog4jPatch(version).ifPresent(javaAgents::add);
TaskExecutor executor = checkGameState(profile, setting, version)
.thenComposeAsync(javaVersion -> {
javaVersionRef.set(Objects.requireNonNull(javaVersion));
@@ -172,7 +180,7 @@ public final class LauncherHelper {
}
}).withStage("launch.state.logging_in"))
.thenComposeAsync(authInfo -> Task.supplyAsync(() -> {
LaunchOptions launchOptions = repository.getLaunchOptions(selectedVersion, javaVersionRef.get(), profile.getGameDir(), scriptFile != null);
LaunchOptions launchOptions = repository.getLaunchOptions(selectedVersion, javaVersionRef.get(), profile.getGameDir(), javaAgents, scriptFile != null);
return new HMCLGameLauncher(
repository,
version,
@@ -598,6 +606,47 @@ public final class LauncherHelper {
return future;
}
private static Optional<String> getLog4jPatch(Version version) {
Optional<String> log4jVersion = version.getLibraries().stream()
.filter(it -> it.is("org.apache.logging.log4j", "log4j-core")
&& (VersionNumber.VERSION_COMPARATOR.compare(it.getVersion(), "2.17") < 0 || "2.0-beta9".equals(it.getVersion())))
.map(Library::getVersion)
.findFirst();
if (log4jVersion.isPresent()) {
final String agentFileName = "log4j-patch-agent-1.0.jar";
Path agentFile = Metadata.HMCL_DIRECTORY.resolve(agentFileName).toAbsolutePath();
String agentFilePath = agentFile.toString();
if (agentFilePath.indexOf('=') >= 0) {
LOG.warning("Invalid character '=' in the HMCL directory path, unable to attach log4j-patch");
return Optional.empty();
}
if (Files.notExists(agentFile)) {
try (InputStream input = DefaultLauncher.class.getResourceAsStream("/assets/game/" + agentFileName)) {
LOG.info("Extract log4j patch to " + agentFilePath);
Files.createDirectories(agentFile.getParent());
Files.copy(input, agentFile, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to extract log4j patch");
try {
Files.deleteIfExists(agentFile);
} catch (IOException ex) {
LOG.log(Level.WARNING, "Failed to delete incomplete log4j patch", ex);
}
return Optional.empty();
}
}
boolean isBeta = log4jVersion.get().startsWith("2.0-beta");
return Optional.of(agentFilePath + "=" + isBeta);
} else {
LOG.info("No log4j with security vulnerabilities found");
return Optional.empty();
}
}
private void checkExit() {
switch (launcherVisibility) {
case HIDE_AND_REOPEN: