6981922: DNS cache poisoning by untrusted applets
authormichaelm
Thu, 17 Mar 2011 18:26:50 -0700
changeset 8817 5351579c46a9
parent 8816 29f983feda95
child 8818 f0456a8381f6
6981922: DNS cache poisoning by untrusted applets Reviewed-by: chegar
jdk/make/sun/net/FILES_java.gmk
jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
jdk/src/share/classes/sun/net/ResourceManager.java
jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
jdk/src/share/classes/sun/nio/ch/Net.java
--- a/jdk/make/sun/net/FILES_java.gmk	Thu Mar 17 17:16:35 2011 -0700
+++ b/jdk/make/sun/net/FILES_java.gmk	Thu Mar 17 18:26:50 2011 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 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
@@ -34,6 +34,7 @@
 	sun/net/ProgressListener.java \
 	sun/net/ProgressMeteringPolicy.java \
 	sun/net/SocksProxy.java \
+	sun/net/ResourceManager.java \
 	sun/net/TelnetInputStream.java \
 	sun/net/TelnetOutputStream.java \
 	sun/net/TelnetProtocolException.java \
--- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Thu Mar 17 17:16:35 2011 -0700
+++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Thu Mar 17 18:26:50 2011 -0700
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.util.Enumeration;
+import sun.net.ResourceManager;
 
 /**
  * Abstract datagram and multicast socket implementation base class.
@@ -66,7 +67,14 @@
      */
     protected synchronized void create() throws SocketException {
         fd = new FileDescriptor();
-        datagramSocketCreate();
+        ResourceManager.beforeUdpCreate();
+        try {
+            datagramSocketCreate();
+        } catch (SocketException ioe) {
+            ResourceManager.afterUdpClose();
+            fd = null;
+            throw ioe;
+        }
     }
 
     /**
@@ -211,6 +219,7 @@
     protected void close() {
         if (fd != null) {
             datagramSocketClose();
+            ResourceManager.afterUdpClose();
             fd = null;
         }
     }
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Mar 17 17:16:35 2011 -0700
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Mar 17 18:26:50 2011 -0700
@@ -32,6 +32,7 @@
 
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
+import sun.net.ResourceManager;
 
 /**
  * Default Socket Implementation. This implementation does
@@ -68,6 +69,10 @@
     private int resetState;
     private final Object resetLock = new Object();
 
+   /* whether this Socket is a stream (TCP) socket or not (UDP)
+    */
+    private boolean stream;
+
     /**
      * Load net library into runtime.
      */
@@ -82,7 +87,19 @@
      */
     protected synchronized void create(boolean stream) throws IOException {
         fd = new FileDescriptor();
-        socketCreate(stream);
+        this.stream = stream;
+        if (!stream) {
+            ResourceManager.beforeUdpCreate();
+            try {
+                socketCreate(false);
+            } catch (IOException ioe) {
+                ResourceManager.afterUdpClose();
+                fd = null;
+                throw ioe;
+            }
+        } else {
+            socketCreate(true);
+        }
         if (socket != null)
             socket.setCreated();
         if (serverSocket != null)
@@ -479,6 +496,9 @@
     protected void close() throws IOException {
         synchronized(fdLock) {
             if (fd != null) {
+                if (!stream) {
+                    ResourceManager.afterUdpClose();
+                }
                 if (fdUseCount == 0) {
                     if (closePending) {
                         return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/ResourceManager.java	Thu Mar 17 18:26:50 2011 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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.  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.net;
+
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Manages count of total number of UDP sockets and ensures
+ * that exception is thrown if we try to create more than the
+ * configured limit.
+ *
+ * This functionality could be put in NetHooks some time in future.
+ */
+
+public class ResourceManager {
+
+    /* default maximum number of udp sockets per VM
+     * when a security manager is enabled.
+     * The default is 1024 which is high enough to be useful
+     * but low enough to be well below the maximum number
+     * of port numbers actually available on all OSes for
+     * such sockets (5000 on some versions of windows)
+     */
+
+    private static final int DEFAULT_MAX_SOCKETS = 1024;
+    private static final int maxSockets;
+    private static final AtomicInteger numSockets;
+
+    static {
+        String prop = java.security.AccessController.doPrivileged(
+            new GetPropertyAction("sun.net.maxDatagramSockets")
+        );
+        int defmax = DEFAULT_MAX_SOCKETS;
+        try {
+            if (prop != null) {
+                defmax = Integer.parseInt(prop);
+            }
+        } catch (NumberFormatException e) {}
+        maxSockets = defmax;
+        numSockets = new AtomicInteger(0);
+    }
+
+    public static void beforeUdpCreate() throws SocketException {
+        if (System.getSecurityManager() != null) {
+            if (numSockets.incrementAndGet() > maxSockets) {
+                numSockets.decrementAndGet();
+                throw new SocketException("maximum number of DatagramSockets reached");
+            }
+        }
+    }
+
+    public static void afterUdpClose() {
+        if (System.getSecurityManager() != null) {
+            numSockets.decrementAndGet();
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Mar 17 17:16:35 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Mar 17 18:26:50 2011 -0700
@@ -32,6 +32,7 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
+import sun.net.ResourceManager;
 
 
 /**
@@ -101,14 +102,22 @@
         throws IOException
     {
         super(sp);
-        this.family = Net.isIPv6Available() ?
-            StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
-        this.fd = Net.socket(family, false);
-        this.fdVal = IOUtil.fdVal(fd);
-        this.state = ST_UNCONNECTED;
+        ResourceManager.beforeUdpCreate();
+        try {
+            this.family = Net.isIPv6Available() ?
+                StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
+            this.fd = Net.socket(family, false);
+            this.fdVal = IOUtil.fdVal(fd);
+            this.state = ST_UNCONNECTED;
+        } catch (IOException ioe) {
+            ResourceManager.afterUdpClose();
+            throw ioe;
+        }
     }
 
-    public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) {
+    public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
+        throws IOException
+    {
         super(sp);
         if ((family != StandardProtocolFamily.INET) &&
             (family != StandardProtocolFamily.INET6))
@@ -957,6 +966,7 @@
     protected void implCloseSelectableChannel() throws IOException {
         synchronized (stateLock) {
             nd.preClose(fd);
+            ResourceManager.afterUdpClose();
 
             // if member of mulitcast group then invalidate all keys
             if (registry != null)
--- a/jdk/src/share/classes/sun/nio/ch/Net.java	Thu Mar 17 17:16:35 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Net.java	Thu Mar 17 18:26:50 2011 -0700
@@ -312,11 +312,12 @@
 
     private static native boolean canJoin6WithIPv4Group0();
 
-    static FileDescriptor socket(boolean stream) {
+    static FileDescriptor socket(boolean stream) throws IOException {
         return socket(UNSPEC, stream);
     }
 
-    static FileDescriptor socket(ProtocolFamily family, boolean stream) {
+    static FileDescriptor socket(ProtocolFamily family, boolean stream)
+        throws IOException {
         boolean preferIPv6 = isIPv6Available() &&
             (family != StandardProtocolFamily.INET);
         return IOUtil.newFD(socket0(preferIPv6, stream, false));