public ProtectionDomain[] combine(ProtectionDomain[] current, ProtectionDomain[] assigned) { // Add a new ProtectionDomain with the null codesource/signers, and // the empty permission set, to the end of the array containing the // 'current' protections domains, i.e. the ones that will be augmented // with the permissions granted to the set of principals present in // the supplied subject. // ProtectionDomain[] newCurrent; if (current == null || current.length == 0) { newCurrent = new ProtectionDomain[1]; newCurrent[0] = pdNoPerms; } else { newCurrent = new ProtectionDomain[current.length + 1]; for (int i = 0; i < current.length; i++) { newCurrent[i] = current[i]; } newCurrent[current.length] = pdNoPerms; } return super.combine(newCurrent, assigned); }
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { byte[] byteCode = classfileBuffer; if (className.equals("beans/Sleeping")) { try { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("beans.Sleeping"); CtMethod m = cc.getDeclaredMethod("sleepNow"); m.addLocalVariable("elapsedTime", CtClass.longType); m.insertBefore("elapsedTime = System.currentTimeMillis();"); m.insertAfter("{elapsedTime = System.currentTimeMillis() - elapsedTime;" + "System.out.println(\"Method Executed in ms: \" + elapsedTime);}"); byteCode = cc.toBytecode(); cc.detach(); } catch (Exception ex) { ex.printStackTrace(); } } return byteCode; }
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if(className.startsWith(TransformConfig.getInstance().getPackageScan())) { logger.log(Level.INFO, "-------------------CLASS---------------------"); logger.log(Level.INFO, "className: " + className); ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ClassVisitor classVisitor = new HookClassAdapter(Opcodes.ASM5, cw); cr.accept(classVisitor, ClassReader.SKIP_FRAMES); // try { // FileOutputStream fos = new FileOutputStream(new File("classMod.class")); // fos.write(cw.toByteArray()); // fos.close(); // } catch (IOException e) { // e.printStackTrace(); // } return cw.toByteArray(); } return null; }
private static void checkPerm(PolicyFile p, ProtectionDomain pd) throws Exception { boolean foundIt = false; Enumeration perms = p.getPermissions(pd).elements(); while (perms.hasMoreElements()) { Permission perm = (Permission)perms.nextElement(); if (!(perm instanceof AllPermission)) { throw new SecurityException("expected AllPermission"); } else { foundIt = true; } } if (!foundIt) { throw new SecurityException("expected AllPermission"); } }
final void checkPackageAccess(Class<?> cls, ProtectionDomain pd) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ReflectUtil.isNonPublicProxyClass(cls)) { for (Class<?> intf: cls.getInterfaces()) { checkPackageAccess(intf, pd); } return; } final String name = cls.getName(); final int i = name.lastIndexOf('.'); if (i != -1) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { sm.checkPackageAccess(name.substring(0, i)); return null; } }, new AccessControlContext(new ProtectionDomain[] {pd})); } } domains.add(pd); }
public static void main(String[]args) throws Exception { final DomainCombiner dc = new DomainCombiner() { @Override public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains) { return currentDomains; // basically a no-op } }; // Get an instance of the saved ACC AccessControlContext saved = AccessController.getContext(); // Simulate the stack ACC with a DomainCombiner attached AccessControlContext stack = new AccessControlContext(AccessController.getContext(), dc); // Now try to run JavaSecurityAccess.doIntersectionPrivilege() and assert // whether the DomainCombiner from the stack ACC is preserved boolean ret = SharedSecrets.getJavaSecurityAccess().doIntersectionPrivilege(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return dc == AccessController.getContext().getDomainCombiner(); } }, stack, saved); if (!ret) { System.exit(1); } }
@Override public byte[] transform(ClassLoader loader, String internalClassName, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (internalClassName != null && classfileBuffer != null) { try { String className = internalClassName.replace('/', '.'); for (String prefix : ignores) if (className.startsWith(prefix)) return null; TransformHandle handle = new TransformHandle(className, classfileBuffer); units.forEach(handle::accept); if (handle.getResult().isPresent()) { byte[] classBuffer = handle.getResult().get(); if (debug) { saveClassFile(className, classBuffer); } return classBuffer; } else { return null; } } catch (Throwable e) { log("unable to transform {0}: {1}", internalClassName, e); e.printStackTrace(); } } return null; }
@Override public boolean implies(ProtectionDomain pd, Permission perm) { System.out.println("CustomPolicy.implies"); // If the protection domain is the same as CustomPolicy, then // we return true. This is to prevent recursive permission checks // that lead to StackOverflow errors when the policy implementation // performs a sensitive operation that triggers a permission check, // for example, as below. if (pd == policyPd) { return true; } // Do something that triggers a permission check to make sure that // we don't cause a StackOverflow error. String home = AccessController.doPrivileged( (PrivilegedAction<String>) () -> System.getProperty("user.home")); return true; }
private ClassLoader getClassLoader(final ObjectName name) { if(clr == null){ return null; } // Restrict to getClassLoader permission only Permissions permissions = new Permissions(); permissions.add(new MBeanPermission("*", null, name, "getClassLoader")); ProtectionDomain protectionDomain = new ProtectionDomain(null, permissions); ProtectionDomain[] domains = {protectionDomain}; AccessControlContext ctx = new AccessControlContext(domains); ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return clr.getClassLoader(name); } }, ctx); return loader; }
/** * create a context that can read any directories (recursively) * mentioned in the class path. In the case of a jar, it has to * be the directory containing the jar, not just the jar, as jar * files might refer to other jar files. */ private static AccessControlContext getContext(File[] cp) throws java.net.MalformedURLException { PathPermissions perms = new PathPermissions(cp); ProtectionDomain domain = new ProtectionDomain(new CodeSource(perms.getCodeBase(), (java.security.cert.Certificate[]) null), perms); AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] { domain }); return acc; }
private ClassLoader(Void unused, ClassLoader parent) { this.parent = parent; if (ParallelLoaders.isRegistered(this.getClass())) { parallelLockMap = new ConcurrentHashMap<>(); package2certs = new ConcurrentHashMap<>(); domains = Collections.synchronizedSet(new HashSet<ProtectionDomain>()); assertionLock = new Object(); } else { // no finer-grained lock; lock on the classloader instance parallelLockMap = null; package2certs = new Hashtable<>(); domains = new HashSet<>(); assertionLock = this; } }
private void attemptSetNullSecurityManager() { final Permissions permissions = new Permissions(); permissions.add(new RuntimePermission("setSecurityManager")); final AccessControlContext context = new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, permissions)}); AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { LOGGER.info("About to call System.setSecurityManager(null)"); System.setSecurityManager(null); LOGGER.info("Progressed beyond call to System.setSecurityManager(null)"); return null; } }, context); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if ("equals".equals(name)) { return proxy == args[0]; } else if ("hashCode".equals(name)) { return hashCode(); } else if ("toString".equals(name)) { return toString(); } else if ("transform".equals(name)) { return transform((ClassLoader) args[0], (String) args[1], (Class<?>) args[2], (ProtectionDomain) args[3], (byte[]) args[4]); } else if ("unregisterClassLoader".equals(name)) { unregisterClassLoader((ClassLoader) args[0]); return null; } else { throw new IllegalArgumentException("Unknown method: " + method); } }
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className.contains("TypeAnnotatedTestClass")) { try { // Here we remove and re-add the dummy fields. This shuffles the constant pool return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); } catch (Throwable e) { // The retransform native code that called this method does not propagate // exceptions. Instead of getting an uninformative generic error, catch // problems here and print it, then exit. e.printStackTrace(); System.exit(1); } } return null; }
private void postDefineClass(Class<?> c, ProtectionDomain pd) { if (pd.getCodeSource() != null) { Certificate certs[] = pd.getCodeSource().getCertificates(); if (certs != null) setSigners(c, certs); } }
Class defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) { return unsafe.defineClass(name, b, off, len, loader, protectionDomain); }
/** * This test will run both with and without a security manager. * * The test starts a number of threads that will call * LogManager.readConfiguration() concurrently (ReadConf), then starts * a number of threads that will create new loggers concurrently * (AddLogger), and then two additional threads: one (Stopper) that * will stop the test after 4secs (TIME ms), and one DeadlockDetector * that will attempt to detect deadlocks. * If after 4secs no deadlock was detected and no exception was thrown * then the test is considered a success and passes. * * This procedure is done twice: once without a security manager and once * again with a security manager - which means the test takes ~8secs to * run. * * Note that 8sec may not be enough to detect issues if there are some. * This is a best effort test. * * @param args the command line arguments * @throws java.lang.Exception if the test fails. */ public static void main(String[] args) throws Exception { File config = new File(System.getProperty("test.src", "."), "deadlockconf.properties"); if (!config.canRead()) { System.err.println("Can't read config file: test cannot execute."); System.err.println("Please check your test environment: "); System.err.println("\t -Dtest.src=" + System.getProperty("test.src", ".")); System.err.println("\t config file is: " + config.getAbsolutePath()); throw new RuntimeException("Can't read config file: " + config.getAbsolutePath()); } System.setProperty("java.util.logging.config.file", config.getAbsolutePath()); // test without security System.out.println("No security"); test(); // test with security System.out.println("\nWith security"); Policy.setPolicy(new Policy() { @Override public boolean implies(ProtectionDomain domain, Permission permission) { if (super.implies(domain, permission)) return true; // System.out.println("Granting " + permission); return true; // all permissions } }); System.setSecurityManager(new SecurityManager()); test(); }
public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { boolean redef = classBeingRedefined != null; System.out.println(trname + ": " + (redef? "Retransforming " : "Loading ") + className); if (className != null) { Options opt = new Options(); opt.shouldInstrumentNativeMethods = true; opt.trackerClassName = "bootreporter/StringIdCallbackReporter"; opt.wrappedTrackerMethodName = "tracker"; opt.fixedIndex = transformId; opt.wrappedPrefix = "wrapped_" + trname + "_"; try { byte[] newcf = Inject.instrumentation(opt, loader, className, classfileBuffer); return redef? null : newcf; } catch (Throwable ex) { System.err.println("ERROR: Injection failure: " + ex); ex.printStackTrace(); System.err.println("Returning bad class file, to cause test failure"); return new byte[0]; } } return null; }
/** * Get the AccessControlContext of the domain combiner created with * the supplied subject, i.e. an AccessControlContext with the domain * combiner created with the supplied subject and where the caller's * context has been removed. */ public static AccessControlContext getDomainCombinerContext(Subject subject) { return new AccessControlContext( new AccessControlContext(new ProtectionDomain[0]), new JMXSubjectDomainCombiner(subject)); }
/** * Loads specified JAR. * * @param jarFileInfo * @throws IOException */ private void loadJar(JarFileInfo jarFileInfo) throws IOException { lstJarFile.add(jarFileInfo); try { Enumeration<JarEntry> en = jarFileInfo.jarFile.entries(); final String EXT_JAR = ".jar"; while (en.hasMoreElements()) { JarEntry je = en.nextElement(); if (je.isDirectory()) { continue; } String s = je.getName().toLowerCase(); // JarEntry name if (s.lastIndexOf(EXT_JAR) == s.length() - EXT_JAR.length()) { JarEntryInfo inf = new JarEntryInfo(jarFileInfo, je); File fileTemp = createTempFile(inf); logInfo(LogArea.JAR, "Loading inner JAR %s from temp file %s", inf.jarEntry, getFilename4Log(fileTemp)); // Construct ProtectionDomain for this inner JAR: URL url = fileTemp.toURI().toURL(); ProtectionDomain pdParent = jarFileInfo.pd; // 'csParent' is never null: top JAR has it, JCL creates it for child JAR: CodeSource csParent = pdParent.getCodeSource(); Certificate[] certParent = csParent.getCertificates(); CodeSource csChild = (certParent == null ? new CodeSource(url, csParent.getCodeSigners()) : new CodeSource(url, certParent)); ProtectionDomain pdChild = new ProtectionDomain(csChild, pdParent.getPermissions(), pdParent.getClassLoader(), pdParent.getPrincipals()); loadJar(new JarFileInfo( new JarFile(fileTemp), inf.getName(), jarFileInfo, pdChild, fileTemp)); } } } catch (JarClassLoaderException e) { throw new RuntimeException( "ERROR on loading inner JAR: " + e.getMessageAll()); } }
private StaticClass getClassAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) { JavaAdapterServices.setClassOverrides(classOverrides); try { return classAdapterGenerator.generateClass(commonLoader, protectionDomain); } finally { JavaAdapterServices.setClassOverrides(null); } }
private ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain, final BaseData data) { return new ClasspathEntry(bundlefile, createProtectionDomain(bundlefile, cpDomain)) { @Override public BaseData getBaseData() { return data; } }; }
private static String printDomain(final ProtectionDomain pd) { if (pd == null) { return "null"; } return AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() { return pd.toString(); } }); }
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { /* The Daemon Thread bug is timing dependent and you want the transform method * to return ASAP - so just return the buffer will be fine */ return classfileBuffer; }
/** * * @param className * @param clsByte * @return */ public Class<?> findClass(String className, byte[] clsByte, URL url) { Class<?> cls = null; try { CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[]) null); ProtectionDomain pd = new ProtectionDomain(cs, null, this, null); cls = super.defineClass(className, clsByte, 0, clsByte.length, pd); resolveClass(cls); classCache.put(className, cls); } catch (Exception ex) { logger.error("define class error", ex); } return cls; }
@Override public boolean implies(ProtectionDomain domain, Permission permission) { if (permName.equals(permission.getName())) { System.out.println("---MyPolicy-implies checks permission for " +permName+" and returns "+allowed); return allowed; } else { return true; } }
public static void main(String... args) throws Throwable { boolean sm = false; if (args.length > 0 && args[0].equals("sm")) { sm = true; PermissionCollection perms = new Permissions(); perms.add(new RuntimePermission("getStackWalkerWithClassReference")); Policy.setPolicy(new Policy() { @Override public boolean implies(ProtectionDomain domain, Permission p) { return perms.implies(p); } }); System.setSecurityManager(new SecurityManager()); } System.err.format("Test %s security manager.%n", sm ? "with" : "without"); CallerSensitiveTest cstest = new CallerSensitiveTest(); // test static call to java.util.CSM::caller and CSM::getCallerClass cstest.staticMethodCall(); // test java.lang.reflect.Method call cstest.reflectMethodCall(); // test java.lang.invoke.MethodHandle cstest.invokeMethodHandle(Lookup1.lookup); cstest.invokeMethodHandle(Lookup2.lookup); // test method ref cstest.lambda(); LambdaTest.lambda(); if (failed > 0) { throw new RuntimeException(failed + " test cases failed."); } }
public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { boolean redef = classBeingRedefined != null; System.out.println(trname + ": " + (redef? "Retransforming " : "Loading ") + className); if (className != null) { try { byte[] newcf = Instrumentor.instrFor(classfileBuffer) .addNativeMethodTrackingInjection( "wrapped_" + trname + "_", (h)->{ h.push(h.getName()); h.push(transformId); h.invokeStatic("bootreporter/StringIdCallbackReporter", "tracker", "(Ljava/lang/String;I)V", false); }) .apply(); /*** debugging ... if (newcf != null) { String fname = trname + (redef?"_redef" : "") + "/" + className; System.err.println("dumping to: " + fname); write_buffer(fname + "_before.class", classfileBuffer); write_buffer(fname + "_instr.class", newcf); } ***/ return redef? null : newcf; } catch (Throwable ex) { System.err.println("ERROR: Injection failure: " + ex); ex.printStackTrace(); System.err.println("Returning bad class file, to cause test failure"); return new byte[0]; } } return null; }
public void testListen() { assumeTrue("test cannot run with security manager", System.getSecurityManager() == null); final PermissionCollection noPermissions = new Permissions(); final ESPolicy policy = new ESPolicy(noPermissions, Collections.emptyMap(), true); assertFalse( policy.implies( new ProtectionDomain(ESPolicyUnitTests.class.getProtectionDomain().getCodeSource(), noPermissions), new SocketPermission("localhost:" + randomFrom(0, randomIntBetween(49152, 65535)), "listen"))); }
private static void checkPerm(PolicyFile p, ProtectionDomain pd) throws Exception { boolean foundIt = false; Enumeration perms = p.getPermissions(pd).elements(); while (perms.hasMoreElements()) { Permission perm = (Permission)perms.nextElement(); if (perm instanceof AllPermission) { foundIt = true; break; } } if (!foundIt) { throw new SecurityException("expected AllPermission"); } }
static AccessControlContext createPermAccCtxt(final String... permNames) { final Permissions perms = new Permissions(); for (final String permName : permNames) { perms.add(new RuntimePermission(permName)); } return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) }); }
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain pd, byte[] classFile) throws IllegalClassFormatException { if (isLibraryClass(className)) return null; debugMessage("Transforming: " + className + " [loader=" + loader + ']'); // Save original bytecode. if (saveBytecode) debugWriteClass(className + ".orig", classFile); ClassReader reader = new ClassReader(classFile); // If using COMPUTE_FRAMES, also enable the JSRInlinerAdapter // in CtxEnhancherAdapter. int wFlags = ClassWriter.COMPUTE_MAXS; // | ClassWriter.COMPUTE_FRAMES; ClassWriter writer = new ContextClassWriter(loader, wFlags); ClassVisitor ctxAdapter = new CtxEnhancherAdapter(writer, className, optInstrumentCGE, loader); try { ClassNode cn = new ClassNode(Opcodes.ASM5); reader.accept(cn, ClassReader.EXPAND_FRAMES); cn.accept(ctxAdapter); } catch (RuntimeException ex) { System.err.println(CTXT_AGENT + "ASM error visiting class " + className); ex.printStackTrace(); System.exit(-1); } byte[] ret = writer.toByteArray(); // Save transformed bytecode. if (saveBytecode) debugWriteClass(className, ret); // Check bytecode for correctness. if (debug) checkBytecode(loader, className, ret, wFlags); return ret; }
/** * Tells the VM to define a class, without security checks. By default, the * class loader and protection domain come from the caller's class. */ @ForceInline public Class<?> defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) { return theInternalUnsafe.defineClass(name, b, off, len, loader, protectionDomain); }
/** * Tells the VM to define a class, without security checks. By default, the * class loader and protection domain come from the caller's class. */ public Class<?> defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) { if (b == null) { throw new NullPointerException(); } if (len < 0) { throw new ArrayIndexOutOfBoundsException(); } return defineClass0(name, b, off, len, loader, protectionDomain); }
/** * Tests loading a class from a jar. */ @Test public void testLoadingFilterPlugin() throws ClassNotFoundException, IllegalAccessException, InstantiationException { // Get URL to our jar final URL jar = getClass().getClassLoader().getResource("testDeserializer/testPlugins.jar"); final String classPath = "examples.filter.LowOffsetFilter"; // Create class loader final PluginClassLoader pluginClassLoader = new PluginClassLoader(jar, getClass().getClassLoader()); final Class<? extends RecordFilter> filterPlugin = (Class<? extends RecordFilter>) pluginClassLoader.loadClass(classPath); assertNotNull("Should not be null", filterPlugin); // Create an instance of it and validate. final RecordFilter filter = filterPlugin.newInstance(); final String topic = "MyTopic"; final int partition = 2; final long offset = 2423L; final Object key = "key"; final Object value = "{name='Bob', value='value'}"; filter.includeRecord(topic, partition, offset, key, value); // Validate it came from our classloader, more of a sanity test. assertTrue("Should have our parent class loader", filter.getClass().getClassLoader() instanceof PluginClassLoader); // Validate permission set defined final ProtectionDomain protectionDomain = filter.getClass().getProtectionDomain(); final PermissionCollection permissionCollection = protectionDomain.getPermissions(); assertTrue("Should have read only permissions", permissionCollection.isReadOnly()); }
private static ProtectionDomain createMinimalPermissionDomain() { // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages. final Permissions permissions = new Permissions(); permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.objects")); permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime")); permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker")); return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions); }
@Override public PermissionCollection getPermissions(ProtectionDomain domain) { return new PermissionsBuilder().addAll( allowAll.get().get() ? allPermissions : allowControl.get().get() ? withControlPermissions : permissions).toPermissions(); }
@Override public byte[] transform(ClassLoader cl, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (Intrinsic.class.equals(classBeingRedefined)) { String cf = new String(classfileBuffer); int i = cf.indexOf("intrinsic"); Assert.assertTrue("cannot find \"intrinsic\" constant in " + Intrinsic.class.getSimpleName() + "'s class file", i > 0); System.arraycopy("redefined".getBytes(), 0, classfileBuffer, i, "redefined".length()); } return classfileBuffer; }