8151934: Resolve class resolution
authorchegar
Thu, 28 Jul 2016 10:13:12 +0100
changeset 43196 2064adad356a
parent 43195 e7f80841643d
child 43197 883675f526b8
8151934: Resolve class resolution Reviewed-by: alanb, skoivu
jdk/src/java.base/share/classes/java/net/URLClassLoader.java
jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Wed Jul 27 02:23:16 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Thu Jul 28 10:13:12 2016 +0100
@@ -115,8 +115,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, acc);
     }
 
     URLClassLoader(String name, URL[] urls, ClassLoader parent,
@@ -127,8 +127,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls);
         this.acc = acc;
+        this.ucp = new URLClassPath(urls, acc);
     }
 
     /**
@@ -159,8 +159,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, acc);
     }
 
     URLClassLoader(URL[] urls, AccessControlContext acc) {
@@ -170,8 +170,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls);
         this.acc = acc;
+        this.ucp = new URLClassPath(urls, acc);
     }
 
     /**
@@ -203,8 +203,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls, factory);
         this.acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, factory, acc);
     }
 
 
@@ -238,8 +238,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, acc);
     }
 
     /**
@@ -271,8 +271,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        this.ucp = new URLClassPath(urls, factory);
         this.acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, factory, acc);
     }
 
     /* A map (used as a set) to keep track of closeable local resources
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Wed Jul 27 02:23:16 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Thu Jul 28 10:13:12 2016 +0100
@@ -38,6 +38,7 @@
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.net.URLStreamHandlerFactory;
+import java.security.AccessControlContext;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.security.CodeSigner;
@@ -83,6 +84,7 @@
     private static final String JAVA_VERSION;
     private static final boolean DEBUG;
     private static final boolean DISABLE_JAR_CHECKING;
+    private static final boolean DISABLE_ACC_CHECKING;
 
     static {
         Properties props = GetPropertyAction.privilegedGetProperties();
@@ -90,6 +92,9 @@
         DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
         String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
         DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+        p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions");
+        DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
     }
 
     /* The original search path of URLs. */
@@ -110,6 +115,11 @@
     /* Whether this URLClassLoader has been closed yet */
     private boolean closed = false;
 
+    /* The context to be used when loading classes and resources.  If non-null
+     * this is the context that was captured during the creation of the
+     * URLClassLoader. null implies no additional security restrictions. */
+    private final AccessControlContext acc;
+
     /**
      * Creates a new URLClassPath for the given URLs. The URLs will be
      * searched in the order specified for classes and resources. A URL
@@ -119,8 +129,12 @@
      * @param urls the directory and JAR file URLs to search for classes
      *        and resources
      * @param factory the URLStreamHandlerFactory to use when creating new URLs
+     * @param acc the context to be used when loading classes and resources, may
+     *            be null
      */
-    public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+    public URLClassPath(URL[] urls,
+                        URLStreamHandlerFactory factory,
+                        AccessControlContext acc) {
         for (int i = 0; i < urls.length; i++) {
             path.add(urls[i]);
         }
@@ -128,10 +142,22 @@
         if (factory != null) {
             jarHandler = factory.createURLStreamHandler("jar");
         }
+        if (DISABLE_ACC_CHECKING)
+            this.acc = null;
+        else
+            this.acc = acc;
     }
 
+    /**
+     * Constructs a URLClassPath with no additional security restrictions.
+     * Used by code that implements the class path.
+     */
     public URLClassPath(URL[] urls) {
-        this(urls, null);
+        this(urls, null, null);
+    }
+
+    public URLClassPath(URL[] urls, AccessControlContext acc) {
+        this(urls, null, acc);
     }
 
     public synchronized List<IOException> closeLoaders() {
@@ -356,6 +382,14 @@
             } catch (IOException e) {
                 // Silently ignore for now...
                 continue;
+            } catch (SecurityException se) {
+                // Always silently ignore. The context, if there is one, that
+                // this URLClassPath was given during construction will never
+                // have permission to access the URL.
+                if (DEBUG) {
+                    System.err.println("Failed to access " + url + ", " + se );
+                }
+                continue;
             }
             // Finally, add the Loader to the search path.
             loaders.add(loader);
@@ -378,7 +412,7 @@
                             && file != null && (file.indexOf("!/") == file.length() - 2)) {
                         // extract the nested URL
                         URL nestedUrl = new URL(file.substring(0, file.length() - 2));
-                        return new JarLoader(nestedUrl, jarHandler, lmap);
+                        return new JarLoader(nestedUrl, jarHandler, lmap, acc);
                     } else if (file != null && file.endsWith("/")) {
                         if ("file".equals(protocol)) {
                             return new FileLoader(url);
@@ -386,10 +420,10 @@
                             return new Loader(url);
                         }
                     } else {
-                        return new JarLoader(url, jarHandler, lmap);
+                        return new JarLoader(url, jarHandler, lmap, acc);
                     }
                 }
-            });
+            }, acc);
         } catch (java.security.PrivilegedActionException pae) {
             throw (IOException)pae.getException();
         }
@@ -585,10 +619,11 @@
      */
     static class JarLoader extends Loader {
         private JarFile jar;
-        private URL csu;
+        private final URL csu;
         private JarIndex index;
         private URLStreamHandler handler;
-        private HashMap<String, Loader> lmap;
+        private final HashMap<String, Loader> lmap;
+        private final AccessControlContext acc;
         private boolean closed = false;
         private static final JavaUtilZipFileAccess zipAccess =
                 SharedSecrets.getJavaUtilZipFileAccess();
@@ -598,13 +633,15 @@
          * a JAR file.
          */
         JarLoader(URL url, URLStreamHandler jarHandler,
-                  HashMap<String, Loader> loaderMap)
+                  HashMap<String, Loader> loaderMap,
+                  AccessControlContext acc)
             throws IOException
         {
             super(new URL("jar", "", -1, url + "!/", jarHandler));
             csu = url;
             handler = jarHandler;
             lmap = loaderMap;
+            this.acc = acc;
 
             ensureOpen();
         }
@@ -663,8 +700,7 @@
                                 }
                                 return null;
                             }
-                        }
-                    );
+                        }, acc);
                 } catch (java.security.PrivilegedActionException pae) {
                     throw (IOException)pae.getException();
                 }
@@ -859,9 +895,9 @@
                                 new PrivilegedExceptionAction<>() {
                                     public JarLoader run() throws IOException {
                                         return new JarLoader(url, handler,
-                                            lmap);
+                                            lmap, acc);
                                     }
-                                });
+                                }, acc);
 
                             /* this newly opened jar file has its own index,
                              * merge it into the parent's index, taking into
--- a/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java	Wed Jul 27 02:23:16 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java	Thu Jul 28 10:13:12 2016 +0100
@@ -29,6 +29,7 @@
 import java.util.*;
 import java.util.jar.*;
 import java.util.zip.*;
+import static sun.security.action.GetPropertyAction.privilegedGetProperty;
 
 /**
  * This class is used to maintain mappings from packages, classes
@@ -72,7 +73,7 @@
      * be added to the index. Otherwise, just the directory names are added.
      */
     private static final boolean metaInfFilenames =
-        "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+        "true".equals(privilegedGetProperty("sun.misc.JarIndex.metaInfFilenames"));
 
     /**
      * Constructs a new, empty jar index.