summaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
authorgary <gary@138bc75d-0d04-0410-961f-82ee72b054a4>2006-07-28 10:54:11 +0000
committergary <gary@138bc75d-0d04-0410-961f-82ee72b054a4>2006-07-28 10:54:11 +0000
commit445973fa2b45ee4036e3cea6f3ce042d0c2b4675 (patch)
tree330a292f4d8ffc6685638990777d68888da955c8 /libjava/java
parentfeaeaad1928e9377e41fc5ea4ee0ccb0a6794e70 (diff)
downloadgcc-445973fa2b45ee4036e3cea6f3ce042d0c2b4675.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115793 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/security/AccessController.java195
-rw-r--r--libjava/java/security/VMAccessController.java294
-rw-r--r--libjava/java/security/natVMAccessController.cc30
3 files changed, 324 insertions, 195 deletions
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;
+}