This patch adds a missing security check to the ObjectOutputStream(OutputStream)
constructor as reported in PR42390.
2010-12-25 Andrew John Hughes <[email protected]>
PR classpath/42390
* java/io/ObjectOutputStream.java:
(ObjectOutputStream(OutputStream)): Add
required security check.
(overridesMethods(Class<?>)): Check whether
the subclass overrides one of the methods
which requires a security check.
--
Andrew :)
Free Java Software Engineer
Red Hat, Inc. (http://www.redhat.com)
Support Free Java!
Contribute to GNU Classpath and IcedTea
http://www.gnu.org/software/classpath
http://icedtea.classpath.org
PGP Key: 94EFD9D8 (http://subkeys.pgp.net)
Fingerprint = F8EF F1EA 401E 2E60 15FA 7927 142C 2591 94EF D9D8
Index: java/io/ObjectOutputStream.java
===================================================================
RCS file: /sources/classpath/classpath/java/io/ObjectOutputStream.java,v
retrieving revision 1.74
diff -u -u -r1.74 ObjectOutputStream.java
--- java/io/ObjectOutputStream.java 3 Jun 2010 19:12:56 -0000 1.74
+++ java/io/ObjectOutputStream.java 25 Dec 2010 16:10:07 -0000
@@ -48,6 +48,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
/**
* An <code>ObjectOutputStream</code> can be used to write objects
@@ -136,6 +138,10 @@
*/
public ObjectOutputStream (OutputStream out) throws IOException
{
+ SecurityManager secMan = System.getSecurityManager();
+ if (secMan != null && overridesMethods(getClass()))
+ secMan.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
+
realOutput = new DataOutputStream(out);
blockData = new byte[ BUFFER_SIZE ];
blockDataCount = 0;
@@ -1481,4 +1487,44 @@
private boolean dump = false;
private static final boolean DEBUG = false;
+
+ /**
+ * Returns true if the given class overrides either of the
+ * methods <code>putFields</code> or <code>writeUnshared</code>.
+ *
+ * @param clazz the class to check.
+ * @return true if the class overrides one of the methods.
+ */
+ private static boolean overridesMethods(final Class<?> clazz)
+ {
+ if (clazz == ObjectOutputStream.class)
+ return false;
+
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run()
+ {
+ Method[] methods = clazz.getDeclaredMethods();
+ for (int a = 0; a < methods.length; ++a)
+ {
+ String name = methods[a].getName();
+ if (name.equals("writeUnshared"))
+ {
+ Class<?>[] paramTypes = methods[a].getParameterTypes();
+ if (paramTypes.length == 1 &&
+ paramTypes[0] == Object.class &&
+ methods[a].getReturnType() == Void.class)
+ return true;
+ }
+ else if (name.equals("putFields"))
+ {
+ if (methods[a].getParameterTypes().length == 0 &&
+ methods[a].getReturnType() == PutField.class)
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ }
+
}