7003952: SEC: securely load DLLs and launch executables using fully qualified path
authorvaleriep
Tue, 26 Apr 2011 15:59:51 -0700
changeset 9849 eb437e9fba66
parent 9848 1631321017da
child 9851 23bd656b112e
7003952: SEC: securely load DLLs and launch executables using fully qualified path Summary: Enforce full path when specifying library locations. Reviewed-by: wetmore, ohair
jdk/make/sun/security/pkcs11/Makefile
jdk/src/share/classes/sun/security/pkcs11/Config.java
jdk/src/share/classes/sun/security/pkcs11/Secmod.java
jdk/src/share/native/sun/security/pkcs11/j2secmod.c
jdk/test/sun/security/pkcs11/Provider/Absolute.cfg
jdk/test/sun/security/pkcs11/Provider/Absolute.java
--- a/jdk/make/sun/security/pkcs11/Makefile	Thu Apr 21 16:42:06 2011 -0700
+++ b/jdk/make/sun/security/pkcs11/Makefile	Tue Apr 26 15:59:51 2011 -0700
@@ -147,7 +147,7 @@
 # Rules
 #
 CLASSDESTDIR = $(TEMPDIR)/classes
-JAVAHFLAGS += -classpath $(CLASSDESTDIR)
+JAVAHFLAGS += -Xbootclasspath/p:$(CLASSDESTDIR)
 
 include $(BUILDDIR)/common/Mapfile-vers.gmk
 
--- a/jdk/src/share/classes/sun/security/pkcs11/Config.java	Thu Apr 21 16:42:06 2011 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs11/Config.java	Tue Apr 26 15:59:51 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -653,6 +653,13 @@
             }
         }
         debug(keyword + ": " + lib);
+
+        // Check to see if full path is specified to prevent the DLL
+        // preloading attack
+        if (!(new File(lib)).isAbsolute()) {
+            throw new ConfigurationException(
+                "Absolute path required for library value: " + lib);
+        }
         return lib;
     }
 
--- a/jdk/src/share/classes/sun/security/pkcs11/Secmod.java	Thu Apr 21 16:42:06 2011 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs11/Secmod.java	Tue Apr 26 15:59:51 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -236,7 +236,8 @@
             throw new IllegalStateException(e);
         }
         if (modules == null) {
-            List<Module> modules = (List<Module>)nssGetModuleList(nssHandle);
+            List<Module> modules = (List<Module>)nssGetModuleList(nssHandle,
+                nssLibDir);
             this.modules = Collections.unmodifiableList(modules);
         }
         return modules;
@@ -358,7 +359,7 @@
      * A representation of one PKCS#11 slot in a PKCS#11 module.
      */
     public static final class Module {
-        // name of the native library
+        // path of the native library
         final String libraryName;
         // descriptive name used by NSS
         final String commonName;
@@ -371,8 +372,10 @@
         // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only
         private Map<Bytes,TrustAttributes> trust;
 
-        Module(String libraryName, String commonName, boolean fips, int slot) {
+        Module(String libraryDir, String libraryName, String commonName,
+                boolean fips, int slot) {
             ModuleType type;
+
             if ((libraryName == null) || (libraryName.length() == 0)) {
                 // must be softtoken
                 libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME);
@@ -397,7 +400,7 @@
                         + "module: " + libraryName + ", " + commonName);
                 }
             }
-            this.libraryName = libraryName;
+            this.libraryName = (new File(libraryDir, libraryName)).getPath();
             this.commonName = commonName;
             this.slot = slot;
             this.type = type;
@@ -752,6 +755,6 @@
 
     private static native boolean nssInit(String functionName, long handle, String configDir);
 
-    private static native Object nssGetModuleList(long handle);
+    private static native Object nssGetModuleList(long handle, String libDir);
 
 }
--- a/jdk/src/share/native/sun/security/pkcs11/j2secmod.c	Thu Apr 21 16:42:06 2011 -0700
+++ b/jdk/src/share/native/sun/security/pkcs11/j2secmod.c	Tue Apr 26 15:59:51 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -74,7 +74,7 @@
 }
 
 JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_Secmod_nssGetModuleList
-  (JNIEnv *env, jclass thisClass, jlong jHandle)
+  (JNIEnv *env, jclass thisClass, jlong jHandle, jstring jLibDir)
 {
     FPTR_GetDBModuleList getModuleList =
         (FPTR_GetDBModuleList)findFunction(env, jHandle, "SECMOD_GetDefaultModuleList");
@@ -104,8 +104,8 @@
     jList = (*env)->NewObject(env, jListClass, jListConstructor);
 
     jModuleClass = (*env)->FindClass(env, "sun/security/pkcs11/Secmod$Module");
-    jModuleConstructor = (*env)->GetMethodID
-        (env, jModuleClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;ZI)V");
+    jModuleConstructor = (*env)->GetMethodID(env, jModuleClass, "<init>",
+        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V");
 
     while (list != NULL) {
         module = list->module;
@@ -124,7 +124,8 @@
         }
         jFIPS = module->isFIPS;
         for (i = 0; i < module->slotCount; i++ ) {
-            jModule = (*env)->NewObject(env, jModuleClass, jModuleConstructor, jDllName, jCommonName, jFIPS, i);
+            jModule = (*env)->NewObject(env, jModuleClass, jModuleConstructor,
+                jLibDir, jDllName, jCommonName, jFIPS, i);
             (*env)->CallVoidMethod(env, jList, jAdd, jModule);
         }
         list = list->next;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Provider/Absolute.cfg	Tue Apr 26 15:59:51 2011 -0700
@@ -0,0 +1,10 @@
+#
+# Configuration file to allow the SunPKCS11 provider to utilize
+# the Solaris Cryptographic Framework, if it is available
+#
+
+name = Absolute
+
+description = SunPKCS11 using a relative path
+
+library = ./libpkcs11.so
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Provider/Absolute.java	Tue Apr 26 15:59:51 2011 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.
+ */
+/**
+ * @test
+ * @bug 7003952
+ * @summary load DLLs and launch executables using fully qualified path
+ */
+import java.security.*;
+import java.lang.reflect.*;
+import sun.security.pkcs11.*;
+
+public class Absolute {
+
+    public static void main(String[] args) throws Exception {
+        Constructor cons;
+        try {
+            Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11");
+            cons = clazz.getConstructor(new Class[] {String.class});
+        } catch (Exception ex) {
+            System.out.println("Skipping test - no PKCS11 provider available");
+            return;
+        }
+
+        String config =
+            System.getProperty("test.src", ".") + "/Absolute.cfg";
+
+        try {
+            Object obj = cons.newInstance(new Object[] {config});
+        } catch (InvocationTargetException ite) {
+            Throwable cause = ite.getCause();
+            if (cause instanceof ProviderException) {
+                Throwable cause2 = cause.getCause();
+                if ((cause2 == null) ||
+                    !cause2.getMessage().startsWith(
+                         "Absolute path required for library value:")) {
+                    // rethrow
+                    throw (ProviderException) cause;
+                }
+                System.out.println("Caught expected Exception: \n" + cause2);
+            }
+        }
+    }
+}