From 2c1c8cb3306f719d17adcca216b3f4c0b09745d9 Mon Sep 17 00:00:00 2001 From: Dogboy21 Date: Sat, 19 Aug 2023 13:11:34 +0200 Subject: [PATCH] fix(fabric-agent): allow SiB classes to be loaded from the parent classloader --- .../agent/SIBTransformer.java | 1 + .../agent/SerializationIsBadAgent.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java b/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java index a38dd21..16fbeb2 100644 --- a/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java +++ b/agent/src/main/java/io/dogboy/serializationisbad/agent/SIBTransformer.java @@ -12,6 +12,7 @@ public byte[] transform(ClassLoader loader, String className, Class classBein try { if (className == null) return classfileBuffer; if ("net/minecraft/launchwrapper/ITweaker".equals(className)) SerializationIsBadAgent.insertLaunchWrapperExclusion(); + if ("net/fabricmc/loader/ModContainer".equals(className)) SerializationIsBadAgent.insertFabricValidParentUrl(loader); String classNameDots = className.replace('/', '.'); diff --git a/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java b/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java index 9198f8b..1e8c793 100644 --- a/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java +++ b/agent/src/main/java/io/dogboy/serializationisbad/agent/SerializationIsBadAgent.java @@ -6,6 +6,9 @@ import java.lang.instrument.Instrumentation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; public class SerializationIsBadAgent { @@ -35,4 +38,39 @@ static void insertLaunchWrapperExclusion() { } } + /** + * Another hacky workaround for newer Fabric versions that enforce + * classpath isolation. This adds the path to the SiB jar to the + * list of jar paths that are allowed to be loaded by the parent + * classloader + * + * @param fabricClassLoader The classloader that was used to load the Fabric classes + */ + static void insertFabricValidParentUrl(ClassLoader fabricClassLoader) { + try { + Path sibPath = new File(SerializationIsBadAgent.class.getProtectionDomain().getCodeSource().getLocation().toURI()).toPath(); + + // basically accessing the following: + // ((KnotClassDelegate) ((Knot) FabricLauncherBase.getLauncher()).classLoader).validParentCodeSources + + Class fabricLauncherBaseClass = Class.forName("net.fabricmc.loader.impl.launch.FabricLauncherBase", true, fabricClassLoader); + Method getLauncherMethod = fabricLauncherBaseClass.getDeclaredMethod("getLauncher"); + Object fabricLauncher = getLauncherMethod.invoke(null); + Field classLoaderField = fabricLauncher.getClass().getDeclaredField("classLoader"); + classLoaderField.setAccessible(true); + Object classLoader = classLoaderField.get(fabricLauncher); + Field validParentCodeSourcesField = classLoader.getClass().getDeclaredField("validParentCodeSources"); + validParentCodeSourcesField.setAccessible(true); + @SuppressWarnings("unchecked") + Set validParentCodeSources = (Set) validParentCodeSourcesField.get(classLoader); + + Set newValidParentCodeSources = new HashSet<>(validParentCodeSources); + newValidParentCodeSources.add(sibPath); + + validParentCodeSourcesField.set(classLoader, newValidParentCodeSources); + } catch (Throwable e) { + SerializationIsBad.logger.error("Failed to insert Fabric valid parent URL", e); + } + } + }