From 6ef85b21630d3eea5ced55c94db257c89c7e7e15 Mon Sep 17 00:00:00 2001 From: Mateusz Pietryga Date: Sun, 13 Aug 2023 21:56:32 +0200 Subject: [PATCH 1/2] Do not assume ClassLoader concrete type when dynamically loading classes #5 --- jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java b/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java index 7217b106..65e3de62 100644 --- a/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java +++ b/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java @@ -7449,8 +7449,7 @@ static private Op compileMethod(Op op, StringBuilder method, boolean jump) { // Make the dynamic class belong to its own class loader so that when we // release the decoder block the class and class loader will be unloaded - URLClassLoader cl = (URLClassLoader) codeBlock.getClass().getClassLoader(); - cl = URLClassLoader.newInstance(cl.getURLs(), cl); + URLClassLoader cl = URLClassLoader.newInstance(new URL[]{}, codeBlock.getClass().getClassLoader()); Class clazz = codeBlock.toClass(cl, null); Op compiledCode = (Op) clazz.newInstance(); codeBlock.detach(); From ad155b35d661608d694f9262ce87a34150a01279 Mon Sep 17 00:00:00 2001 From: Mateusz Pietryga Date: Mon, 14 Aug 2023 00:09:27 +0200 Subject: [PATCH 2/2] Prevent illegal reflective access when dynamically loading classes #5 --- .../java/jdos/cpu/core_dynamic/Compiler.java | 28 +++++++++++++++---- pom.xml | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java b/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java index 65e3de62..0c74699f 100644 --- a/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java +++ b/jdosbox/src/main/java/jdos/cpu/core_dynamic/Compiler.java @@ -7425,7 +7425,7 @@ public void close() { static private Op compileMethod(Op op, StringBuilder method, boolean jump) { //System.out.println(method.toString()); try { - String className = "CacheBlock" + (count++); + String className = "jdos.cpu.core_dynamic.CacheBlock" + (count++); // :TODO: research using a new pool for each block since the classes don't need to see each other CtClass codeBlock = pool.makeClass(className); codeBlock.setSuperclass(pool.getCtClass("jdos.cpu.core_dynamic.Op")); @@ -7444,20 +7444,36 @@ static private Op compileMethod(Op op, StringBuilder method, boolean jump) { if (cycle<1) { cycle=1; } - CtConstructor c = CtNewConstructor.make("public "+className+"(){this.cycle="+cycle+";}", codeBlock); + CtConstructor c = CtNewConstructor.make("public "+codeBlock.getSimpleName()+"(){this.cycle="+cycle+";}", codeBlock); codeBlock.addConstructor(c); // Make the dynamic class belong to its own class loader so that when we // release the decoder block the class and class loader will be unloaded - URLClassLoader cl = URLClassLoader.newInstance(new URL[]{}, codeBlock.getClass().getClassLoader()); - Class clazz = codeBlock.toClass(cl, null); + ClassLoader cl = new URLClassLoader( + new URL[]{ Compiler.class.getProtectionDomain().getCodeSource().getLocation()}, + codeBlock.getClass().getClassLoader()); + + // Create second copy of Compiler class inside custom classloader as "neighbour". + // CtClass.toClass(neighbour) does not cause illegal reflective access in JDK17. + Class clazz = codeBlock.toClass(cl.loadClass(Compiler.class.getName())); Op compiledCode = (Op) clazz.newInstance(); codeBlock.detach(); if (saveClasses) { if (op instanceof DecodeBlock) { DecodeBlock block = (DecodeBlock)op; - String header = "package jdos.cpu.core_dynamic;\n\nimport jdos.cpu.core_dynamic.*;\nimport jdos.cpu.*;\nimport jdos.fpu.*;\nimport jdos.hardware.*;\nimport jdos.util.*;\nimport jdos.cpu.core_normal.*;\nimport jdos.cpu.core_share.*;\n\npublic final class "+className+" extends Op {\npublic int call() {"; - Loader.add(codeBlock.getName(), codeBlock.toBytecode(), block.codeStart, getOpCode(block.codeStart, block.codeLen), header+method.toString()+"\n}"); + String classBody = + "package " + codeBlock.getPackageName() + ";\n\n" + + "import jdos.cpu.core_dynamic.*;\n" + + "import jdos.cpu.*;\n" + + "import jdos.fpu.*;\n" + + "import jdos.hardware.*;\n" + + "import jdos.util.*;\n" + + "import jdos.cpu.core_normal.*;\n" + + "import jdos.cpu.core_share.*;\n\n" + + "public final class " + codeBlock.getSimpleName() + " extends " + codeBlock.getSuperclass().getName() + " {\n" + + " public int call() { " + method + "} \n" + + "}"; + Loader.add(codeBlock.getName(), codeBlock.toBytecode(), block.codeStart, getOpCode(block.codeStart, block.codeLen), classBody); } else { Log.exit("Tried to save an incomplete code block"); } diff --git a/pom.xml b/pom.xml index 68429056..c6f80067 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ org.javassist javassist - 3.14.0-GA + 3.29.2-GA jnetpcap