当试图在类似插件的环境中实现沙盒时,我遇到https://stackoverflow.com/a/5580239/2057294这似乎正是我想要的,但是我无法让它工作,我做错了什么?
我有以下设置:
final class ModURLClassLoader extends URLClassLoader {
ModURLClassLoader(final URL[] urls) {
super(urls);
}
ModURLClassLoader(final URL[] urls, final ClassLoader parent) {
super(urls, parent);
}
ModURLClassLoader(final URL[] urls, final ClassLoader parent, final URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
@Override
protected PermissionCollection getPermissions(final CodeSource codesource) {
PermissionCollection permissionCollection = super.getPermissions(codesource);
//give no permissions to the codesource
return permissionCollection;
}
@Override
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
int i = name.lastIndexOf('.');
if (i != -1) {
sm.checkPackageAccess(name.substring(0, i));
}
}
return super.loadClass(name, resolve);
}
}
这里的想法是通过ModURLClassLoader
加载的代码可能根本没有权限。我确实希望能够静态添加额外的权限,以防我阻止一些mod通常想拥有的权限。
然后我通过以下方式加载我的课程:
public class JavaMod extends LoadableMod {
private ECSMod ecsMod;
private ModURLClassLoader modUrlClassLoader;
JavaMod(final Path modDirectory) throws ModNotLoadableException {
super(modDirectory);
}
@Override
protected void load0() throws ModNotLoadableException {
try {
Properties properties = ModLoaderHelper.getConfiguration(modDirectory);
String jarName = properties.getProperty("jar");
String entryPoint = properties.getProperty("entryPoint");
Path jarPath = modDirectory.resolve(jarName);
try {
modUrlClassLoader = AccessController.doPrivileged((PrivilegedExceptionAction<ModURLClassLoader>)() -> new ModURLClassLoader(new URL[] { jarPath.toUri().toURL() }, getClass().getClassLoader()));
} catch (PrivilegedActionException ex) {
throw new ModNotLoadableException(ex);
}
Class<?> clazz = Class.forName(entryPoint, false, modUrlClassLoader);
if (!ECSMod.class.isAssignableFrom(clazz)) {
throw new ModNotLoadableException(clazz + " does not implement ECSMod");
}
this.ecsMod = (ECSMod)clazz.newInstance();
} catch (Exception ex) {
throw new ModNotLoadableException(ex);
}
}
@Override
protected void unload0() {
try {
modUrlClassLoader.close();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
@Override
protected ECSGame createGame0() {
ECSGame ecsGame = new ECSGame();
ecsMod.setupGame(ecsGame);
return ecsGame;
}
}
加载具有实现ECSMod
的类的不受信任的JAR,我已确认clazz
和ecsMod
都属于ModURLClassLoader
的实例。
然后是恶意代码:
public final class UntrustedEvilMod implements ECSMod {
@Override
public void setupGame(final ECSGame game) {
System.exit(0);
}
}
其中ECSMod
和ECSGame
是属于插件(也称为mod)API的类,并且位于原始类加载器中。
我在没有安全经理的情况下运行这个,因为我认为在这种情况下这是不必要的吗?由于ModURLClassLoader
定义了安全性。
为什么这不起作用,这意味着它仍会导致程序退出,而我想要一个AccessControlException
?