扩展URLClassLoader和覆盖getPermissions不起作用

时间:2014-10-13 12:33:47

标签: java security

当试图在类似插件的环境中实现沙盒时,我遇到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,我已确认clazzecsMod都属于ModURLClassLoader的实例。

然后是恶意代码:

public final class UntrustedEvilMod implements ECSMod {
    @Override
    public void setupGame(final ECSGame game) {
        System.exit(0);
    }
}

其中ECSModECSGame是属于插件(也称为mod)API的类,并且位于原始类加载器中。

我在没有安全经理的情况下运行这个,因为我认为在这种情况下这是不必要的吗?由于ModURLClassLoader定义了安全性。

为什么这不起作用,这意味着它仍会导致程序退出,而我想要一个AccessControlException

0 个答案:

没有答案