Package org.jnode.vm

Source Code of org.jnode.vm.VmAccessController

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm;

import java.security.AccessControlException;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;

import org.jnode.annotation.CheckPermission;
import org.jnode.annotation.DoPrivileged;
import org.jnode.annotation.MagicPermission;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.scheduler.VmProcessor;
import org.jnode.vm.scheduler.VmThread;

/**
* JNode VM implementation of the java AccessControl system.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
@MagicPermission
public final class VmAccessController {

    /**
     * Checks whether 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.
     * @throws AccessControlException thrown if the current context does not allow the given
     *                                permission.
     */

    @CheckPermission
    public static void checkPermission(Permission perm)
        throws AccessControlException {
        if (!VmProcessor.current().isThreadSwitchActive()) {
            // getContext().checkPermission(perm);

            // This is an optimized version of
            // getContext().checkPermission()
            // that does not require any memory allocations.
            final VmStackReader reader = VmProcessor.current()
                .getArchitecture().getStackReader();
            final VmStackFrameEnumerator sfEnum = new VmStackFrameEnumerator(reader);
            int recursionCount = 0;
            while (sfEnum.isValid()) {
                final VmMethod method = sfEnum.getMethod();
                if (method.hasDoPrivilegedPragma()) {
                    // Stop here with the current thread's stacktrace.
                    break;
                } else if (method.hasCheckPermissionPragma()) {
                    // Be paranoia for now, let's check for recursive
                    // checkPermission calls.
                    recursionCount++;
                    if (recursionCount > 2) {
                        reader.debugStackTrace();
                        Unsafe.die("Recursive checkPermission");
                    }
                } else {
                    final VmType<?> declClass = method.getDeclaringClass();
                    final ProtectionDomain pd = declClass.getProtectionDomain();
                    if (pd != null) {
                        // Unsafe.debug(":pd");
                        if (!pd.implies(perm)) {
                            // Unsafe.debug("Permission denied");
                            throw new AccessControlException("Permission \""
                                + perm + "\" not granted due to "
                                + declClass.getName());
                        }
                    }
                }
                if (method.hasPrivilegedActionPragma()) {
                    // Break here, do not include inherited thread context
                    return;
                }
                sfEnum.next();
            }

            final VmThread thread = VmThread.currentThread();
            final VmAccessControlContext inheritedCtx = thread.getContext();
            if (inheritedCtx != null) {
                inheritedCtx.checkPermission(perm);
            }
        }
    }

    /**
     * This method takes a "snapshot" of the current calling context, which
     * includes the current Thread's inherited AccessControlContext, and places
     * it in an AccessControlContext object. This context may then be checked at
     * a later point, possibly in another thread.
     *
     * @return the AccessControlContext based on the current context.
     */
    public static VmAccessControlContext getContext() {
        final VmStackReader reader = VmProcessor.current()
            .getArchitecture().getStackReader();
        final VmStackFrame[] stack = reader.getVmStackTrace(VmMagic
            .getCurrentFrame(), null, Integer.MAX_VALUE);
        final int count = stack.length;
        final ProtectionDomain domains[] = new ProtectionDomain[count];

        for (int i = 0; i < count; i++) {
            final VmMethod method = stack[i].getMethod();
            if (method.hasDoPrivilegedPragma()) {
                // Stop here
                break;
            } else if (method.hasPrivilegedActionPragma()) {
                // Break here, do not include inherited thread context
                return new VmAccessControlContext(domains, null);
            } else {
                domains[i] = method.getDeclaringClass().getProtectionDomain();
            }
        }
        final VmThread thread = VmThread.currentThread();
        return new VmAccessControlContext(domains, thread.getContext());
    }

    /**
     * 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.
     */
    @DoPrivileged
    public static Object doPrivileged(PrivilegedAction action,
                                      VmAccessControlContext context) {
        final VmThread thread = VmThread.currentThread();
        final VmAccessControlContext prevContext = thread.getContext();
        thread.setContext(context);
        try {
            return action.run();
        } finally {
            thread.setContext(prevContext);
        }
    }

    /**
     * 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.
     * @throws PrivilegedActionException wrapped around any exception that is thrown in the
     *                                   <code>run()</code> method.
     * @return the result of the <code>action.run()</code> method.
     */
    @DoPrivileged
    public static Object doPrivileged(PrivilegedExceptionAction action,
                                      VmAccessControlContext context) throws PrivilegedActionException {
        final VmThread thread = VmThread.currentThread();
        final VmAccessControlContext prevContext = thread.getContext();
        thread.setContext(context);
        try {
            return action.run();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new PrivilegedActionException(e);
        } finally {
            thread.setContext(prevContext);
        }
    }
}
TOP

Related Classes of org.jnode.vm.VmAccessController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.