changeset 6332:41529646ab84

8008593: Better URLClassLoader resource management Reviewed-by: alanb, sherman, hawtin
author chegar
date Fri, 05 Apr 2013 18:12:11 +0100
parents 6c00e5d483b9
children 31c487a93b19
files make/java/zip/mapfile-vers make/java/zip/reorder-i586 make/java/zip/reorder-sparc make/java/zip/reorder-sparcv9 src/share/classes/java/util/zip/ZipFile.java src/share/classes/sun/misc/JavaUtilZipFileAccess.java src/share/classes/sun/misc/SharedSecrets.java src/share/classes/sun/misc/URLClassPath.java src/share/native/java/util/zip/ZipFile.c src/share/native/java/util/zip/zip_util.c src/share/native/java/util/zip/zip_util.h
diffstat 11 files changed, 105 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/zip/mapfile-vers	Fri Apr 05 08:43:00 2013 -0700
+++ b/make/java/zip/mapfile-vers	Fri Apr 05 18:12:11 2013 +0100
@@ -68,6 +68,7 @@
 		Java_java_util_zip_ZipFile_initIDs;
 		Java_java_util_zip_ZipFile_open;
 		Java_java_util_zip_ZipFile_read;
+		Java_java_util_zip_ZipFile_startsWithLOC;
 
 		ZIP_Close;
 		ZIP_CRC32;
--- a/make/java/zip/reorder-i586	Fri Apr 05 08:43:00 2013 -0700
+++ b/make/java/zip/reorder-i586	Fri Apr 05 18:12:11 2013 +0100
@@ -19,6 +19,7 @@
 text: .text%Java_java_util_zip_ZipFile_initIDs;
 text: .text%Java_java_util_zip_ZipFile_open;
 text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
 text: .text%Java_java_util_zip_ZipFile_getEntry;
 text: .text%Java_java_util_zip_ZipFile_freeEntry;
 text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/make/java/zip/reorder-sparc	Fri Apr 05 08:43:00 2013 -0700
+++ b/make/java/zip/reorder-sparc	Fri Apr 05 18:12:11 2013 +0100
@@ -18,6 +18,7 @@
 text: .text%Java_java_util_zip_ZipFile_initIDs;
 text: .text%Java_java_util_zip_ZipFile_open;
 text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
 text: .text%Java_java_util_zip_ZipFile_getEntry;
 text: .text%Java_java_util_zip_ZipFile_freeEntry;
 text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/make/java/zip/reorder-sparcv9	Fri Apr 05 08:43:00 2013 -0700
+++ b/make/java/zip/reorder-sparcv9	Fri Apr 05 18:12:11 2013 +0100
@@ -18,6 +18,7 @@
 text: .text%Java_java_util_zip_ZipFile_initIDs;
 text: .text%Java_java_util_zip_ZipFile_open;
 text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
 text: .text%Java_java_util_zip_ZipFile_getEntry;
 text: .text%Java_java_util_zip_ZipFile_freeEntry;
 text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/src/share/classes/java/util/zip/ZipFile.java	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/classes/java/util/zip/ZipFile.java	Fri Apr 05 18:12:11 2013 +0100
@@ -54,9 +54,10 @@
  */
 public
 class ZipFile implements ZipConstants, Closeable {
-    private long jzfile;  // address of jzfile data
-    private String name;  // zip file name
-    private int total;    // total number of entries
+    private long jzfile;           // address of jzfile data
+    private final String name;     // zip file name
+    private final int total;       // total number of entries
+    private final boolean locsig;  // if zip file starts with LOCSIG (usually true)
     private volatile boolean closeRequested = false;
 
     private static final int STORED = ZipEntry.STORED;
@@ -216,6 +217,7 @@
         sun.misc.PerfCounter.getZipFileCount().increment();
         this.name = name;
         this.total = getTotal(jzfile);
+        this.locsig = startsWithLOC(jzfile);
     }
 
     /**
@@ -737,10 +739,28 @@
         }
     }
 
+    static {
+        sun.misc.SharedSecrets.setJavaUtilZipFileAccess(
+            new sun.misc.JavaUtilZipFileAccess() {
+                public boolean startsWithLocHeader(ZipFile zip) {
+                    return zip.startsWithLocHeader();
+                }
+             }
+        );
+    }
+
+    /**
+     * Returns {@code true} if, and only if, the zip file begins with {@code
+     * LOCSIG}.
+     */
+    private boolean startsWithLocHeader() {
+        return locsig;
+    }
 
     private static native long open(String name, int mode, long lastModified,
                                     boolean usemmap) throws IOException;
     private static native int getTotal(long jzfile);
+    private static native boolean startsWithLOC(long jzfile);
     private static native int read(long jzfile, long jzentry,
                                    long pos, byte[] b, int off, int len);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/JavaUtilZipFileAccess.java	Fri Apr 05 18:12:11 2013 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.util.zip.ZipFile;
+
+public interface JavaUtilZipFileAccess {
+    public boolean startsWithLocHeader(ZipFile zip);
+}
--- a/src/share/classes/sun/misc/SharedSecrets.java	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/classes/sun/misc/SharedSecrets.java	Fri Apr 05 18:12:11 2013 +0100
@@ -56,6 +56,7 @@
     private static JavaSecurityAccess javaSecurityAccess;
     private static JavaxSecurityAuthKerberosAccess javaxSecurityAuthKerberosAccess;
     private static JavaUtilZipAccess javaUtilZipAccess;
+    private static JavaUtilZipFileAccess javaUtilZipFileAccess;
     private static JavaAWTAccess javaAWTAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -179,6 +180,16 @@
         return javaUtilZipAccess;
     }
 
+    public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
+        if (javaUtilZipFileAccess == null)
+            unsafe.ensureClassInitialized(java.util.zip.ZipFile.class);
+        return javaUtilZipFileAccess;
+    }
+
+    public static void setJavaUtilZipFileAccess(JavaUtilZipFileAccess access) {
+        javaUtilZipFileAccess = access;
+    }
+
     public static void setJavaAWTAccess(JavaAWTAccess jaa) {
         javaAWTAccess = jaa;
     }
--- a/src/share/classes/sun/misc/URLClassPath.java	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/classes/sun/misc/URLClassPath.java	Fri Apr 05 18:12:11 2013 +0100
@@ -63,12 +63,16 @@
     final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
     final static String JAVA_VERSION;
     private static final boolean DEBUG;
+    private static final boolean DISABLE_JAR_CHECKING;
 
     static {
         JAVA_VERSION = java.security.AccessController.doPrivileged(
             new sun.security.action.GetPropertyAction("java.version"));
         DEBUG        = (java.security.AccessController.doPrivileged(
             new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
+        String p = java.security.AccessController.doPrivileged(
+            new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
+        DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
     }
 
     /* The original search path of URLs. */
@@ -536,7 +540,7 @@
                      * in a hurry.
                      */
                     JarURLConnection juc = (JarURLConnection)uc;
-                    jarfile = juc.getJarFile();
+                    jarfile = JarLoader.checkJar(juc.getJarFile());
                 }
             } catch (Exception e) {
                 return null;
@@ -592,6 +596,8 @@
         private URLStreamHandler handler;
         private HashMap<String, Loader> lmap;
         private boolean closed = false;
+        private static final sun.misc.JavaUtilZipFileAccess zipAccess =
+                sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
 
         /*
          * Creates a new JarLoader for the specified URL referring to
@@ -696,6 +702,14 @@
             }
         }
 
+        /* Throws if the given jar file is does not start with the correct LOC */
+        static JarFile checkJar(JarFile jar) throws IOException {
+            if (System.getSecurityManager() != null && !DISABLE_JAR_CHECKING
+                && !zipAccess.startsWithLocHeader(jar))
+                throw new IOException("Invalid Jar file");
+            return jar;
+        }
+
         private JarFile getJarFile(URL url) throws IOException {
             // Optimize case where url refers to a local jar file
             if (isOptimizable(url)) {
@@ -703,11 +717,12 @@
                 if (!p.exists()) {
                     throw new FileNotFoundException(p.getPath());
                 }
-                return new JarFile (p.getPath());
+                return checkJar(new JarFile(p.getPath()));
             }
             URLConnection uc = getBaseURL().openConnection();
             uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
-            return ((JarURLConnection)uc).getJarFile();
+            JarFile jarFile = ((JarURLConnection)uc).getJarFile();
+            return checkJar(jarFile);
         }
 
         /*
--- a/src/share/native/java/util/zip/ZipFile.c	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/native/java/util/zip/ZipFile.c	Fri Apr 05 18:12:11 2013 +0100
@@ -136,6 +136,14 @@
     return zip->total;
 }
 
+JNIEXPORT jboolean JNICALL
+Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
+{
+    jzfile *zip = jlong_to_ptr(zfile);
+
+    return zip->locsig;
+}
+
 JNIEXPORT void JNICALL
 Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
 {
--- a/src/share/native/java/util/zip/zip_util.c	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/native/java/util/zip/zip_util.c	Fri Apr 05 18:12:11 2013 +0100
@@ -830,6 +830,14 @@
         return NULL;
     }
 
+    // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
+    if (readFully(zfd, errbuf, 4) != -1) {  // errors will be handled later
+        if (GETSIG(errbuf) == LOCSIG)
+            zip->locsig = JNI_TRUE;
+        else
+            zip->locsig = JNI_FALSE;
+    }
+
     len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
     if (len <= 0) {
         if (len == 0) { /* zip file is empty */
--- a/src/share/native/java/util/zip/zip_util.h	Fri Apr 05 08:43:00 2013 -0700
+++ b/src/share/native/java/util/zip/zip_util.h	Fri Apr 05 18:12:11 2013 +0100
@@ -210,6 +210,7 @@
                              start of the file. */
     jboolean usemmap;     /* if mmap is used. */
 #endif
+    jboolean locsig;      /* if zip file starts with LOCSIG */
     cencache cencache;    /* CEN header cache */
     ZFILE zfd;            /* open file descriptor */
     void *lock;           /* read lock */