Skip to content

Commit

Permalink
* Started refactoring the unsafe/reflection masking code
Browse files Browse the repository at this point in the history
  • Loading branch information
katherine-hough committed Nov 27, 2023
1 parent aafa02c commit 6ecf460
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 201 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import edu.columbia.cs.psl.phosphor.instrumenter.*;
import edu.columbia.cs.psl.phosphor.instrumenter.asm.OffsetPreservingClassReader;
import edu.columbia.cs.psl.phosphor.mask.SerializationFixingCV;
import edu.columbia.cs.psl.phosphor.org.objectweb.asm.commons.OurSerialVersionUIDAdder;
import edu.columbia.cs.psl.phosphor.runtime.StringUtils;
import edu.columbia.cs.psl.phosphor.runtime.TaintInstrumented;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import edu.columbia.cs.psl.phosphor.control.ControlStackInitializingMV;
import edu.columbia.cs.psl.phosphor.control.ControlStackRestoringMV;
import edu.columbia.cs.psl.phosphor.instrumenter.analyzer.NeverNullArgAnalyzerAdapter;
import edu.columbia.cs.psl.phosphor.mask.ReflectionMV;
import edu.columbia.cs.psl.phosphor.mask.ReflectionMVFactory;
import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame;
import edu.columbia.cs.psl.phosphor.runtime.TaintInstrumented;
import edu.columbia.cs.psl.phosphor.runtime.TaintSourceWrapper;
Expand Down Expand Up @@ -245,7 +247,7 @@ private MethodVisitor createInstrumentingMVChain(int access, String name, String
controlStackRestoringMV = new ControlStackRestoringMV(next, rootmV, className, name, controlFlowPolicy);
next = controlStackRestoringMV;
}
ReflectionHidingMV reflectionMasker = new ReflectionHidingMV(next, className, name, isEnum);
ReflectionMV reflectionMasker = ReflectionMVFactory.create(next, className, name);
PrimitiveBoxingFixer boxFixer = new PrimitiveBoxingFixer(access, className, name, instrumentedDesc, signature,
_exceptions, reflectionMasker, analyzer);

Expand Down Expand Up @@ -293,8 +295,7 @@ private MethodVisitor createInstrumentingMVChain(int access, String name, String
}
lvs.setPrimitiveArrayAnalyzer(primitiveArrayFixer);
reflectionMasker.setLvs(lvs);
final MethodVisitor prev = preAnalyzer;
return prev;
return preAnalyzer;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] _exceptions) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package edu.columbia.cs.psl.phosphor.mask;

import edu.columbia.cs.psl.phosphor.Configuration;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.IS_INSTANCE;

class DisabledReflectionMV extends ReflectionMV implements Opcodes {
DisabledReflectionMV(MethodVisitor mv, String className, String methodName) {
super(Configuration.ASM_VERSION, mv);
if (!isApplicable(className, methodName)) {
throw new IllegalArgumentException();
}
}

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
if (owner.equals("java/lang/Class") && name.startsWith("isInstance")) {
// Even if we are not masking other methods, this must be masked
IS_INSTANCE.delegateVisit(mv);
} else {
super.visitMethodInsn(opcode, owner, name, desc, isInterface);
}
}

public static boolean isApplicable(String className, String methodName) {
switch (className) {
case "org/codehaus/groovy/vmplugin/v5/Java5":
return methodName.equals("makeInterfaceTypes");
case "jdk/internal/reflect/ReflectionFactory":
case "java/lang/reflect/ReflectAccess":
// Java >= 9
// TODO keep?
case "java/io/ObjectOutputStream":
case "java/io/ObjectInputStream":
return true;
default:
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package edu.columbia.cs.psl.phosphor.mask;

import edu.columbia.cs.psl.phosphor.Configuration;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.IS_INSTANCE;

class ObjectStreamReflectionMV extends ReflectionMV {
private final String methodName;

ObjectStreamReflectionMV(MethodVisitor mv, String className, String methodName) {
super(Configuration.ASM_VERSION, mv);
if (!isApplicable(className, methodName)) {
throw new IllegalArgumentException();
}
this.methodName = methodName;
}

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
if (owner.equals("java/lang/Class") && name.startsWith("isInstance")) {
// Even if we are not masking other methods, this must be masked
IS_INSTANCE.delegateVisit(mv);
} else if (owner.equals("sun/misc/Unsafe") && shouldMask(name)) {
owner = ReflectionMVFactory.getRuntimeUnsafePropagatorClassName();
super.visitMethodInsn(
Opcodes.INVOKESTATIC, owner, name, "(Lsun/misc/Unsafe;" + desc.substring(1), isInterface);
} else {
super.visitMethodInsn(opcode, owner, name, desc, isInterface);
}
}

private boolean shouldMask(String name) {
switch (methodName) {
case "setObjFieldValues":
return name.startsWith("putObject") || name.startsWith("compareAndSwapObject");
case "getObjFieldValues":
return name.startsWith("getObject");
case "getPrimFieldValues":
case "setPrimFieldValues":
// Check for name.startsWith("put") || name.startsWith("get") was included but unhandled with a
// TODO and the note: name = name + "$$NOUNBOX"
// It is unclear if this needs to fixed
default:
return false;
}
}

public static boolean isApplicable(String className, String methodName) {
return (className.equals("java/io/ObjectStreamClass") || className.equals("java/io/ObjectStreamField"))
&& Configuration.TAINT_THROUGH_SERIALIZATION
&& !methodName.equals("getDeclaredSerialFields$$PHOSPHORTAGGED");
}
}
Loading

0 comments on commit 6ecf460

Please sign in to comment.