2016-05-14 Fritz Reese <fritzoreese@gmail.com>
[official-gcc.git] / libjava / java / security / VMAccessController.java
blob66ada195229fc1f81dafab376ae69a8e1a2c073b
1 /* VMAccessController.java -- VM-specific access controller methods.
2 Copyright (C) 2004, 2005, 2006, 2010 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301 USA.
19 Linking this library statically or dynamically with other modules is
20 making a combined work based on this library. Thus, the terms and
21 conditions of the GNU General Public License cover the whole
22 combination.
24 As a special exception, the copyright holders of this library give you
25 permission to link this library with independent modules to produce an
26 executable, regardless of the license terms of these independent
27 modules, and to copy and distribute the resulting executable under
28 terms of your choice, provided that you also meet, for each linked
29 independent module, the terms and conditions of the license of that
30 module. An independent module is a module which is not derived from
31 or based on this library. If you modify this library, you may extend
32 this exception to your version of the library, but you are not
33 obligated to do so. If you do not wish to do so, delete this
34 exception statement from your version. */
37 package java.security;
39 import java.util.HashSet;
40 import java.util.LinkedList;
42 final class VMAccessController
45 // Fields.
46 // -------------------------------------------------------------------------
48 /**
49 * And we return this all-permissive context to ensure that privileged
50 * methods called from getContext succeed.
52 private static final AccessControlContext DEFAULT_CONTEXT;
53 static
55 CodeSource source = new CodeSource(null, null);
56 Permissions permissions = new Permissions();
57 permissions.add(new AllPermission());
58 ProtectionDomain[] domain = new ProtectionDomain[] {
59 new ProtectionDomain(source, permissions, null, null)
61 DEFAULT_CONTEXT = new AccessControlContext(domain);
64 private static final boolean DEBUG = gnu.classpath.Configuration.DEBUG;
65 private static void debug(String msg)
67 System.err.print(">>> VMAccessController: ");
68 System.err.println(msg);
71 // Constructors.
72 // -------------------------------------------------------------------------
74 private VMAccessController() { }
76 // Class methods.
77 // -------------------------------------------------------------------------
79 /**
80 * Relate a class (which should be an instance of {@link PrivilegedAction}
81 * with an access control context. This method is used by {@link
82 * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
83 * to set up the context that will be returned by {@link #getContext()}.
84 * This method relates the class to the current thread, so contexts
85 * pushed from one thread will not be available to another.
87 * @param acc The access control context.
89 static void pushContext (AccessControlContext acc)
91 // Can't really do anything while the VM is initializing.
92 VMAccessControlState state = VMAccessControlState.getThreadState();
93 if (state == null)
94 return;
96 if (DEBUG)
97 debug("pushing " + acc);
99 LinkedList stack = state.getContexts();
100 stack.addFirst(acc);
104 * Removes the relation of a class to an {@link AccessControlContext}.
105 * This method is used by {@link AccessController} when exiting from a
106 * call to {@link
107 * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
109 static void popContext()
111 // Can't really do anything while the VM is initializing.
112 VMAccessControlState state = VMAccessControlState.getThreadState();
113 if (state == null)
114 return;
116 if (DEBUG)
117 debug("popping context");
119 // Stack should never be null, nor should it be empty, if this method
120 // and its counterpart has been called properly.
121 LinkedList stack = state.getContexts();
122 if (!stack.isEmpty())
124 stack.removeFirst();
126 else if (DEBUG)
128 debug("no stack during pop?????");
133 * Examine the method stack of the currently running thread, and create
134 * an {@link AccessControlContext} filled in with the appropriate {@link
135 * ProtectionDomain} objects given this stack.
137 * @return The context.
139 static AccessControlContext getContext()
141 // If the VM is initializing return the all-permissive context
142 // so that any security checks succeed.
143 VMAccessControlState state = VMAccessControlState.getThreadState();
144 if (state == null)
145 return DEFAULT_CONTEXT;
147 // If we are already in getContext, but called a method that needs
148 // a permission check, return the all-permissive context so methods
149 // called from here succeed.
151 // XXX is this necessary? We should verify if there are any calls in
152 // the stack below this method that require permission checks.
153 if (state.isInGetContext())
155 if (DEBUG)
156 debug("already in getContext");
157 return DEFAULT_CONTEXT;
160 state.setInGetContext(true);
162 Object[] stack = getStack();
163 Class[] classes = (Class[]) stack[0];
164 boolean privileged = ((Boolean) stack[1]).booleanValue();
166 if (DEBUG)
167 debug("got trace of length " + classes.length);
169 HashSet domains = new HashSet();
170 HashSet seenDomains = new HashSet();
171 AccessControlContext context = null;
173 // We walk down the stack, adding each ProtectionDomain for each
174 // class in the call stack. If we reach a call to doPrivileged,
175 // we don't add any more stack frames. We skip the first three stack
176 // frames, since they comprise the calls to getStack, getContext,
177 // and AccessController.getContext.
178 for (int i = 3; i < classes.length; i++)
180 Class clazz = classes[i];
181 ClassLoader loader = clazz.getClassLoader();
183 if (DEBUG)
185 debug("checking " + clazz);
186 // subject to getClassLoader RuntimePermission
187 debug("loader = " + loader);
190 if (privileged && i == classes.length - 2)
192 // If there was a call to doPrivileged with a supplied context,
193 // return that context. If using JAAS doAs*, it should be
194 // a context with a SubjectDomainCombiner
195 LinkedList l = state.getContexts();
196 if (!l.isEmpty())
197 context = (AccessControlContext) l.getFirst();
200 // subject to getProtectionDomain RuntimePermission
201 ProtectionDomain domain = clazz.getProtectionDomain();
203 if (domain == null)
204 continue;
205 if (seenDomains.contains(domain))
206 continue;
207 seenDomains.add(domain);
209 // Create a static snapshot of this domain, which may change over time
210 // if the current policy changes.
211 domains.add(new ProtectionDomain(domain.getCodeSource(),
212 domain.getPermissions(),
213 loader, null));
216 if (DEBUG)
217 debug("created domains: " + domains);
219 ProtectionDomain[] result = (ProtectionDomain[])
220 domains.toArray(new ProtectionDomain[domains.size()]);
222 if (context != null)
224 DomainCombiner dc = context.getDomainCombiner ();
225 // If the supplied context had no explicit DomainCombiner, use
226 // our private version, which computes the intersection of the
227 // context's domains with the derived set.
228 if (dc == null)
229 context = new AccessControlContext
230 (IntersectingDomainCombiner.SINGLETON.combine
231 (result, context.getProtectionDomains ()));
232 // Use the supplied DomainCombiner. This should be secure,
233 // because only trusted code may create an
234 // AccessControlContext with a custom DomainCombiner.
235 else
236 context = new AccessControlContext (result, context, dc);
238 // No context was supplied. Return the derived one.
239 else
240 context = new AccessControlContext (result);
242 state.setInGetContext(false);
243 return context;
247 * Returns a snapshot of the current call stack as a two-element
248 * array. The first element is an array of classes in the call
249 * stack, and the second element is a boolean value indicating
250 * whether the trace stopped early because a call to doPrivileged
251 * was encountered. If this boolean value is true then the call to
252 * doPrivileged will be the second-last frame in the returned trace.
254 * @return A snapshot of the current call stack.
256 private static native Object[] getStack();