From 1612bc5265d145b1002e2715b6c1ed85bd5d4044 Mon Sep 17 00:00:00 2001 From: denis Date: Thu, 17 Mar 2011 17:16:35 -0700 Subject: [PATCH] 6907662: System clipboard should ensure access restrictions Reviewed-by: alexp --- src/share/classes/java/awt/AWTEvent.java | 25 +++++++++ src/share/classes/java/awt/Component.java | 23 +++++++++ src/share/classes/java/awt/EventQueue.java | 51 +++++++++++++++++-- src/share/classes/java/awt/MenuComponent.java | 23 +++++++++ src/share/classes/java/awt/TrayIcon.java | 21 ++++++++ .../java/security/AccessControlContext.java | 21 ++++++++ .../java/security/ProtectionDomain.java | 32 ++++++++++++ src/share/classes/javax/swing/Timer.java | 36 ++++++++++++- .../classes/javax/swing/TransferHandler.java | 42 ++++++++++++++- src/share/classes/sun/awt/AWTAccessor.java | 17 +++++++ .../classes/sun/misc/JavaSecurityAccess.java | 40 +++++++++++++++ src/share/classes/sun/misc/SharedSecrets.java | 14 +++++ 12 files changed, 339 insertions(+), 6 deletions(-) create mode 100644 src/share/classes/sun/misc/JavaSecurityAccess.java diff --git a/src/share/classes/java/awt/AWTEvent.java b/src/share/classes/java/awt/AWTEvent.java index 60ab93e1d..5afd14afa 100644 --- a/src/share/classes/java/awt/AWTEvent.java +++ b/src/share/classes/java/awt/AWTEvent.java @@ -33,6 +33,11 @@ import java.lang.reflect.Field; import sun.awt.AWTAccessor; import sun.util.logging.PlatformLogger; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.io.ObjectInputStream; +import java.io.IOException; + /** * The root event class for all AWT events. * This class and its subclasses supercede the original @@ -97,6 +102,22 @@ public abstract class AWTEvent extends EventObject { */ protected boolean consumed = false; + /* + * The event's AccessControlContext. + */ + private transient volatile AccessControlContext acc = + AccessController.getContext(); + + /* + * Returns the acc this event was constructed with. + */ + final AccessControlContext getAccessControlContext() { + if (acc == null) { + throw new SecurityException("AWTEvent is missing AccessControlContext"); + } + return acc; + } + transient boolean focusManagerIsDispatching = false; transient boolean isPosted; @@ -247,6 +268,10 @@ public abstract class AWTEvent extends EventObject { public boolean isSystemGenerated(AWTEvent ev) { return ev.isSystemGenerated; } + + public AccessControlContext getAccessControlContext(AWTEvent ev) { + return ev.getAccessControlContext(); + } }); } diff --git a/src/share/classes/java/awt/Component.java b/src/share/classes/java/awt/Component.java index d0eda994f..adabdbccc 100644 --- a/src/share/classes/java/awt/Component.java +++ b/src/share/classes/java/awt/Component.java @@ -59,6 +59,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.AccessControlContext; import javax.accessibility.*; import java.applet.Applet; @@ -471,6 +472,12 @@ public abstract class Component implements ImageObserver, MenuContainer, static final Object LOCK = new AWTTreeLock(); static class AWTTreeLock {} + /* + * The component's AccessControlContext. + */ + private transient volatile AccessControlContext acc = + AccessController.getContext(); + /** * Minimum size. * (This field perhaps should have been transient). @@ -671,6 +678,16 @@ public abstract class Component implements ImageObserver, MenuContainer, return objectLock; } + /* + * Returns the acc this component was constructed with. + */ + final AccessControlContext getAccessControlContext() { + if (acc == null) { + throw new SecurityException("Component is missing AccessControlContext"); + } + return acc; + } + boolean isPacked = false; /** @@ -950,6 +967,10 @@ public abstract class Component implements ImageObserver, MenuContainer, public void processEvent(Component comp, AWTEvent e) { comp.processEvent(e); } + + public AccessControlContext getAccessControlContext(Component comp) { + return comp.getAccessControlContext(); + } }); } @@ -8608,6 +8629,8 @@ public abstract class Component implements ImageObserver, MenuContainer, { objectLock = new Object(); + acc = AccessController.getContext(); + s.defaultReadObject(); appContext = AppContext.getAppContext(); diff --git a/src/share/classes/java/awt/EventQueue.java b/src/share/classes/java/awt/EventQueue.java index d4c763b4f..8aab49f07 100644 --- a/src/share/classes/java/awt/EventQueue.java +++ b/src/share/classes/java/awt/EventQueue.java @@ -48,6 +48,12 @@ import sun.awt.AWTAccessor; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; +import java.security.AccessControlContext; +import java.security.ProtectionDomain; + +import sun.misc.SharedSecrets; +import sun.misc.JavaSecurityAccess; + /** * EventQueue is a platform-independent class * that queues events, both from the underlying peer classes @@ -612,6 +618,9 @@ public class EventQueue { return null; } + private static final JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + /** * Dispatches an event. The manner in which the event is * dispatched depends upon the type of the event and the @@ -650,13 +659,49 @@ public class EventQueue { * @throws NullPointerException if event is null * @since 1.2 */ - protected void dispatchEvent(AWTEvent event) { + protected void dispatchEvent(final AWTEvent event) { + final Object src = event.getSource(); + final PrivilegedAction action = new PrivilegedAction() { + public Void run() { + dispatchEventImpl(event, src); + return null; + } + }; + + final AccessControlContext stack = AccessController.getContext(); + final AccessControlContext srcAcc = getAccessControlContextFrom(src); + final AccessControlContext eventAcc = event.getAccessControlContext(); + if (srcAcc == null) { + javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc); + } else { + javaSecurityAccess.doIntersectionPrivilege( + new PrivilegedAction() { + public Void run() { + javaSecurityAccess.doIntersectionPrivilege(action, eventAcc); + return null; + } + }, stack, srcAcc); + } + } + + private static AccessControlContext getAccessControlContextFrom(Object src) { + return src instanceof Component ? + ((Component)src).getAccessControlContext() : + src instanceof MenuComponent ? + ((MenuComponent)src).getAccessControlContext() : + src instanceof TrayIcon ? + ((TrayIcon)src).getAccessControlContext() : + null; + } + + /** + * Called from dispatchEvent() under a correct AccessControlContext + */ + private void dispatchEventImpl(final AWTEvent event, final Object src) { event.isPosted = true; - Object src = event.getSource(); if (event instanceof ActiveEvent) { // This could become the sole method of dispatching in time. setCurrentEventAndMostRecentTimeImpl(event); - ((ActiveEvent)event).dispatch(); } else if (src instanceof Component) { ((Component)src).dispatchEvent(event); diff --git a/src/share/classes/java/awt/MenuComponent.java b/src/share/classes/java/awt/MenuComponent.java index 19d57394a..d1a5a2577 100644 --- a/src/share/classes/java/awt/MenuComponent.java +++ b/src/share/classes/java/awt/MenuComponent.java @@ -33,6 +33,9 @@ import sun.awt.SunToolkit; import sun.awt.AWTAccessor; import javax.accessibility.*; +import java.security.AccessControlContext; +import java.security.AccessController; + /** * The abstract class MenuComponent is the superclass * of all menu-related components. In this respect, the class @@ -99,6 +102,23 @@ public abstract class MenuComponent implements java.io.Serializable { */ boolean newEventsOnly = false; + /* + * The menu's AccessControlContext. + */ + private transient volatile AccessControlContext acc = + AccessController.getContext(); + + /* + * Returns the acc this menu component was constructed with. + */ + final AccessControlContext getAccessControlContext() { + if (acc == null) { + throw new SecurityException( + "MenuComponent is missing AccessControlContext"); + } + return acc; + } + /* * Internal constants for serialization. */ @@ -402,6 +422,9 @@ public abstract class MenuComponent implements java.io.Serializable { throws ClassNotFoundException, IOException, HeadlessException { GraphicsEnvironment.checkHeadless(); + + acc = AccessController.getContext(); + s.defaultReadObject(); appContext = AppContext.getAppContext(); diff --git a/src/share/classes/java/awt/TrayIcon.java b/src/share/classes/java/awt/TrayIcon.java index 35a98706e..13185bf92 100644 --- a/src/share/classes/java/awt/TrayIcon.java +++ b/src/share/classes/java/awt/TrayIcon.java @@ -40,6 +40,8 @@ import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.HeadlessToolkit; import java.util.EventObject; +import java.security.AccessControlContext; +import java.security.AccessController; /** * A TrayIcon object represents a tray icon that can be @@ -90,6 +92,7 @@ import java.util.EventObject; * @author Anton Tarasov */ public class TrayIcon { + private Image image; private String tooltip; private PopupMenu popup; @@ -103,6 +106,24 @@ public class TrayIcon { transient MouseMotionListener mouseMotionListener; transient ActionListener actionListener; + /* + * The tray icon's AccessControlContext. + * + * Unlike the acc in Component, this field is made final + * because TrayIcon is not serializable. + */ + private final AccessControlContext acc = AccessController.getContext(); + + /* + * Returns the acc this tray icon was constructed with. + */ + final AccessControlContext getAccessControlContext() { + if (acc == null) { + throw new SecurityException("TrayIcon is missing AccessControlContext"); + } + return acc; + } + static { Toolkit.loadLibraries(); if (!GraphicsEnvironment.isHeadless()) { diff --git a/src/share/classes/java/security/AccessControlContext.java b/src/share/classes/java/security/AccessControlContext.java index e80953b66..940aff637 100644 --- a/src/share/classes/java/security/AccessControlContext.java +++ b/src/share/classes/java/security/AccessControlContext.java @@ -29,6 +29,9 @@ import java.util.ArrayList; import java.util.List; import sun.security.util.Debug; import sun.security.util.SecurityConstants; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; + /** * An AccessControlContext is used to make system resource access decisions @@ -196,6 +199,24 @@ public final class AccessControlContext { this.isPrivileged = isPrivileged; } + /** + * Constructor for JavaSecurityAccess.doIntersectionPrivilege() + */ + AccessControlContext(ProtectionDomain[] context, + AccessControlContext privilegedContext) + { + this.context = context; + this.privilegedContext = privilegedContext; + this.isPrivileged = true; + } + + /** + * Returns this context's context. + */ + ProtectionDomain[] getContext() { + return context; + } + /** * Returns true if this context is privileged. */ diff --git a/src/share/classes/java/security/ProtectionDomain.java b/src/share/classes/java/security/ProtectionDomain.java index 43a39028e..9025e81b5 100644 --- a/src/share/classes/java/security/ProtectionDomain.java +++ b/src/share/classes/java/security/ProtectionDomain.java @@ -36,6 +36,8 @@ import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; import sun.misc.SharedSecrets; import sun.security.util.Debug; import sun.security.util.SecurityConstants; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; /** * @@ -59,6 +61,36 @@ import sun.security.util.SecurityConstants; public class ProtectionDomain { + static { + // Set up JavaSecurityAccess in SharedSecrets + SharedSecrets.setJavaSecurityAccess( + new JavaSecurityAccess() { + public T doIntersectionPrivilege( + PrivilegedAction action, + final AccessControlContext stack, + final AccessControlContext context) + { + if (action == null) { + throw new NullPointerException(); + } + return AccessController.doPrivileged( + action, + new AccessControlContext( + stack.getContext(), context).optimize() + ); + } + + public T doIntersectionPrivilege( + PrivilegedAction action, + AccessControlContext context) + { + return doIntersectionPrivilege(action, + AccessController.getContext(), context); + } + } + ); + } + /* CodeSource */ private CodeSource codesource ; diff --git a/src/share/classes/javax/swing/Timer.java b/src/share/classes/javax/swing/Timer.java index 9e98d5f92..c6c80baed 100644 --- a/src/share/classes/javax/swing/Timer.java +++ b/src/share/classes/javax/swing/Timer.java @@ -35,6 +35,10 @@ import java.util.concurrent.locks.*; import java.awt.*; import java.awt.event.*; import java.io.Serializable; +import java.io.*; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.swing.event.EventListenerList; @@ -208,6 +212,22 @@ public class Timer implements Serializable } } + /* + * The timer's AccessControlContext. + */ + private transient volatile AccessControlContext acc = + AccessController.getContext(); + + /** + * Returns the acc this timer was constructed with. + */ + final AccessControlContext getAccessControlContext() { + if (acc == null) { + throw new SecurityException( + "Timer is missing AccessControlContext"); + } + return acc; + } /** * DoPostEvent is a runnable class that fires actionEvents to @@ -587,8 +607,13 @@ public class Timer implements Serializable void post() { - if (notify.compareAndSet(false, true) || !coalesce) { - SwingUtilities.invokeLater(doPostEvent); + if (notify.compareAndSet(false, true) || !coalesce) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + SwingUtilities.invokeLater(doPostEvent); + return null; + } + }, getAccessControlContext()); } } @@ -596,6 +621,13 @@ public class Timer implements Serializable return lock; } + private void readObject(ObjectInputStream in) + throws ClassNotFoundException, IOException + { + this.acc = AccessController.getContext(); + in.defaultReadObject(); + } + /* * We have to use readResolve because we can not initialize final * fields for deserialized object otherwise diff --git a/src/share/classes/javax/swing/TransferHandler.java b/src/share/classes/javax/swing/TransferHandler.java index eb7f8d1a6..dd54b259e 100644 --- a/src/share/classes/javax/swing/TransferHandler.java +++ b/src/share/classes/javax/swing/TransferHandler.java @@ -42,6 +42,16 @@ import sun.awt.AppContext; import sun.swing.*; import sun.awt.SunToolkit; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import java.security.AccessControlContext; +import java.security.ProtectionDomain; +import sun.misc.SharedSecrets; +import sun.misc.JavaSecurityAccess; + +import sun.awt.AWTAccessor; + /** * This class is used to handle the transfer of a Transferable * to and from Swing components. The Transferable is used to @@ -1686,7 +1696,37 @@ public class TransferHandler implements Serializable { return true; } - public void actionPerformed(ActionEvent e) { + private static final JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + + public void actionPerformed(final ActionEvent e) { + final Object src = e.getSource(); + + final PrivilegedAction action = new PrivilegedAction() { + public Void run() { + actionPerformedImpl(e); + return null; + } + }; + + final AccessControlContext stack = AccessController.getContext(); + final AccessControlContext srcAcc = AWTAccessor.getComponentAccessor().getAccessControlContext((Component)src); + final AccessControlContext eventAcc = AWTAccessor.getAWTEventAccessor().getAccessControlContext(e); + + if (srcAcc == null) { + javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc); + } else { + javaSecurityAccess.doIntersectionPrivilege( + new PrivilegedAction() { + public Void run() { + javaSecurityAccess.doIntersectionPrivilege(action, eventAcc); + return null; + } + }, stack, srcAcc); + } + } + + private void actionPerformedImpl(ActionEvent e) { Object src = e.getSource(); if (src instanceof JComponent) { JComponent c = (JComponent) src; diff --git a/src/share/classes/sun/awt/AWTAccessor.java b/src/share/classes/sun/awt/AWTAccessor.java index 0e38de6df..b88531dfc 100644 --- a/src/share/classes/sun/awt/AWTAccessor.java +++ b/src/share/classes/sun/awt/AWTAccessor.java @@ -33,6 +33,9 @@ import java.awt.image.BufferedImage; import sun.misc.Unsafe; import java.awt.peer.ComponentPeer; +import java.security.AccessController; +import java.security.AccessControlContext; + /** * The AWTAccessor utility class. * The main purpose of this class is to enable accessing @@ -221,6 +224,13 @@ public final class AWTAccessor { * Processes events occurring on this component. */ void processEvent(Component comp, AWTEvent e); + + + /* + * Returns the acc this component was constructed with. + */ + AccessControlContext getAccessControlContext(Component comp); + } /* @@ -323,6 +333,13 @@ public final class AWTAccessor { * Indicates whether this AWTEvent was generated by the system. */ boolean isSystemGenerated(AWTEvent ev); + + + /* + * Returns the acc this event was constructed with. + */ + AccessControlContext getAccessControlContext(AWTEvent ev); + } public interface InputEventAccessor { diff --git a/src/share/classes/sun/misc/JavaSecurityAccess.java b/src/share/classes/sun/misc/JavaSecurityAccess.java new file mode 100644 index 000000000..5a3aa513f --- /dev/null +++ b/src/share/classes/sun/misc/JavaSecurityAccess.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.misc; + +import java.security.AccessControlContext; +import java.security.PrivilegedAction; + +public interface JavaSecurityAccess { + + T doIntersectionPrivilege(PrivilegedAction action, + AccessControlContext stack, + AccessControlContext context); + + T doIntersectionPrivilege(PrivilegedAction action, + AccessControlContext context); + +} diff --git a/src/share/classes/sun/misc/SharedSecrets.java b/src/share/classes/sun/misc/SharedSecrets.java index 2335b2d68..0bd39b4a5 100644 --- a/src/share/classes/sun/misc/SharedSecrets.java +++ b/src/share/classes/sun/misc/SharedSecrets.java @@ -30,6 +30,8 @@ import java.io.Console; import java.io.FileDescriptor; import java.security.ProtectionDomain; +import java.security.AccessController; + /** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without using reflection. A package-private class implements a public @@ -48,6 +50,7 @@ public class SharedSecrets { private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; + private static JavaSecurityAccess javaSecurityAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -125,4 +128,15 @@ public class SharedSecrets { unsafe.ensureClassInitialized(ProtectionDomain.class); return javaSecurityProtectionDomainAccess; } + + public static void setJavaSecurityAccess(JavaSecurityAccess jsa) { + javaSecurityAccess = jsa; + } + + public static JavaSecurityAccess getJavaSecurityAccess() { + if (javaSecurityAccess == null) { + unsafe.ensureClassInitialized(AccessController.class); + } + return javaSecurityAccess; + } } -- GitLab