Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ban sun.misc.Unsafe #4

Merged
merged 3 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.7
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.7
java-version: 1.8
- name: Build with Maven
run: mvn package --file pom.xml
- name: Upload Artifacts
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ hs_err_pid*

# IntelliJ
.idea/

# result of build
target/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ Supported fields for the `option` list are:
* `nobigmath` — disables `BigInteger` and `BigDecimal`, raising [appropriate exceptions](https://github.com/DMOJ/java-sandbox-agent/blob/master/src/main/java/ca/dmoj/java/BigIntegerDisallowedException.java) if they are used
* `unicode` — encodes `System.out` as UTF-8 instead of ASCII, sacrificing performance for Unicode support
* `nobuf` — sets `System.out` as being line-buffered, for interactive problems
* `unsafe` — enables `sun.misc.Unsafe`, which is disabled by default
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
Expand All @@ -39,4 +39,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
23 changes: 23 additions & 0 deletions src/main/java/ca/dmoj/java/DisallowedClassRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ca.dmoj.java;

public class DisallowedClassRule {
protected interface ExceptionFactory {
Exception create();
}

protected String className;
protected ExceptionFactory exception;

public DisallowedClassRule(String className, ExceptionFactory exception) {
this.className = className;
this.exception = exception;
}

public String getClassName() {
return className;
}

public Exception getException() {
return exception.create();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ca.dmoj.java;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class DisallowedClassesClassFileTransformer implements ClassFileTransformer {
protected DisallowedClassRule[] rules;

public DisallowedClassesClassFileTransformer(DisallowedClassRule... rules) {
this.rules = rules;
}

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
if (className == null) return classfileBuffer;

Exception disallowed = null;
for (DisallowedClassRule rule : rules) {
// If the class ever loaded it's because a submission used it
if (className.startsWith(rule.getClassName())) {
disallowed = rule.getException();
break;
}
}

if (disallowed != null) ExceptionHandler.dumpExceptionAndExit(disallowed);

// Don't actually retransform anything
return classfileBuffer;
}
}
9 changes: 9 additions & 0 deletions src/main/java/ca/dmoj/java/ExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ca.dmoj.java;

class ExceptionHandler {
public static void dumpExceptionAndExit(Throwable exception) {
System.err.print("7257b50d-e37a-4664-b1a5-b1340b4206c0: ");
exception.printStackTrace();
System.exit(1);
}
}
45 changes: 13 additions & 32 deletions src/main/java/ca/dmoj/java/SubmissionAgent.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package ca.dmoj.java;

import java.io.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.ArrayList;

public class SubmissionAgent {
public static void premain(String argv, Instrumentation inst) throws UnsupportedEncodingException {
boolean unsafe = false;
boolean unicode = false;
boolean noBigMath = false;
boolean noBuf = false;

if (argv != null) {
for (String opt : argv.split(",")) {
if (opt.equals("unsafe")) unsafe = true;
if (opt.equals("unicode")) unicode = true;
if (opt.equals("nobigmath")) noBigMath = true;
if (opt.equals("nobuf")) noBuf = true;
Expand All @@ -22,30 +22,17 @@ public static void premain(String argv, Instrumentation inst) throws Unsupported

final Thread selfThread = Thread.currentThread();

ArrayList<DisallowedClassRule> disallowedClassRules = new ArrayList<>();
if (!unsafe) {
disallowedClassRules.add(new DisallowedClassRule("sun/reflect/Unsafe", UnsafeDisallowedException::new));
disallowedClassRules.add(new DisallowedClassRule("sun/misc/Unsafe", UnsafeDisallowedException::new));
}
if (noBigMath) {
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
if (className == null) return classfileBuffer;

RuntimeException disallowed = null;
// If the class ever loaded it's because a submission used it
if (className.startsWith("java/math/BigInteger") ||
className.startsWith("java/math/MutableBigInteger")) {
disallowed = new BigIntegerDisallowedException();
} else if (className.startsWith("java/math/BigDecimal")) {
disallowed = new BigDecimalDisallowedException();
}

if (disallowed != null) dumpExceptionAndExit(disallowed);

// Don't actually retransform anything
return classfileBuffer;
}
});
disallowedClassRules.add(new DisallowedClassRule("java/math/BigInteger", BigIntegerDisallowedException::new));
disallowedClassRules.add(new DisallowedClassRule("java/math/MutableBigInteger", BigIntegerDisallowedException::new));
disallowedClassRules.add(new DisallowedClassRule("java/math/BigDecimal", BigDecimalDisallowedException::new));
}
inst.addTransformer(new DisallowedClassesClassFileTransformer(disallowedClassRules.toArray(new DisallowedClassRule[0])));

if (noBuf) {
// Create output PrintStream set to autoflush:
Expand All @@ -61,7 +48,7 @@ public byte[] transform(ClassLoader loader, String className, Class<?> classBein
selfThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable error) {
dumpExceptionAndExit(error);
ExceptionHandler.dumpExceptionAndExit(error);
}
});

Expand All @@ -75,10 +62,4 @@ public void run() {
}
}));
}

private static void dumpExceptionAndExit(Throwable exception) {
System.err.print("7257b50d-e37a-4664-b1a5-b1340b4206c0: ");
exception.printStackTrace();
System.exit(1);
}
}
4 changes: 4 additions & 0 deletions src/main/java/ca/dmoj/java/UnsafeDisallowedException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ca.dmoj.java;

public class UnsafeDisallowedException extends RuntimeException {
}
Loading