# HG changeset patch # User robm # Date 1500161350 -3600 # Node ID 0e846618238e7d0470c38ecc721dee785cdfd9dc # Parent 8f1c0d565d1322e0b1357c59b8a4fbb0bd429b48 8174770: Check registry registration location Reviewed-by: rriggs diff -r 8f1c0d565d13 -r 0e846618238e make/sun/rmi/rmi/Makefile --- a/make/sun/rmi/rmi/Makefile Sat Jul 15 21:26:47 2017 +0100 +++ b/make/sun/rmi/rmi/Makefile Sun Jul 16 00:29:10 2017 +0100 @@ -52,15 +52,9 @@ include $(BUILDDIR)/common/Rules.gmk # -# Full package names of implementations requiring stubs -# -REMOTE_impls = \ - sun.rmi.registry.RegistryImpl - -# # The java-rmi.cgi script in bin/ only gets delivered in certain situations # -BUILD_TARGETS = stubs +BUILD_TARGETS = ifeq ($(PLATFORM), linux) BUILD_TARGETS += bin endif @@ -74,30 +68,6 @@ clean clobber:: bin.clean - -# -# Compile stubs and skeletons for remote implementations -# (use -v1.1 for backward interoperability) -# -# gnumake 3.78.1 on windows attempts to build the target even -# though it exists. Not sure why, but a check for file existence -# has been added... -# -REMOTE_files = $(subst .,/,$(REMOTE_impls)) -FILES_classes = $(REMOTE_files:%=$(CLASSBINDIR)/%.class) -FILES_stubs = $(REMOTE_files:%=$(CLASSBINDIR)/%_Stub.class) -FILES_skels = $(REMOTE_files:%=$(CLASSBINDIR)/%_Skel.class) - -$(FILES_stubs) $(FILES_skels): $(FILES_classes) - if [ ! -s $@ ] ; \ - then $(RMIC) -v1.1 -classpath \ - "$(CLASSBINDIR)" \ - -d $(CLASSBINDIR) '$(subst /,.,$(<:$(CLASSBINDIR)/%.class=%))' ; \ - fi - @$(java-vm-cleanup) - -stubs: $(FILES_stubs) $(FILES_skels) - bin: $(BINDIR)/java-rmi.cgi $(BINDIR)/java-rmi.cgi: $(PLATFORM_SRC)/bin/java-rmi.cgi.sh @@ -107,5 +77,5 @@ bin.clean: $(RM) $(BINDIR)/java-rmi.cgi -.PHONY: stubs bin bin.clean +.PHONY: bin bin.clean diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java --- a/src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Sat Jul 15 21:26:47 2017 +0100 +++ b/src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Sun Jul 16 00:29:10 2017 +0100 @@ -32,6 +32,7 @@ package sun.management.jmxremote; +import sun.misc.ObjectInputFilter; import java.rmi.AccessException; import java.rmi.NotBoundException; import java.rmi.Remote; @@ -56,7 +57,12 @@ String name, Remote object) throws RemoteException { - super(port, csf, ssf); + super(port, csf, ssf, new ObjectInputFilter() { + @Override + public Status checkInput(ObjectInputFilter.FilterInfo info) { + return SingleEntryRegistry.singleRegistryFilter(info); + } + }); this.name = name; this.object = object; } @@ -84,6 +90,23 @@ throw new AccessException("Cannot modify this registry"); } + /** + * ObjectInputFilter to check parameters to SingleEntryRegistry. + * Since it is a read-only Registry, no classes are accepted. + * String arguments are accepted without passing them to the serialFilter. + * + * @param info a reference to the serialization filter information + * @return Status.REJECTED if parameters are out of range + */ + private static ObjectInputFilter.Status singleRegistryFilter(ObjectInputFilter.FilterInfo info) { + return (info.serialClass() != null || + info.depth() > 2 || + info.references() > 4 || + info.arrayLength() >= 0) + ? ObjectInputFilter.Status.REJECTED + : ObjectInputFilter.Status.ALLOWED; + } + private final String name; private final Remote object; diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/rmi/registry/RegistryImpl.java --- a/src/share/classes/sun/rmi/registry/RegistryImpl.java Sat Jul 15 21:26:47 2017 +0100 +++ b/src/share/classes/sun/rmi/registry/RegistryImpl.java Sun Jul 16 00:29:10 2017 +0100 @@ -69,6 +69,10 @@ * registry. * * The LocateRegistry class is used to obtain registry for different hosts. + *

+ * The default RegistryImpl exported restricts access to clients on the local host + * for the methods {@link #bind}, {@link #rebind}, {@link #unbind} by checking + * the client host in the skeleton. * * @see java.rmi.registry.LocateRegistry */ @@ -107,11 +111,18 @@ */ private static final ObjectInputFilter registryFilter = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ObjectInputFilter run() { - return initRegistryFilter(); - } - }); + @Override + public ObjectInputFilter run() { + return initRegistryFilter(); + } + }); + + private static final ObjectInputFilter defaultFilter = new ObjectInputFilter() { + @Override + public Status checkInput(ObjectInputFilter.FilterInfo info) { + return RegistryImpl.registryFilter(info); + } + }; /** * Initialize the registryFilter from the security properties or system property; if any @@ -142,8 +153,22 @@ RMIServerSocketFactory ssf) throws RemoteException { + this(port, csf, ssf, defaultFilter); + } + + + /** + * Construct a new RegistryImpl on the specified port with the + * given custom socket factory pair and ObjectInputFilter. + */ + public RegistryImpl(int port, + RMIClientSocketFactory csf, + RMIServerSocketFactory ssf, + ObjectInputFilter serialFilter) + throws RemoteException + { LiveRef lref = new LiveRef(id, port, csf, ssf); - setup(new UnicastServerRef2(lref, registryFilter())); + setup(new UnicastServerRef2(lref, serialFilter)); } /** @@ -153,7 +178,7 @@ throws RemoteException { LiveRef lref = new LiveRef(id, port); - setup(new UnicastServerRef(lref, registryFilter())); + setup(new UnicastServerRef(lref, defaultFilter)); } /* @@ -194,7 +219,8 @@ public void bind(String name, Remote obj) throws RemoteException, AlreadyBoundException, AccessException { - checkAccess("Registry.bind"); + // The access check preventing remote access is done in the skeleton + // and is not applicable to local access. synchronized (bindings) { Remote curr = bindings.get(name); if (curr != null) @@ -211,7 +237,8 @@ public void unbind(String name) throws RemoteException, NotBoundException, AccessException { - checkAccess("Registry.unbind"); + // The access check preventing remote access is done in the skeleton + // and is not applicable to local access. synchronized (bindings) { Remote obj = bindings.get(name); if (obj == null) @@ -227,7 +254,8 @@ public void rebind(String name, Remote obj) throws RemoteException, AccessException { - checkAccess("Registry.rebind"); + // The access check preventing remote access is done in the skeleton + // and is not applicable to local access. bindings.put(name, obj); } @@ -254,7 +282,6 @@ * 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. @@ -280,7 +307,7 @@ if (clientHost.isAnyLocalAddress()) { throw new AccessException( - "Registry." + op + " disallowed; origin unknown"); + op + " disallowed; origin unknown"); } try { @@ -303,7 +330,7 @@ // must have been an IOException throw new AccessException( - "Registry." + op + " disallowed; origin " + + op + " disallowed; origin " + clientHost + " is non-local host"); } } @@ -312,8 +339,7 @@ * Local call from this VM: allow access. */ } catch (java.net.UnknownHostException ex) { - throw new AccessException("Registry." + op + - " disallowed; origin is unknown host"); + throw new AccessException(op + " disallowed; origin is unknown host"); } } @@ -360,53 +386,48 @@ * {@link ObjectInputFilter.Status#REJECTED} if rejected, * otherwise {@link ObjectInputFilter.Status#UNDECIDED} */ - private static ObjectInputFilter registryFilter() { - return new ObjectInputFilter() { - @Override - public ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo filterInfo) { - if (registryFilter != null) { - ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); - if (status != ObjectInputFilter.Status.UNDECIDED) { - // The Registry filter can override the built-in white-list - return status; - } - } + private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) { + if (registryFilter != null) { + ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); + if (status != ObjectInputFilter.Status.UNDECIDED) { + // The Registry filter can override the built-in white-list + return status; + } + } - if (filterInfo.depth() > REGISTRY_MAX_DEPTH) { + if (filterInfo.depth() > REGISTRY_MAX_DEPTH) { + return ObjectInputFilter.Status.REJECTED; + } + Class clazz = filterInfo.serialClass(); + if (clazz != null) { + if (clazz.isArray()) { + if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) { return ObjectInputFilter.Status.REJECTED; } - Class clazz = filterInfo.serialClass(); - if (clazz != null) { - if (clazz.isArray()) { - if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) { - return ObjectInputFilter.Status.REJECTED; - } - do { - // Arrays are allowed depending on the component type - clazz = clazz.getComponentType(); - } while (clazz.isArray()); - } - if (clazz.isPrimitive()) { - // Arrays of primitives are allowed - return ObjectInputFilter.Status.ALLOWED; - } - if (String.class == clazz - || java.lang.Number.class.isAssignableFrom(clazz) - || Remote.class.isAssignableFrom(clazz) - || java.lang.reflect.Proxy.class.isAssignableFrom(clazz) - || UnicastRef.class.isAssignableFrom(clazz) - || RMIClientSocketFactory.class.isAssignableFrom(clazz) - || RMIServerSocketFactory.class.isAssignableFrom(clazz) - || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz) - || java.rmi.server.UID.class.isAssignableFrom(clazz)) { - return ObjectInputFilter.Status.ALLOWED; - } else { - return ObjectInputFilter.Status.REJECTED; - } - } - return ObjectInputFilter.Status.UNDECIDED; + do { + // Arrays are allowed depending on the component type + clazz = clazz.getComponentType(); + } while (clazz.isArray()); + } + if (clazz.isPrimitive()) { + // Arrays of primitives are allowed + return ObjectInputFilter.Status.ALLOWED; } - }; + if (String.class == clazz + || java.lang.Number.class.isAssignableFrom(clazz) + || Remote.class.isAssignableFrom(clazz) + || java.lang.reflect.Proxy.class.isAssignableFrom(clazz) + || UnicastRef.class.isAssignableFrom(clazz) + || RMIClientSocketFactory.class.isAssignableFrom(clazz) + || RMIServerSocketFactory.class.isAssignableFrom(clazz) + || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz) + || java.rmi.server.UID.class.isAssignableFrom(clazz)) { + return ObjectInputFilter.Status.ALLOWED; + } else { + return ObjectInputFilter.Status.REJECTED; + } + } + return ObjectInputFilter.Status.UNDECIDED; } /** diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java Sun Jul 16 00:29:10 2017 +0100 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017, 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.rmi.registry; + +import java.io.IOException; +import java.io.InputStream; +import java.rmi.AccessException; +import java.rmi.server.RemoteCall; + +import sun.rmi.transport.Connection; +import sun.rmi.transport.StreamRemoteCall; +import sun.rmi.transport.tcp.TCPConnection; + +/** + * Skeleton to dispatch RegistryImpl methods. + * Originally generated by RMIC but frozen to match the stubs. + */ +@SuppressWarnings({"deprecation", "serial"}) +public final class RegistryImpl_Skel + implements java.rmi.server.Skeleton { + private static final java.rmi.server.Operation[] operations = { + new java.rmi.server.Operation("void bind(java.lang.String, java.rmi.Remote)"), + new java.rmi.server.Operation("java.lang.String list()[]"), + new java.rmi.server.Operation("java.rmi.Remote lookup(java.lang.String)"), + new java.rmi.server.Operation("void rebind(java.lang.String, java.rmi.Remote)"), + new java.rmi.server.Operation("void unbind(java.lang.String)") + }; + + private static final long interfaceHash = 4905912898345647071L; + + public java.rmi.server.Operation[] getOperations() { + return operations.clone(); + } + + public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash) + throws java.lang.Exception { + if (hash != interfaceHash) + throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch"); + + sun.rmi.registry.RegistryImpl server = (sun.rmi.registry.RegistryImpl) obj; + switch (opnum) { + case 0: // bind(String, Remote) + { + // Check access before reading the arguments + RegistryImpl.checkAccess("Registry.bind"); + + java.lang.String $param_String_1; + java.rmi.Remote $param_Remote_2; + try { + java.io.ObjectInput in = call.getInputStream(); + $param_String_1 = (java.lang.String) in.readObject(); + $param_Remote_2 = (java.rmi.Remote) in.readObject(); + } catch (java.io.IOException | java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); + } finally { + call.releaseInputStream(); + } + server.bind($param_String_1, $param_Remote_2); + try { + call.getResultStream(true); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling return", e); + } + break; + } + + case 1: // list() + { + call.releaseInputStream(); + java.lang.String[] $result = server.list(); + try { + java.io.ObjectOutput out = call.getResultStream(true); + out.writeObject($result); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling return", e); + } + break; + } + + case 2: // lookup(String) + { + java.lang.String $param_String_1; + try { + java.io.ObjectInput in = call.getInputStream(); + $param_String_1 = (java.lang.String) in.readObject(); + } catch (java.io.IOException | java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); + } finally { + call.releaseInputStream(); + } + java.rmi.Remote $result = server.lookup($param_String_1); + try { + java.io.ObjectOutput out = call.getResultStream(true); + out.writeObject($result); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling return", e); + } + break; + } + + case 3: // rebind(String, Remote) + { + // Check access before reading the arguments + RegistryImpl.checkAccess("Registry.rebind"); + + java.lang.String $param_String_1; + java.rmi.Remote $param_Remote_2; + try { + java.io.ObjectInput in = call.getInputStream(); + $param_String_1 = (java.lang.String) in.readObject(); + $param_Remote_2 = (java.rmi.Remote) in.readObject(); + } catch (java.io.IOException | java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); + } finally { + call.releaseInputStream(); + } + server.rebind($param_String_1, $param_Remote_2); + try { + call.getResultStream(true); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling return", e); + } + break; + } + + case 4: // unbind(String) + { + // Check access before reading the arguments + RegistryImpl.checkAccess("Registry.unbind"); + + java.lang.String $param_String_1; + try { + java.io.ObjectInput in = call.getInputStream(); + $param_String_1 = (java.lang.String) in.readObject(); + } catch (java.io.IOException | java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling arguments", e); + } finally { + call.releaseInputStream(); + } + server.unbind($param_String_1); + try { + call.getResultStream(true); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling return", e); + } + break; + } + + default: + throw new java.rmi.UnmarshalException("invalid method number"); + } + } +} diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java Sun Jul 16 00:29:10 2017 +0100 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2017, 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.rmi.registry; +/** + * Stubs to invoke RegistryImpl remote methods. + * Originally generated from RMIC but frozen to match RegistryImpl_Skel. + */ +@SuppressWarnings({"deprecation", "serial"}) +public final class RegistryImpl_Stub + extends java.rmi.server.RemoteStub + implements java.rmi.registry.Registry, java.rmi.Remote { + private static final java.rmi.server.Operation[] operations = { + new java.rmi.server.Operation("void bind(java.lang.String, java.rmi.Remote)"), + new java.rmi.server.Operation("java.lang.String list()[]"), + new java.rmi.server.Operation("java.rmi.Remote lookup(java.lang.String)"), + new java.rmi.server.Operation("void rebind(java.lang.String, java.rmi.Remote)"), + new java.rmi.server.Operation("void unbind(java.lang.String)") + }; + + private static final long interfaceHash = 4905912898345647071L; + + // constructors + public RegistryImpl_Stub() { + super(); + } + + public RegistryImpl_Stub(java.rmi.server.RemoteRef ref) { + super(ref); + } + + // methods from remote interfaces + + // implementation of bind(String, Remote) + public void bind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2) + throws java.rmi.AccessException, java.rmi.AlreadyBoundException, java.rmi.RemoteException { + try { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_String_1); + out.writeObject($param_Remote_2); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + ref.done(call); + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.rmi.AlreadyBoundException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of list() + public java.lang.String[] list() + throws java.rmi.AccessException, java.rmi.RemoteException { + try { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); + ref.invoke(call); + java.lang.String[] $result; + try { + java.io.ObjectInput in = call.getInputStream(); + $result = (java.lang.String[]) in.readObject(); + } catch (java.io.IOException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } catch (java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } finally { + ref.done(call); + } + return $result; + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of lookup(String) + public java.rmi.Remote lookup(java.lang.String $param_String_1) + throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException { + try { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 2, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_String_1); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + java.rmi.Remote $result; + try { + java.io.ObjectInput in = call.getInputStream(); + $result = (java.rmi.Remote) in.readObject(); + } catch (java.io.IOException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } catch (java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } finally { + ref.done(call); + } + return $result; + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.rmi.NotBoundException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of rebind(String, Remote) + public void rebind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2) + throws java.rmi.AccessException, java.rmi.RemoteException { + try { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 3, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_String_1); + out.writeObject($param_Remote_2); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + ref.done(call); + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of unbind(String) + public void unbind(java.lang.String $param_String_1) + throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException { + try { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 4, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_String_1); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + ref.done(call); + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.rmi.NotBoundException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } +} diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/rmi/server/Activation.java --- a/src/share/classes/sun/rmi/server/Activation.java Sat Jul 15 21:26:47 2017 +0100 +++ b/src/share/classes/sun/rmi/server/Activation.java Sun Jul 16 00:29:10 2017 +0100 @@ -30,6 +30,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.OutputStream; import java.io.PrintStream; @@ -105,7 +106,6 @@ import sun.rmi.log.ReliableLog; import sun.rmi.registry.RegistryImpl; import sun.rmi.runtime.NewThreadAction; -import sun.rmi.server.UnicastServerRef; import sun.rmi.transport.LiveRef; import sun.security.action.GetBooleanAction; import sun.security.action.GetIntegerAction; @@ -345,6 +345,7 @@ throw new AccessException( "binding ActivationSystem is disallowed"); } else { + RegistryImpl.checkAccess("ActivationSystem.bind"); super.bind(name, obj); } } @@ -356,6 +357,7 @@ throw new AccessException( "unbinding ActivationSystem is disallowed"); } else { + RegistryImpl.checkAccess("ActivationSystem.unbind"); super.unbind(name); } } @@ -368,6 +370,7 @@ throw new AccessException( "binding ActivationSystem is disallowed"); } else { + RegistryImpl.checkAccess("ActivationSystem.rebind"); super.rebind(name, obj); } } @@ -458,6 +461,33 @@ } + /** + * SameHostOnlyServerRef checks that access is from a local client + * before the parameters are deserialized. The unmarshalCustomCallData + * hook is used to check the network address of the caller + * with RegistryImpl.checkAccess(). + * The kind of access is retained for an exception if one is thrown. + */ + static class SameHostOnlyServerRef extends UnicastServerRef { + private static final long serialVersionUID = 1234L; + private String accessKind; // an exception message + + /** + * Construct a new SameHostOnlyServerRef from a LiveRef. + * @param lref a LiveRef + */ + SameHostOnlyServerRef(LiveRef lref, String accessKind) { + super(lref); + this.accessKind = accessKind; + } + + @Override + protected void unmarshalCustomCallData(ObjectInput in) throws IOException, ClassNotFoundException { + RegistryImpl.checkAccess(accessKind); + super.unmarshalCustomCallData(in); + } + } + class ActivationSystemImpl extends RemoteServer implements ActivationSystem @@ -475,7 +505,8 @@ * 'this' can be exported. */ LiveRef lref = new LiveRef(new ObjID(4), port, null, ssf); - UnicastServerRef uref = new UnicastServerRef(lref); + UnicastServerRef uref = new SameHostOnlyServerRef(lref, + "ActivationSystem.nonLocalAccess"); ref = uref; uref.exportObject(this, null); } @@ -484,8 +515,8 @@ throws ActivationException, UnknownGroupException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.registerObject"); - + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. ActivationGroupID groupID = desc.getGroupID(); ActivationID id = new ActivationID(activatorStub); getGroupEntry(groupID).registerObject(id, desc, true); @@ -496,15 +527,18 @@ throws ActivationException, UnknownObjectException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.unregisterObject"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. getGroupEntry(id).unregisterObject(id, true); } public ActivationGroupID registerGroup(ActivationGroupDesc desc) throws ActivationException, RemoteException { + Thread.dumpStack(); checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.registerGroup"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. checkArgs(desc, null); ActivationGroupID id = new ActivationGroupID(systemStub); @@ -521,7 +555,8 @@ throws ActivationException, UnknownGroupException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.activeGroup"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. getGroupEntry(id).activeGroup(group, incarnation); return monitor; @@ -531,7 +566,8 @@ throws ActivationException, UnknownGroupException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.unregisterGroup"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. // remove entry before unregister so state is updated before // logged @@ -543,7 +579,8 @@ throws ActivationException, UnknownObjectException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.setActivationDesc"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. if (!getGroupID(id).equals(desc.getGroupID())) { throw new ActivationException( @@ -557,8 +594,8 @@ throws ActivationException, UnknownGroupException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess( - "ActivationSystem.setActivationGroupDesc"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. checkArgs(desc, null); return getGroupEntry(id).setActivationGroupDesc(id, desc, true); @@ -568,7 +605,8 @@ throws ActivationException, UnknownObjectException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess("ActivationSystem.getActivationDesc"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. return getGroupEntry(id).getActivationDesc(id); } @@ -577,8 +615,8 @@ throws ActivationException, UnknownGroupException, RemoteException { checkShutdown(); - RegistryImpl.checkAccess - ("ActivationSystem.getActivationGroupDesc"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. return getGroupEntry(id).desc; } @@ -588,7 +626,8 @@ * the activation daemon and exits the activation daemon. */ public void shutdown() throws AccessException { - RegistryImpl.checkAccess("ActivationSystem.shutdown"); + // RegistryImpl.checkAccess() is done in the SameHostOnlyServerRef + // during unmarshallCustomData and is not applicable to local access. Object lock = startupLock; if (lock != null) { diff -r 8f1c0d565d13 -r 0e846618238e src/share/classes/sun/rmi/server/UnicastServerRef.java --- a/src/share/classes/sun/rmi/server/UnicastServerRef.java Sat Jul 15 21:26:47 2017 +0100 +++ b/src/share/classes/sun/rmi/server/UnicastServerRef.java Sun Jul 16 00:29:10 2017 +0100 @@ -32,6 +32,7 @@ import java.io.ObjectStreamClass; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.rmi.AccessException; import java.rmi.MarshalException; import java.rmi.Remote; import java.rmi.RemoteException; @@ -290,20 +291,25 @@ try { in = call.getInputStream(); num = in.readInt(); - if (num >= 0) { - if (skel != null) { - oldDispatch(obj, call, num); - return; - } else { - throw new UnmarshalException( - "skeleton class not found but required " + - "for client version"); - } + } catch (Exception readEx) { + throw new UnmarshalException("error unmarshalling call header", + readEx); + } + if (num >= 0) { + if (skel != null) { + oldDispatch(obj, call, num); + return; + } else { + throw new UnmarshalException( + "skeleton class not found but required " + + "for client version"); } + } + try { op = in.readLong(); } catch (Exception readEx) { throw new UnmarshalException("error unmarshalling call header", - readEx); + readEx); } /* @@ -331,6 +337,11 @@ try { unmarshalCustomCallData(in); params = unmarshalParameters(obj, method, marshalStream); + } catch (AccessException aex) { + // For compatibility, AccessException is not wrapped in UnmarshalException + // disable saving any refs in the inputStream for GC + ((StreamRemoteCall) call).discardPendingRefs(); + throw aex; } catch (java.io.IOException | ClassNotFoundException e) { // disable saving any refs in the inputStream for GC ((StreamRemoteCall) call).discardPendingRefs(); @@ -367,6 +378,7 @@ */ } } catch (Throwable e) { + Throwable origEx = e; logCallException(e); ObjectOutput out = call.getResultStream(false); @@ -382,6 +394,12 @@ clearStackTraces(e); } out.writeObject(e); + + // AccessExceptions should cause Transport.serviceCall + // to flag the connection as unusable. + if (origEx instanceof AccessException) { + throw new IOException("Connection is not reusable", origEx); + } } finally { call.releaseInputStream(); // in case skeleton doesn't call.releaseOutputStream(); @@ -413,62 +431,41 @@ * Handle server-side dispatch using the RMI 1.1 stub/skeleton * protocol, given a non-negative operation number that has * already been read from the call stream. + * Exceptions are handled by the caller to be sent to the remote client. * * @param obj the target remote object for the call * @param call the "remote call" from which operation and * method arguments can be obtained. * @param op the operation number - * @exception IOException if unable to marshal return result or + * @throws Exception if unable to marshal return result or * release input or output streams */ - public void oldDispatch(Remote obj, RemoteCall call, int op) - throws IOException + private void oldDispatch(Remote obj, RemoteCall call, int op) + throws Exception { long hash; // hash for matching stub with skeleton + // read remote call header + ObjectInput in; + in = call.getInputStream(); try { - // read remote call header - ObjectInput in; - try { - in = call.getInputStream(); - try { - Class clazz = Class.forName("sun.rmi.transport.DGCImpl_Skel"); - if (clazz.isAssignableFrom(skel.getClass())) { - ((MarshalInputStream)in).useCodebaseOnly(); - } - } catch (ClassNotFoundException ignore) { } - hash = in.readLong(); - } catch (Exception readEx) { - throw new UnmarshalException("error unmarshalling call header", - readEx); + Class clazz = Class.forName("sun.rmi.transport.DGCImpl_Skel"); + if (clazz.isAssignableFrom(skel.getClass())) { + ((MarshalInputStream)in).useCodebaseOnly(); } + } catch (ClassNotFoundException ignore) { } - // if calls are being logged, write out object id and operation - logCall(obj, skel.getOperations()[op]); - unmarshalCustomCallData(in); - // dispatch to skeleton for remote object - skel.dispatch(obj, call, op, hash); - - } catch (Throwable e) { - logCallException(e); + try { + hash = in.readLong(); + } catch (Exception ioe) { + throw new UnmarshalException("error unmarshalling call header", ioe); + } - ObjectOutput out = call.getResultStream(false); - if (e instanceof Error) { - e = new ServerError( - "Error occurred in server thread", (Error) e); - } else if (e instanceof RemoteException) { - e = new ServerException( - "RemoteException occurred in server thread", - (Exception) e); - } - if (suppressStackTraces) { - clearStackTraces(e); - } - out.writeObject(e); - } finally { - call.releaseInputStream(); // in case skeleton doesn't - call.releaseOutputStream(); - } + // if calls are being logged, write out object id and operation + logCall(obj, skel.getOperations()[op]); + unmarshalCustomCallData(in); + // dispatch to skeleton for remote object + skel.dispatch(obj, call, op, hash); } /**