6907662: System clipboard should ensure access restrictions
authordenis
Thu, 17 Mar 2011 17:16:35 -0700
changeset 8816 29f983feda95
parent 8815 9a3f042d307e
child 8817 5351579c46a9
6907662: System clipboard should ensure access restrictions Reviewed-by: alexp
jdk/src/share/classes/java/awt/AWTEvent.java
jdk/src/share/classes/java/awt/Component.java
jdk/src/share/classes/java/awt/EventQueue.java
jdk/src/share/classes/java/awt/MenuComponent.java
jdk/src/share/classes/java/awt/TrayIcon.java
jdk/src/share/classes/java/security/AccessControlContext.java
jdk/src/share/classes/java/security/ProtectionDomain.java
jdk/src/share/classes/javax/swing/Timer.java
jdk/src/share/classes/javax/swing/TransferHandler.java
jdk/src/share/classes/sun/awt/AWTAccessor.java
jdk/src/share/classes/sun/misc/JavaSecurityAccess.java
jdk/src/share/classes/sun/misc/SharedSecrets.java
--- a/jdk/src/share/classes/java/awt/AWTEvent.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/awt/AWTEvent.java	Thu Mar 17 17:16:35 2011 -0700
@@ -33,6 +33,11 @@
 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 @@
      */
     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 boolean isSystemGenerated(AWTEvent ev) {
                     return ev.isSystemGenerated;
                 }
+
+                public AccessControlContext getAccessControlContext(AWTEvent ev) {
+                    return ev.getAccessControlContext();
+                }
             });
     }
 
--- a/jdk/src/share/classes/java/awt/Component.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/awt/Component.java	Thu Mar 17 17:16:35 2011 -0700
@@ -59,6 +59,7 @@
 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 @@
     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 @@
         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 void processEvent(Component comp, AWTEvent e) {
                 comp.processEvent(e);
             }
+
+            public AccessControlContext getAccessControlContext(Component comp) {
+                return comp.getAccessControlContext();
+            }
         });
     }
 
@@ -8608,6 +8629,8 @@
     {
         objectLock = new Object();
 
+        acc = AccessController.getContext();
+
         s.defaultReadObject();
 
         appContext = AppContext.getAppContext();
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Thu Mar 17 17:16:35 2011 -0700
@@ -48,6 +48,12 @@
 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;
+
 /**
  * <code>EventQueue</code> is a platform-independent class
  * that queues events, both from the underlying peer classes
@@ -612,6 +618,9 @@
         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 @@
      * @throws NullPointerException if <code>event</code> is <code>null</code>
      * @since           1.2
      */
-    protected void dispatchEvent(AWTEvent event) {
+    protected void dispatchEvent(final AWTEvent event) {
+        final Object src = event.getSource();
+        final PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
+            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<Void>() {
+                    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);
--- a/jdk/src/share/classes/java/awt/MenuComponent.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/awt/MenuComponent.java	Thu Mar 17 17:16:35 2011 -0700
@@ -33,6 +33,9 @@
 import sun.awt.AWTAccessor;
 import javax.accessibility.*;
 
+import java.security.AccessControlContext;
+import java.security.AccessController;
+
 /**
  * The abstract class <code>MenuComponent</code> is the superclass
  * of all menu-related components. In this respect, the class
@@ -100,6 +103,23 @@
     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.
      */
     final static String actionListenerK = Component.actionListenerK;
@@ -402,6 +422,9 @@
         throws ClassNotFoundException, IOException, HeadlessException
     {
         GraphicsEnvironment.checkHeadless();
+
+        acc = AccessController.getContext();
+
         s.defaultReadObject();
 
         appContext = AppContext.getAppContext();
--- a/jdk/src/share/classes/java/awt/TrayIcon.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/awt/TrayIcon.java	Thu Mar 17 17:16:35 2011 -0700
@@ -40,6 +40,8 @@
 import sun.awt.SunToolkit;
 import sun.awt.HeadlessToolkit;
 import java.util.EventObject;
+import java.security.AccessControlContext;
+import java.security.AccessController;
 
 /**
  * A <code>TrayIcon</code> object represents a tray icon that can be
@@ -90,6 +92,7 @@
  * @author Anton Tarasov
  */
 public class TrayIcon {
+
     private Image image;
     private String tooltip;
     private PopupMenu popup;
@@ -103,6 +106,24 @@
     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()) {
--- a/jdk/src/share/classes/java/security/AccessControlContext.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/security/AccessControlContext.java	Thu Mar 17 17:16:35 2011 -0700
@@ -29,6 +29,9 @@
 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
@@ -197,6 +200,24 @@
     }
 
     /**
+     * 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.
      */
     boolean isPrivileged()
--- a/jdk/src/share/classes/java/security/ProtectionDomain.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/java/security/ProtectionDomain.java	Thu Mar 17 17:16:35 2011 -0700
@@ -36,6 +36,8 @@
 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 @@
 
 public class ProtectionDomain {
 
+    static {
+        // Set up JavaSecurityAccess in SharedSecrets
+        SharedSecrets.setJavaSecurityAccess(
+            new JavaSecurityAccess() {
+                public <T> T doIntersectionPrivilege(
+                    PrivilegedAction<T> 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> T doIntersectionPrivilege(
+                    PrivilegedAction<T> action,
+                    AccessControlContext context)
+                {
+                    return doIntersectionPrivilege(action,
+                        AccessController.getContext(), context);
+                }
+            }
+       );
+    }
+
     /* CodeSource */
     private CodeSource codesource ;
 
--- a/jdk/src/share/classes/javax/swing/Timer.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/javax/swing/Timer.java	Thu Mar 17 17:16:35 2011 -0700
@@ -35,6 +35,10 @@
 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 @@
         }
     }
 
+    /*
+     * 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 @@
 
 
     void post() {
-        if (notify.compareAndSet(false, true) || !coalesce) {
-            SwingUtilities.invokeLater(doPostEvent);
+         if (notify.compareAndSet(false, true) || !coalesce) {
+             AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                 public Void run() {
+                     SwingUtilities.invokeLater(doPostEvent);
+                     return null;
+                }
+            }, getAccessControlContext());
         }
     }
 
@@ -596,6 +621,13 @@
         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
--- a/jdk/src/share/classes/javax/swing/TransferHandler.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/javax/swing/TransferHandler.java	Thu Mar 17 17:16:35 2011 -0700
@@ -42,6 +42,16 @@
 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 <code>Transferable</code>
  * to and from Swing components.  The <code>Transferable</code> is used to
@@ -1686,7 +1696,37 @@
             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<Void> action = new PrivilegedAction<Void>() {
+                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<Void>() {
+                            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;
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Thu Mar 17 17:16:35 2011 -0700
@@ -33,6 +33,9 @@
 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 @@
          * 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 @@
          * 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 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/JavaSecurityAccess.java	Thu Mar 17 17:16:35 2011 -0700
@@ -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> T doIntersectionPrivilege(PrivilegedAction<T> action,
+                                  AccessControlContext stack,
+                                  AccessControlContext context);
+
+    <T> T doIntersectionPrivilege(PrivilegedAction<T> action,
+                                  AccessControlContext context);
+
+}
--- a/jdk/src/share/classes/sun/misc/SharedSecrets.java	Mon Jan 10 18:12:43 2011 +0000
+++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java	Thu Mar 17 17:16:35 2011 -0700
@@ -30,6 +30,8 @@
 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 @@
     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 @@
                 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;
+    }
 }