8075545: Add permission check for locale service provider implementations
authornaoto
Wed, 29 Apr 2015 11:03:56 -0700
changeset 30047 63b6a16968d5
parent 30046 cf2c86e1819e
child 30048 3424bede284d
8075545: Add permission check for locale service provider implementations Reviewed-by: mchung, alanb
jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java
jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
jdk/test/java/util/PluggableLocale/ExecTest.sh
jdk/test/java/util/PluggableLocale/PermissionTest.java
jdk/test/java/util/PluggableLocale/PermissionTest.sh
jdk/test/java/util/PluggableLocale/localeServiceProvider.policy
--- a/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java	Wed Apr 29 10:25:53 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java	Wed Apr 29 11:03:56 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, 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
@@ -140,11 +140,24 @@
  */
 public abstract class LocaleServiceProvider {
 
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("localeServiceProvider"));
+        }
+        return null;
+    }
+    private LocaleServiceProvider(Void ignore) { }
+
     /**
-     * Sole constructor.  (For invocation by subclass constructors, typically
-     * implicit.)
+     * Initializes a new locale service provider.
+     *
+     * @throws  SecurityException
+     *          If a security manager has been installed and it denies
+     *          {@link RuntimePermission RuntimePermission("localeServiceProvider")}
      */
     protected LocaleServiceProvider() {
+        this(checkPermission());
     }
 
     /**
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Wed Apr 29 10:25:53 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Wed Apr 29 11:03:56 2015 -0700
@@ -25,6 +25,8 @@
 
 package sun.util.locale.provider;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.spi.BreakIteratorProvider;
 import java.text.spi.CollatorProvider;
 import java.text.spi.DateFormatProvider;
@@ -177,7 +179,9 @@
      * A dummy locale service provider that indicates there is no
      * provider available
      */
-    private static final NullProvider NULL_PROVIDER = new NullProvider();
+    private static final NullProvider NULL_PROVIDER = AccessController.doPrivileged(
+        (PrivilegedAction<NullProvider>) () -> new NullProvider());
+
     private static class NullProvider extends LocaleServiceProvider {
         @Override
         public Locale[] getAvailableLocales() {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Wed Apr 29 10:25:53 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Wed Apr 29 11:03:56 2015 -0700
@@ -26,7 +26,7 @@
 package sun.util.locale.provider;
 
 import java.security.AccessController;
-import java.security.PrivilegedActionException;
+import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.text.spi.BreakIteratorProvider;
 import java.text.spi.CollatorProvider;
@@ -133,8 +133,12 @@
     @Override
     public BreakIteratorProvider getBreakIteratorProvider() {
         if (breakIteratorProvider == null) {
-            BreakIteratorProvider provider = new BreakIteratorProviderImpl(getAdapterType(),
-                                                            getLanguageTagSet("FormatData"));
+            BreakIteratorProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<BreakIteratorProvider>) () ->
+                    new BreakIteratorProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (breakIteratorProvider == null) {
                     breakIteratorProvider = provider;
@@ -147,8 +151,12 @@
     @Override
     public CollatorProvider getCollatorProvider() {
         if (collatorProvider == null) {
-            CollatorProvider provider = new CollatorProviderImpl(getAdapterType(),
-                                                getLanguageTagSet("CollationData"));
+            CollatorProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<CollatorProvider>) () ->
+                    new CollatorProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("CollationData")));
+
             synchronized (this) {
                 if (collatorProvider == null) {
                     collatorProvider = provider;
@@ -161,8 +169,12 @@
     @Override
     public DateFormatProvider getDateFormatProvider() {
         if (dateFormatProvider == null) {
-            DateFormatProvider provider = new DateFormatProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("FormatData"));
+            DateFormatProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<DateFormatProvider>) () ->
+                    new DateFormatProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (dateFormatProvider == null) {
                     dateFormatProvider = provider;
@@ -175,8 +187,12 @@
     @Override
     public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
         if (dateFormatSymbolsProvider == null) {
-            DateFormatSymbolsProvider provider = new DateFormatSymbolsProviderImpl(getAdapterType(),
-                                                                getLanguageTagSet("FormatData"));
+            DateFormatSymbolsProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<DateFormatSymbolsProvider>) () ->
+                    new DateFormatSymbolsProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (dateFormatSymbolsProvider == null) {
                     dateFormatSymbolsProvider = provider;
@@ -189,7 +205,12 @@
     @Override
     public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
         if (decimalFormatSymbolsProvider == null) {
-            DecimalFormatSymbolsProvider provider = new DecimalFormatSymbolsProviderImpl(getAdapterType(), getLanguageTagSet("FormatData"));
+            DecimalFormatSymbolsProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<DecimalFormatSymbolsProvider>) () ->
+                    new DecimalFormatSymbolsProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (decimalFormatSymbolsProvider == null) {
                     decimalFormatSymbolsProvider = provider;
@@ -202,8 +223,12 @@
     @Override
     public NumberFormatProvider getNumberFormatProvider() {
         if (numberFormatProvider == null) {
-            NumberFormatProvider provider = new NumberFormatProviderImpl(getAdapterType(),
-                                                        getLanguageTagSet("FormatData"));
+            NumberFormatProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<NumberFormatProvider>) () ->
+                    new NumberFormatProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (numberFormatProvider == null) {
                     numberFormatProvider = provider;
@@ -219,8 +244,12 @@
     @Override
     public CurrencyNameProvider getCurrencyNameProvider() {
         if (currencyNameProvider == null) {
-            CurrencyNameProvider provider = new CurrencyNameProviderImpl(getAdapterType(),
-                                            getLanguageTagSet("CurrencyNames"));
+            CurrencyNameProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<CurrencyNameProvider>) () ->
+                    new CurrencyNameProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("CurrencyNames")));
+
             synchronized (this) {
                 if (currencyNameProvider == null) {
                     currencyNameProvider = provider;
@@ -233,8 +262,12 @@
     @Override
     public LocaleNameProvider getLocaleNameProvider() {
         if (localeNameProvider == null) {
-            LocaleNameProvider provider = new LocaleNameProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("LocaleNames"));
+            LocaleNameProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<LocaleNameProvider>) () ->
+                    new LocaleNameProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("LocaleNames")));
+
             synchronized (this) {
                 if (localeNameProvider == null) {
                     localeNameProvider = provider;
@@ -247,8 +280,12 @@
     @Override
     public TimeZoneNameProvider getTimeZoneNameProvider() {
         if (timeZoneNameProvider == null) {
-            TimeZoneNameProvider provider = new TimeZoneNameProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("TimeZoneNames"));
+            TimeZoneNameProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<TimeZoneNameProvider>) () ->
+                    new TimeZoneNameProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("TimeZoneNames")));
+
             synchronized (this) {
                 if (timeZoneNameProvider == null) {
                     timeZoneNameProvider = provider;
@@ -261,9 +298,12 @@
     @Override
     public CalendarDataProvider getCalendarDataProvider() {
         if (calendarDataProvider == null) {
-            CalendarDataProvider provider;
-            provider = new CalendarDataProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("CalendarData"));
+            CalendarDataProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<CalendarDataProvider>) () ->
+                    new CalendarDataProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("CalendarData")));
+
             synchronized (this) {
                 if (calendarDataProvider == null) {
                     calendarDataProvider = provider;
@@ -276,9 +316,12 @@
     @Override
     public CalendarNameProvider getCalendarNameProvider() {
         if (calendarNameProvider == null) {
-            CalendarNameProvider provider;
-            provider = new CalendarNameProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("FormatData"));
+            CalendarNameProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<CalendarNameProvider>) () ->
+                    new CalendarNameProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("FormatData")));
+
             synchronized (this) {
                 if (calendarNameProvider == null) {
                     calendarNameProvider = provider;
@@ -294,8 +337,12 @@
     @Override
     public CalendarProvider getCalendarProvider() {
         if (calendarProvider == null) {
-            CalendarProvider provider = new CalendarProviderImpl(getAdapterType(),
-                                                    getLanguageTagSet("CalendarData"));
+            CalendarProvider provider = AccessController.doPrivileged(
+                (PrivilegedAction<CalendarProvider>) () ->
+                    new CalendarProviderImpl(
+                        getAdapterType(),
+                        getLanguageTagSet("CalendarData")));
+
             synchronized (this) {
                 if (calendarProvider == null) {
                     calendarProvider = provider;
@@ -319,6 +366,7 @@
     }
 
     // ResourceBundleBasedAdapter method implementation
+
     @Override
     public LocaleData getLocaleData() {
         if (localeData == null) {
@@ -449,4 +497,4 @@
         }
         return locales;
     }
-                            }
+}
--- a/jdk/test/java/util/PluggableLocale/ExecTest.sh	Wed Apr 29 10:25:53 2015 -0700
+++ b/jdk/test/java/util/PluggableLocale/ExecTest.sh	Wed Apr 29 11:03:56 2015 -0700
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2015, 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
@@ -33,7 +33,7 @@
 # Parameters:
 #    providersToTest: [foo|bar|foobar]
 #    java class name: <class name>
-#    providersInExtDir: [true|false]
+#    java security policy file: (Optional. Installs security manager if exists)
 
 if [ "${TESTSRC}" = "" ]
 then
@@ -113,8 +113,14 @@
   exit $result
 fi
 
+# security options
+if [ "$3" != "" ]
+then
+  SECURITYOPTS="-Djava.security.manager -Djava.security.policy=${TESTSRC}${FS}$3"
+fi
+
 # run
-RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${CLASSPATHARG} $2 "
+RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${SECURITYOPTS} -classpath ${CLASSPATHARG} $2 "
 
 echo ${RUNCMD}
 ${RUNCMD}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/PermissionTest.java	Wed Apr 29 11:03:56 2015 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+/*
+ *
+ */
+public class PermissionTest{
+
+    //  Make sure provider impls can be instantiated under a security manager.ZZ
+    com.foo.BreakIteratorProviderImpl breakIP = new com.foo.BreakIteratorProviderImpl();
+    com.foo.CollatorProviderImpl collatorP = new com.foo.CollatorProviderImpl();
+    com.foo.DateFormatProviderImpl dateFP = new com.foo.DateFormatProviderImpl();
+    com.foo.DateFormatSymbolsProviderImpl dateFSP = new com.foo.DateFormatSymbolsProviderImpl();
+    com.foo.DecimalFormatSymbolsProviderImpl decimalFSP = new com.foo.DecimalFormatSymbolsProviderImpl();
+    com.foo.NumberFormatProviderImpl numberFP = new com.foo.NumberFormatProviderImpl();
+    com.bar.CurrencyNameProviderImpl currencyNP = new com.bar.CurrencyNameProviderImpl();
+    com.bar.CurrencyNameProviderImpl2 currencyNP2 = new com.bar.CurrencyNameProviderImpl2();
+    com.bar.LocaleNameProviderImpl localeNP = new com.bar.LocaleNameProviderImpl();
+    com.bar.TimeZoneNameProviderImpl tzNP = new com.bar.TimeZoneNameProviderImpl();
+    com.bar.GenericTimeZoneNameProviderImpl tzGenNP = new com.bar.GenericTimeZoneNameProviderImpl();
+    com.bar.CalendarDataProviderImpl calDataP = new com.bar.CalendarDataProviderImpl();
+    com.bar.CalendarNameProviderImpl calNameP = new com.bar.CalendarNameProviderImpl();
+
+    public static void main(String[] s) {
+        new PermissionTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/PermissionTest.sh	Wed Apr 29 11:03:56 2015 -0700
@@ -0,0 +1,31 @@
+#!/bin/sh
+# 
+# Copyright (c) 2015, 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 8075545
+# @summary Check whether RuntimePermission("localeServiceProvider") is
+#    handled correctly
+# @run shell ExecTest.sh foobar PermissionTest
+# @run shell/fail ExecTest.sh foobar PermissionTest dummy
+# @run shell ExecTest.sh foobar PermissionTest localeServiceProvider.policy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/PluggableLocale/localeServiceProvider.policy	Wed Apr 29 11:03:56 2015 -0700
@@ -0,0 +1,3 @@
+grant {
+    permission java.lang.RuntimePermission "localeServiceProvider";
+};