summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog12
-rw-r--r--libjava/Makefile.am1
-rw-r--r--libjava/Makefile.in45
-rw-r--r--libjava/include/java-stack.h1
-rw-r--r--libjava/java/security/AccessController.java195
-rw-r--r--libjava/java/security/VMAccessController.java294
-rw-r--r--libjava/java/security/natVMAccessController.cc30
-rw-r--r--libjava/sources.am3
-rw-r--r--libjava/stacktrace.cc42
9 files changed, 414 insertions, 209 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 3e4e0f5e23f..e73c3e5956a 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,4 +1,16 @@
2006-07-28 Gary Benson <gbenson@redhat.com>
+ Casey Marshall <csm@gnu.org>
+
+ PR libgcj/13604:
+ * include/java-stack.h (GetClassMethodStack): Declare.
+ * stacktrace.cc (GetClassMethodStack): New method.
+ * java/security/AccessController.java: Removed.
+ * java/security/VMAccessController.java: New file.
+ * java/security/natVMAccessController.cc: Likewise.
+ * Makefile.am (nat_source_files): Added the above.
+ * sources.am, Makefile.in: Rebuilt.
+
+2006-07-28 Gary Benson <gbenson@redhat.com>
* java/lang/SecurityManager.java (currentClassLoader,
currentLoadedClass, classLoaderDepth, checkAccess, checkRead,
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index f4f5d15a070..45a493039ec 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -826,6 +826,7 @@ java/net/natVMNetworkInterface.cc \
java/net/natInetAddress.cc \
java/nio/channels/natVMChannels.cc \
java/nio/natDirectByteBufferImpl.cc \
+java/security/natVMAccessController.cc \
java/text/natCollator.cc \
java/util/natResourceBundle.cc \
java/util/natVMTimeZone.cc \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index e50c1e6d8c6..631ebb87b89 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -287,12 +287,13 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc jvmti.cc exception.cc \
java/lang/reflect/natField.cc java/lang/reflect/natMethod.cc \
java/net/natVMNetworkInterface.cc java/net/natInetAddress.cc \
java/nio/channels/natVMChannels.cc \
- java/nio/natDirectByteBufferImpl.cc java/text/natCollator.cc \
- java/util/natResourceBundle.cc java/util/natVMTimeZone.cc \
- java/util/logging/natLogger.cc java/util/zip/natDeflater.cc \
- java/util/zip/natInflater.cc boehm.cc nogc.cc posix.cc \
- win32.cc darwin.cc posix-threads.cc win32-threads.cc \
- no-threads.cc
+ java/nio/natDirectByteBufferImpl.cc \
+ java/security/natVMAccessController.cc \
+ java/text/natCollator.cc java/util/natResourceBundle.cc \
+ java/util/natVMTimeZone.cc java/util/logging/natLogger.cc \
+ java/util/zip/natDeflater.cc java/util/zip/natInflater.cc \
+ boehm.cc nogc.cc posix.cc win32.cc darwin.cc posix-threads.cc \
+ win32-threads.cc no-threads.cc
am__objects_2 = gnu/classpath/natSystemProperties.lo \
gnu/gcj/natCore.lo gnu/gcj/convert/JIS0208_to_Unicode.lo \
gnu/gcj/convert/JIS0212_to_Unicode.lo \
@@ -328,10 +329,11 @@ am__objects_2 = gnu/classpath/natSystemProperties.lo \
java/lang/reflect/natField.lo java/lang/reflect/natMethod.lo \
java/net/natVMNetworkInterface.lo java/net/natInetAddress.lo \
java/nio/channels/natVMChannels.lo \
- java/nio/natDirectByteBufferImpl.lo java/text/natCollator.lo \
- java/util/natResourceBundle.lo java/util/natVMTimeZone.lo \
- java/util/logging/natLogger.lo java/util/zip/natDeflater.lo \
- java/util/zip/natInflater.lo
+ java/nio/natDirectByteBufferImpl.lo \
+ java/security/natVMAccessController.lo \
+ java/text/natCollator.lo java/util/natResourceBundle.lo \
+ java/util/natVMTimeZone.lo java/util/logging/natLogger.lo \
+ java/util/zip/natDeflater.lo java/util/zip/natInflater.lo
@USING_BOEHMGC_TRUE@am__objects_3 = boehm.lo
@USING_NOGC_TRUE@am__objects_4 = nogc.lo
@USING_POSIX_PLATFORM_TRUE@am__objects_5 = posix.lo
@@ -616,6 +618,7 @@ bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
+build_libsubdir = @build_libsubdir@
build_os = @build_os@
build_subdir = @build_subdir@
build_vendor = @build_vendor@
@@ -4158,7 +4161,7 @@ java_rmi_server_header_files = $(patsubst classpath/%,%,$(patsubst %.java,%.h,$(
java_security_source_files = \
classpath/java/security/AccessControlContext.java \
classpath/java/security/AccessControlException.java \
-java/security/AccessController.java \
+classpath/java/security/AccessController.java \
classpath/java/security/AlgorithmParameterGenerator.java \
classpath/java/security/AlgorithmParameterGeneratorSpi.java \
classpath/java/security/AlgorithmParameters.java \
@@ -4223,6 +4226,7 @@ classpath/java/security/SignedObject.java \
classpath/java/security/Signer.java \
classpath/java/security/UnrecoverableKeyException.java \
classpath/java/security/UnresolvedPermission.java \
+java/security/VMAccessController.java \
java/security/VMSecureRandom.java
java_security_header_files = $(patsubst classpath/%,%,$(patsubst %.java,%.h,$(java_security_source_files)))
@@ -7136,6 +7140,7 @@ java/net/natVMNetworkInterface.cc \
java/net/natInetAddress.cc \
java/nio/channels/natVMChannels.cc \
java/nio/natDirectByteBufferImpl.cc \
+java/security/natVMAccessController.cc \
java/text/natCollator.cc \
java/util/natResourceBundle.cc \
java/util/natVMTimeZone.cc \
@@ -7625,6 +7630,14 @@ java/nio/$(DEPDIR)/$(am__dirstamp):
@: > java/nio/$(DEPDIR)/$(am__dirstamp)
java/nio/natDirectByteBufferImpl.lo: java/nio/$(am__dirstamp) \
java/nio/$(DEPDIR)/$(am__dirstamp)
+java/security/$(am__dirstamp):
+ @$(mkdir_p) java/security
+ @: > java/security/$(am__dirstamp)
+java/security/$(DEPDIR)/$(am__dirstamp):
+ @$(mkdir_p) java/security/$(DEPDIR)
+ @: > java/security/$(DEPDIR)/$(am__dirstamp)
+java/security/natVMAccessController.lo: java/security/$(am__dirstamp) \
+ java/security/$(DEPDIR)/$(am__dirstamp)
java/text/$(am__dirstamp):
@$(mkdir_p) java/text
@: > java/text/$(am__dirstamp)
@@ -7926,6 +7939,8 @@ mostlyclean-compile:
-rm -f java/nio/channels/natVMChannels.lo
-rm -f java/nio/natDirectByteBufferImpl.$(OBJEXT)
-rm -f java/nio/natDirectByteBufferImpl.lo
+ -rm -f java/security/natVMAccessController.$(OBJEXT)
+ -rm -f java/security/natVMAccessController.lo
-rm -f java/text/natCollator.$(OBJEXT)
-rm -f java/text/natCollator.lo
-rm -f java/util/logging/natLogger.$(OBJEXT)
@@ -8042,6 +8057,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@java/net/$(DEPDIR)/natVMNetworkInterface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/nio/$(DEPDIR)/natDirectByteBufferImpl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/nio/channels/$(DEPDIR)/natVMChannels.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/security/$(DEPDIR)/natVMAccessController.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/text/$(DEPDIR)/natCollator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natResourceBundle.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natVMTimeZone.Plo@am__quote@
@@ -8317,6 +8333,7 @@ clean-libtool:
-rm -rf java/net/.libs java/net/_libs
-rm -rf java/nio/.libs java/nio/_libs
-rm -rf java/nio/channels/.libs java/nio/channels/_libs
+ -rm -rf java/security/.libs java/security/_libs
-rm -rf java/text/.libs java/text/_libs
-rm -rf java/util/.libs java/util/_libs
-rm -rf java/util/logging/.libs java/util/logging/_libs
@@ -8739,6 +8756,8 @@ distclean-generic:
-rm -f java/nio/$(am__dirstamp)
-rm -f java/nio/channels/$(DEPDIR)/$(am__dirstamp)
-rm -f java/nio/channels/$(am__dirstamp)
+ -rm -f java/security/$(DEPDIR)/$(am__dirstamp)
+ -rm -f java/security/$(am__dirstamp)
-rm -f java/text/$(DEPDIR)/$(am__dirstamp)
-rm -f java/text/$(am__dirstamp)
-rm -f java/util/$(DEPDIR)/$(am__dirstamp)
@@ -8760,7 +8779,7 @@ clean-am: clean-binPROGRAMS clean-dbexecLTLIBRARIES clean-generic \
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ./$(DEPDIR) classpath/tools/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/zip/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) classpath/tools/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/security/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/zip/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-local distclean-tags
@@ -8791,7 +8810,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ./$(DEPDIR) classpath/tools/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/zip/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) classpath/tools/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/security/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/zip/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/libjava/include/java-stack.h b/libjava/include/java-stack.h
index eb1ddcce4c7..a1b0db670ea 100644
--- a/libjava/include/java-stack.h
+++ b/libjava/include/java-stack.h
@@ -124,6 +124,7 @@ public:
static void GetCallerInfo (jclass checkClass, jclass *, _Jv_Method **);
static JArray<jclass> *GetClassContext (jclass checkClass);
static ClassLoader *GetFirstNonSystemClassLoader (void);
+ static JArray<jobjectArray> *GetClassMethodStack (_Jv_StackTrace *trace);
};
diff --git a/libjava/java/security/AccessController.java b/libjava/java/security/AccessController.java
deleted file mode 100644
index 4f40edbcf46..00000000000
--- a/libjava/java/security/AccessController.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/* AccessController.java --- Access control context and permission checker
- Copyright (C) 2001, 2004 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath 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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java.security;
-
-/**
- * Access control context and permission checker.
- * Can check permissions in the access control context of the current thread
- * through the <code>checkPermission()</code> method.
- * Manipulates the access control context for code that needs to be executed
- * the protection domain of the calling class (by explicitly ignoring the
- * context of the calling code) in the <code>doPrivileged()</code> methods.
- * And provides a <code>getContext()</code> method which gives the access
- * control context of the current thread that can be used for checking
- * permissions at a later time and/or in another thread.
- * <p>
- * XXX - Mostly a stub implementation at the moment. Needs native support
- * from the VM to function correctly. XXX - Do not forget to think about
- * how to handle <code>java.lang.reflect.Method.invoke()</code> on the
- * <code>doPrivileged()</code> methods.
- *
- * @author Mark Wielaard (mark@klomp.org)
- * @since 1.2
- */
-public final class AccessController
-{
- /**
- * This class only has static methods so there is no public contructor.
- */
- private AccessController()
- {
- }
-
- /**
- * Checks wether the access control context of the current thread allows
- * the given Permission. Throws an <code>AccessControlException</code>
- * when the permission is not allowed in the current context. Otherwise
- * returns silently without throwing an exception.
- *
- * @param perm the permission to be checked.
- * @exception AccessControlException thrown if the current context does not
- * allow the given permission.
- */
- public static void checkPermission(Permission perm)
- throws AccessControlException
- {
- getContext().checkPermission(perm);
- }
-
- /**
- * Calls the <code>run()</code> method of the given action with as
- * (initial) access control context only the protection domain of the
- * calling class. Calls to <code>checkPermission()</code> in the
- * <code>run()</code> method ignore all earlier protection domains of
- * classes in the call chain. Note that the protection domains of classes
- * called by the code in the <code>run()</code> method are not ignored.
- *
- * @param action the <code>PrivilegedAction</code> whose <code>run()</code>
- * should be be called.
- * @return the result of the <code>action.run()</code> method.
- */
- public static Object doPrivileged(PrivilegedAction action)
- {
- return action.run();
- }
-
- /**
- * Calls the <code>run()</code> method of the given action with as
- * (initial) access control context the given context combined with the
- * protection domain of the calling class. Calls to
- * <code>checkPermission()</code> in the <code>run()</code> method ignore
- * all earlier protection domains of classes in the call chain, but add
- * checks for the protection domains given in the supplied context.
- *
- * @param action the <code>PrivilegedAction</code> whose <code>run()</code>
- * should be be called.
- * @param context the <code>AccessControlContext</code> whose protection
- * domains should be added to the protection domain of the calling class.
- * @return the result of the <code>action.run()</code> method.
- */
- public static Object doPrivileged(PrivilegedAction action,
- AccessControlContext context)
- {
- return action.run();
- }
-
- /**
- * Calls the <code>run()</code> method of the given action with as
- * (initial) access control context only the protection domain of the
- * calling class. Calls to <code>checkPermission()</code> in the
- * <code>run()</code> method ignore all earlier protection domains of
- * classes in the call chain. Note that the protection domains of classes
- * called by the code in the <code>run()</code> method are not ignored.
- * If the <code>run()</code> method throws an exception then this method
- * will wrap that exception in an <code>PrivilegedActionException</code>.
- *
- * @param action the <code>PrivilegedExceptionAction</code> whose
- * <code>run()</code> should be be called.
- * @return the result of the <code>action.run()</code> method.
- * @exception PrivilegedActionException wrapped around any exception that
- * is thrown in the <code>run()</code> method.
- */
- public static Object doPrivileged(PrivilegedExceptionAction action)
- throws PrivilegedActionException
- {
- try
- {
- return action.run();
- }
- catch (Exception e)
- {
- throw new PrivilegedActionException(e);
- }
- }
-
- /**
- * Calls the <code>run()</code> method of the given action with as
- * (initial) access control context the given context combined with the
- * protection domain of the calling class. Calls to
- * <code>checkPermission()</code> in the <code>run()</code> method ignore
- * all earlier protection domains of classes in the call chain, but add
- * checks for the protection domains given in the supplied context.
- * If the <code>run()</code> method throws an exception then this method
- * will wrap that exception in an <code>PrivilegedActionException</code>.
- *
- * @param action the <code>PrivilegedExceptionAction</code> whose
- * <code>run()</code> should be be called.
- * @param context the <code>AccessControlContext</code> whose protection
- * domains should be added to the protection domain of the calling class.
- * @return the result of the <code>action.run()</code> method.
- * @exception PrivilegedActionException wrapped around any exception that
- * is thrown in the <code>run()</code> method.
- */
- public static Object doPrivileged(PrivilegedExceptionAction action,
- AccessControlContext context)
- throws PrivilegedActionException
- {
- try
- {
- return action.run();
- }
- catch (Exception e)
- {
- throw new PrivilegedActionException(e);
- }
- }
-
- /**
- * Returns the complete access control context of the current thread.
- * <p>
- * XXX - Should this include all the protection domains in the call chain
- * or only the domains till the last <code>doPrivileged()</code> call?
- * <p>
- * XXX - needs native support. Currently returns an empty context.
- */
- public static AccessControlContext getContext()
- {
- // For now just return an new empty context
- return new AccessControlContext(new ProtectionDomain[0]);
- }
-}
diff --git a/libjava/java/security/VMAccessController.java b/libjava/java/security/VMAccessController.java
new file mode 100644
index 00000000000..dfbd16f693b
--- /dev/null
+++ b/libjava/java/security/VMAccessController.java
@@ -0,0 +1,294 @@
+/* VMAccessController.java -- VM-specific access controller methods.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+
+final class VMAccessController
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * This is a per-thread stack of AccessControlContext objects (which can
+ * be null) for each call to AccessController.doPrivileged in each thread's
+ * call stack. We use this to remember which context object corresponds to
+ * which call.
+ */
+ private static final ThreadLocal contexts = new ThreadLocal();
+
+ /**
+ * This is a Boolean that, if set, tells getContext that it has already
+ * been called once, allowing us to handle recursive permission checks
+ * caused by methods getContext calls.
+ */
+ private static final ThreadLocal inGetContext = new ThreadLocal();
+
+ /**
+ * And we return this all-permissive context to ensure that privileged
+ * methods called from getContext succeed.
+ */
+ private static final AccessControlContext DEFAULT_CONTEXT;
+ static
+ {
+ CodeSource source = new CodeSource(null, null);
+ Permissions permissions = new Permissions();
+ permissions.add(new AllPermission());
+ ProtectionDomain[] domain = new ProtectionDomain[] {
+ new ProtectionDomain(source, permissions)
+ };
+ DEFAULT_CONTEXT = new AccessControlContext(domain);
+ }
+
+ private static final boolean DEBUG = gnu.classpath.Configuration.DEBUG;
+ private static void debug(String msg)
+ {
+ System.err.print(">>> VMAccessController: ");
+ System.err.println(msg);
+ }
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ private VMAccessController() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Relate a class (which should be an instance of {@link PrivilegedAction}
+ * with an access control context. This method is used by {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
+ * to set up the context that will be returned by {@link #getContext()}.
+ * This method relates the class to the current thread, so contexts
+ * pushed from one thread will not be available to another.
+ *
+ * @param acc The access control context.
+ */
+ static void pushContext (AccessControlContext acc)
+ {
+ if (!runtimeInitialized())
+ return;
+
+ if (DEBUG)
+ debug("pushing " + acc);
+ LinkedList stack = (LinkedList) contexts.get();
+ if (stack == null)
+ {
+ if (DEBUG)
+ debug("no stack... creating ");
+ stack = new LinkedList();
+ contexts.set(stack);
+ }
+ stack.addFirst(acc);
+ }
+
+ /**
+ * Removes the relation of a class to an {@link AccessControlContext}.
+ * This method is used by {@link AccessController} when exiting from a
+ * call to {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
+ */
+ static void popContext()
+ {
+ if (!runtimeInitialized())
+ return;
+
+ if (DEBUG)
+ debug("popping context");
+
+ // Stack should never be null, nor should it be empty, if this method
+ // and its counterpart has been called properly.
+ LinkedList stack = (LinkedList) contexts.get();
+ if (stack != null)
+ {
+ stack.removeFirst();
+ if (stack.isEmpty())
+ contexts.set(null);
+ }
+ else if (DEBUG)
+ {
+ debug("no stack during pop?????");
+ }
+ }
+
+ /**
+ * Examine the method stack of the currently running thread, and create
+ * an {@link AccessControlContext} filled in with the appropriate {@link
+ * ProtectionDomain} objects given this stack.
+ *
+ * @return The context.
+ */
+ static AccessControlContext getContext()
+ {
+ // If the VM is initializing return the all-permissive context
+ // so that any security checks succeed.
+ //
+ // XXX this might not be necessary, but it seems prudent.
+ if (!runtimeInitialized())
+ return DEFAULT_CONTEXT;
+
+ // If we are already in getContext, but called a method that needs
+ // a permission check, return the all-permissive context so methods
+ // called from here succeed.
+ //
+ // XXX is this necessary? We should verify if there are any calls in
+ // the stack below this method that require permission checks.
+ Boolean inCall = (Boolean) inGetContext.get();
+ if (inCall != null && inCall.booleanValue())
+ {
+ if (DEBUG)
+ debug("already in getContext");
+ return DEFAULT_CONTEXT;
+ }
+
+ inGetContext.set(Boolean.TRUE);
+
+ Object[][] stack = getStack();
+ Class[] classes = (Class[]) stack[0];
+ String[] methods = (String[]) stack[1];
+
+ if (DEBUG)
+ debug("got trace of length " + classes.length);
+
+ HashSet domains = new HashSet();
+ HashSet seenDomains = new HashSet();
+ AccessControlContext context = null;
+ int privileged = 0;
+
+ // We walk down the stack, adding each ProtectionDomain for each
+ // class in the call stack. If we reach a call to doPrivileged,
+ // we don't add any more stack frames. We skip the first three stack
+ // frames, since they comprise the calls to getStack, getContext,
+ // and AccessController.getContext.
+ for (int i = 3; i < classes.length && privileged < 2; i++)
+ {
+ Class clazz = classes[i];
+ String method = methods[i];
+
+ if (DEBUG)
+ {
+ debug("checking " + clazz + "." + method);
+ // subject to getClassLoader RuntimePermission
+ debug("loader = " + clazz.getClassLoader());
+ }
+
+ // If the previous frame was a call to doPrivileged, then this is
+ // the last frame we look at.
+ if (privileged == 1)
+ privileged = 2;
+
+ if (clazz.equals (AccessController.class)
+ && method.equals ("doPrivileged"))
+ {
+ // If there was a call to doPrivileged with a supplied context,
+ // return that context. If using JAAS doAs*, it should be
+ // a context with a SubjectDomainCombiner
+ LinkedList l = (LinkedList) contexts.get();
+ if (l != null)
+ context = (AccessControlContext) l.getFirst();
+ privileged = 1;
+ }
+
+ // subject to getProtectionDomain RuntimePermission
+ ProtectionDomain domain = clazz.getProtectionDomain();
+
+ if (domain == null)
+ continue;
+ if (seenDomains.contains(domain))
+ continue;
+ seenDomains.add(domain);
+
+ // Create a static snapshot of this domain, which may change over time
+ // if the current policy changes.
+ domains.add(new ProtectionDomain(domain.getCodeSource(),
+ domain.getPermissions()));
+ }
+
+ if (DEBUG)
+ debug("created domains: " + domains);
+
+ ProtectionDomain[] result = (ProtectionDomain[])
+ domains.toArray(new ProtectionDomain[domains.size()]);
+
+ if (context != null)
+ {
+ DomainCombiner dc = context.getDomainCombiner ();
+ // If the supplied context had no explicit DomainCombiner, use
+ // our private version, which computes the intersection of the
+ // context's domains with the derived set.
+ if (dc == null)
+ context = new AccessControlContext
+ (IntersectingDomainCombiner.SINGLETON.combine
+ (result, context.getProtectionDomains ()));
+ // Use the supplied DomainCombiner. This should be secure,
+ // because only trusted code may create an
+ // AccessControlContext with a custom DomainCombiner.
+ else
+ context = new AccessControlContext (result, context, dc);
+ }
+ // No context was supplied. Return the derived one.
+ else
+ context = new AccessControlContext (result);
+
+ inGetContext.set(Boolean.FALSE);
+ return context;
+ }
+
+ /**
+ * Returns a snapshot of the current call stack as a pair of arrays:
+ * the first an array of classes in the call stack, the second an array
+ * of strings containing the method names in the call stack. The two
+ * arrays match up, meaning that method <i>i</i> is declared in class
+ * <i>i</i>. The arrays are clean; it will only contain Java methods,
+ * and no element of the list should be null.
+ *
+ * @return A pair of arrays describing the current call stack. The first
+ * element is an array of Class objects, and the second is an array
+ * of Strings comprising the method names.
+ */
+ private static native Object[][] getStack();
+
+ /**
+ * Tell whether runtime initialization is complete.
+ *
+ * @return whether runtime initialization is complete.
+ */
+ private static native boolean runtimeInitialized();
+}
diff --git a/libjava/java/security/natVMAccessController.cc b/libjava/java/security/natVMAccessController.cc
new file mode 100644
index 00000000000..25503453284
--- /dev/null
+++ b/libjava/java/security/natVMAccessController.cc
@@ -0,0 +1,30 @@
+// natVMAccessController.cc -- Native part of the VMAccessController class.
+
+/* Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java-stack.h>
+
+#include <java/security/VMAccessController.h>
+
+JArray<jobjectArray> *
+java::security::VMAccessController::getStack ()
+{
+ _Jv_StackTrace *trace = _Jv_StackTrace::GetStackTrace ();
+ return _Jv_StackTrace::GetClassMethodStack (trace);
+}
+
+jboolean
+java::security::VMAccessController::runtimeInitialized ()
+{
+ return gcj::runtimeInitialized;
+}
diff --git a/libjava/sources.am b/libjava/sources.am
index cbb7fa0ad49..1b1ed620edf 100644
--- a/libjava/sources.am
+++ b/libjava/sources.am
@@ -5265,7 +5265,7 @@ java/rmi/server.list: $(java_rmi_server_source_files)
java_security_source_files = \
classpath/java/security/AccessControlContext.java \
classpath/java/security/AccessControlException.java \
-java/security/AccessController.java \
+classpath/java/security/AccessController.java \
classpath/java/security/AlgorithmParameterGenerator.java \
classpath/java/security/AlgorithmParameterGeneratorSpi.java \
classpath/java/security/AlgorithmParameters.java \
@@ -5330,6 +5330,7 @@ classpath/java/security/SignedObject.java \
classpath/java/security/Signer.java \
classpath/java/security/UnrecoverableKeyException.java \
classpath/java/security/UnresolvedPermission.java \
+java/security/VMAccessController.java \
java/security/VMSecureRandom.java
java_security_header_files = $(patsubst classpath/%,%,$(patsubst %.java,%.h,$(java_security_source_files)))
diff --git a/libjava/stacktrace.cc b/libjava/stacktrace.cc
index ba971ddc13e..843c5124e7e 100644
--- a/libjava/stacktrace.cc
+++ b/libjava/stacktrace.cc
@@ -534,3 +534,45 @@ _Jv_StackTrace::GetFirstNonSystemClassLoader ()
return NULL;
}
+
+JArray<jobjectArray> *
+_Jv_StackTrace::GetClassMethodStack (_Jv_StackTrace *trace)
+{
+ jint length = 0;
+
+ UpdateNCodeMap();
+ for (int i = 0; i < trace->length; i++)
+ {
+ _Jv_StackFrame *frame = &trace->frames[i];
+ FillInFrameInfo (frame);
+
+ if (frame->klass && frame->meth)
+ length++;
+ }
+
+ jclass array_class = _Jv_GetArrayClass (&::java::lang::Object::class$, NULL);
+ JArray<jobjectArray> *result =
+ (JArray<jobjectArray> *) _Jv_NewObjectArray (2, array_class, NULL);
+ JArray<jclass> *classes = (JArray<jclass> *)
+ _Jv_NewObjectArray (length, &::java::lang::Class::class$, NULL);
+ JArray<jstring> *methods = (JArray<jstring> *)
+ _Jv_NewObjectArray (length, &::java::lang::String::class$, NULL);
+ jclass *c = elements (classes);
+ jstring *m = elements (methods);
+
+ for (int i = 0, j = 0; i < trace->length; i++)
+ {
+ _Jv_StackFrame *frame = &trace->frames[i];
+ if (!frame->klass || !frame->meth)
+ continue;
+ c[j] = frame->klass;
+ m[j] = JvNewStringUTF (frame->meth->name->chars());
+ j++;
+ }
+
+ jobjectArray *elems = elements (result);
+ elems[0] = (jobjectArray) classes;
+ elems[1] = (jobjectArray) methods;
+
+ return result;
+}