unixdomainchannels: fix some sockaddr_un address handling unixdomainchannels
authormichaelm
Thu, 14 Nov 2019 15:01:49 +0000
branchunixdomainchannels
changeset 59082 5e250ee9259e
parent 59079 7893d1012580
child 59090 fb91b01624be
unixdomainchannels: fix some sockaddr_un address handling
src/java.base/share/native/libnet/net_util.h
src/java.base/unix/native/libnio/ch/InheritedChannel.c
src/java.base/unix/native/libnio/ch/Net.c
src/java.base/windows/native/libnio/ch/Net.c
test/jdk/java/nio/channels/unixdomain/Bind.java
--- a/src/java.base/share/native/libnet/net_util.h	Thu Nov 14 12:40:13 2019 +0000
+++ b/src/java.base/share/native/libnet/net_util.h	Thu Nov 14 15:01:49 2019 +0000
@@ -166,7 +166,7 @@
 NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
 
 JNIEXPORT jobject JNICALL
-NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa);
+NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa, socklen_t len);
 
 JNIEXPORT jint JNICALL
 NET_UnixSocketAddressToSockaddr(JNIEnv *env, jobject uaddr, struct sockaddr_un *sa, int *len);
--- a/src/java.base/unix/native/libnio/ch/InheritedChannel.c	Thu Nov 14 12:40:13 2019 +0000
+++ b/src/java.base/unix/native/libnio/ch/InheritedChannel.c	Thu Nov 14 15:01:49 2019 +0000
@@ -77,7 +77,7 @@
 
     if (getpeername(fd, (struct sockaddr *)&sa, &len) == 0) {
         if (sa.sun_family == AF_UNIX) {
-            remote_sa = NET_SockaddrToUnixAddress(env, &sa);
+            remote_sa = NET_SockaddrToUnixAddress(env, &sa, len);
         }
     }
     return remote_sa;
--- a/src/java.base/unix/native/libnio/ch/Net.c	Thu Nov 14 12:40:13 2019 +0000
+++ b/src/java.base/unix/native/libnio/ch/Net.c	Thu Nov 14 15:01:49 2019 +0000
@@ -51,12 +51,19 @@
 extern jmethodID udsa_ctorID;
 extern jfieldID udsa_pathID;
 
+#define PATHLEN(len) (len - offsetof(struct sockaddr_un, sun_path))
+
 JNIEXPORT jobject JNICALL
-NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa) {
+NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa, socklen_t len) {
 
     if (sa->sun_family == AF_UNIX) {
-        char *name = sa->sun_path;
+        char *name;
 
+        if (PATHLEN(len) == 0) {
+            name = "";
+        } else {
+            name = sa->sun_path;
+        }
         jstring nstr = JNU_NewStringPlatform(env, name);
         return (*env)->NewObject(env, udsa_class, udsa_ctorID, nstr);
     }
@@ -110,8 +117,8 @@
     int sa_len = 0;
     int rv = 0;
 
-    if (uaddr == NULL) 
-	return; /* Rely on implicit bind */
+    if (uaddr == NULL)
+        return; /* Rely on implicit bind */
 
     if (NET_UnixSocketAddressToSockaddr(env, uaddr, &sa, &sa_len) != 0)
         return;
@@ -180,7 +187,7 @@
 
     setfdval(env, newfdo, newfd);
 
-    usa = NET_SockaddrToUnixAddress(env, &sa);
+    usa = NET_SockaddrToUnixAddress(env, &sa, sa_len);
     CHECK_NULL_RETURN(usa, IOS_THROWN);
 
     (*env)->SetObjectArrayElement(env, usaa, 0, usa);
@@ -198,7 +205,7 @@
         handleSocketError(env, errno);
         return NULL;
     }
-    return NET_SockaddrToUnixAddress(env, &sa);
+    return NET_SockaddrToUnixAddress(env, &sa, sa_len);
 }
 
 /**
--- a/src/java.base/windows/native/libnio/ch/Net.c	Thu Nov 14 12:40:13 2019 +0000
+++ b/src/java.base/windows/native/libnio/ch/Net.c	Thu Nov 14 15:01:49 2019 +0000
@@ -90,12 +90,19 @@
 extern jmethodID udsa_ctorID;
 extern jfieldID udsa_pathID;
 
+#define PATHLEN(len) (len - offsetof(struct sockaddr_un, sun_path))
+
 JNIEXPORT jobject JNICALL
-NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa) {
+NET_SockaddrToUnixAddress(JNIEnv *env, struct sockaddr_un *sa, socklen_t len) {
 
     if (sa->sun_family == AF_UNIX) {
-        char *name = sa->sun_path;
+        char *name;
 
+        if (PATHLEN(len) == 0) {
+            name = "";
+        } else {
+            name = sa->sun_path;
+        }
         jstring nstr = JNU_NewStringPlatform(env, name);
         return (*env)->NewObject(env, udsa_class, udsa_ctorID, nstr);
     }
@@ -222,7 +229,7 @@
 
     setfdval(env, newfdo, newfd);
 
-    usa = NET_SockaddrToUnixAddress(env, &sa);
+    usa = NET_SockaddrToUnixAddress(env, &sa, sa_len);
     CHECK_NULL_RETURN(usa, IOS_THROWN);
 
     (*env)->SetObjectArrayElement(env, usaa, 0, usa);
@@ -239,7 +246,7 @@
         handleSocketError(env, errno);
         return NULL;
     }
-    return NET_SockaddrToUnixAddress(env, &sa);
+    return NET_SockaddrToUnixAddress(env, &sa, sa_len);
 }
 
 JNIEXPORT void JNICALL
--- a/test/jdk/java/nio/channels/unixdomain/Bind.java	Thu Nov 14 12:40:13 2019 +0000
+++ b/test/jdk/java/nio/channels/unixdomain/Bind.java	Thu Nov 14 15:01:49 2019 +0000
@@ -53,100 +53,93 @@
             System.out.println("Unix domain channels not supported");
             return;
         }
-	spath = Path.of("server.sock");
-	cpath = Path.of("client.sock");
-	sAddr = new UnixDomainSocketAddress(spath);
-	cAddr = new UnixDomainSocketAddress(cpath);
-	nullAddr = new UnixDomainSocketAddress("");
+        spath = Path.of("server.sock");
+        cpath = Path.of("client.sock");
+        sAddr = new UnixDomainSocketAddress(spath);
+        cAddr = new UnixDomainSocketAddress(cpath);
+        nullAddr = new UnixDomainSocketAddress("");
         runTests();
     }
 
     static boolean supported() {
-	try {
-	    SocketChannel.open(StandardProtocolFamily.UNIX);
-	} catch (UnsupportedAddressTypeException e) {
-	    return false;
-	} catch (Exception e) {
-	    return true; // continue test to see what problem is
-	}
-	return true;
+        try {
+            SocketChannel.open(StandardProtocolFamily.UNIX);
+        } catch (UnsupportedAddressTypeException e) {
+            return false;
+        } catch (Exception e) {
+            return true; // continue test to see what problem is
+        }
+        return true;
     }
 
     static interface ThrowingRunnable {
-	public void run() throws Exception;
+        public void run() throws Exception;
     }
 
     static void init() throws IOException {
-	Files.deleteIfExists(cpath);
-	Files.deleteIfExists(spath);
-	client = null; server = null; accept1 = null;
+        Files.deleteIfExists(cpath);
+        Files.deleteIfExists(spath);
+        client = null; server = null; accept1 = null;
     }
-	
+
     static void checkNormal(ThrowingRunnable r) {
-	try {
-	    init();
-	    r.run();
-	    System.out.println("PASS:");
-	} catch (Exception e) {
-	    throw new RuntimeException(e);
-	} finally {
-	    cleanup();
-	}
+        try {
+            init();
+            r.run();
+            System.out.println("PASS:");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            cleanup();
+        }
     }
 
     static void checkException(Class<? extends Exception> expected, ThrowingRunnable r) {
-	try {
-	    init();
-	    r.run();
-	    throw new RuntimeException("Exception expected");
-	} catch (Exception e) {
-	    if (!expected.isAssignableFrom(e.getClass())) {
-		String msg = "Expected: " + expected + " Got: " + e.getClass();
-	    	throw new RuntimeException(msg);
-	    }
-	    System.out.println("PASS: Got " + e);
-	} finally {
-	    cleanup();
-	}
+        try {
+            init();
+            r.run();
+            throw new RuntimeException("Exception expected");
+        } catch (Exception e) {
+            if (!expected.isAssignableFrom(e.getClass())) {
+                String msg = "Expected: " + expected + " Got: " + e.getClass();
+                throw new RuntimeException(msg);
+            }
+            System.out.println("PASS: Got " + e);
+        } finally {
+            cleanup();
+        }
     }
 
     static void cleanup() {
-	try {
-	    if (server != null)
-		server.close();
-	    if (client != null)
-		client.close();
-	    if (accept1 != null)
-		accept1.close();
-	} catch (IOException e) {}
+        try {
+            if (server != null)
+                server.close();
+            if (client != null)
+                client.close();
+            if (accept1 != null)
+                accept1.close();
+        } catch (IOException e) {}
     }
 
     static void assertClientAddress(SocketAddress a) {
-	assertAddress(a, cAddr, "client");
+        assertAddress(a, cAddr, "client");
     }
 
     static void assertServerAddress(SocketAddress a) {
-	assertAddress(a, sAddr, "server");
+        assertAddress(a, sAddr, "server");
     }
 
     static void assertAddress(SocketAddress a, UnixDomainSocketAddress a1, String s) {
-	if (!(a instanceof UnixDomainSocketAddress))
-	    throw new RuntimeException("wrong address type");
-	UnixDomainSocketAddress ua = (UnixDomainSocketAddress)a;
-	if (!a.equals(a1))
-	    throw new RuntimeException("this is not the " + s + " address");
+        if (!(a instanceof UnixDomainSocketAddress)) {
+            System.err.println("adddr = " + a);
+            throw new RuntimeException("wrong address type");
+        }
+        UnixDomainSocketAddress ua = (UnixDomainSocketAddress)a;
+        if (!a.equals(a1))
+            throw new RuntimeException("this is not the " + s + " address");
     }
 
     public static void runTests() throws IOException {
-	checkNormal(() -> {
-	    client = SocketChannel.open(StandardProtocolFamily.UNIX);
-	    client.bind(cAddr);
-	});
-	checkNormal(() -> {
-	    server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
-	    server.bind(sAddr);
-	});
-	// Repeat first two to make sure they are repeatable
         checkNormal(() -> {
             client = SocketChannel.open(StandardProtocolFamily.UNIX);
             client.bind(cAddr);
@@ -155,45 +148,55 @@
             server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
             server.bind(sAddr);
         });
-	// client bind to null: allowed
-	checkNormal(() -> {
-	    client = SocketChannel.open(StandardProtocolFamily.UNIX);
-	    client.bind(null);
-	    assertAddress(client.getLocalAddress(), nullAddr, "null address");
-	});
-	// server bind to null: not allowed
-	checkException(
-	    BindException.class, () -> {
-	        server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
-	        server.bind(null);
-	    }
-	);
-	// server no bind : not allowed
-	checkException(
-	    NotYetBoundException.class, () -> {
-	        server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
-		server.accept();
-	    }
-	);
-	// client implicit bind and connect
-	checkNormal(() -> {
+        // Repeat first two to make sure they are repeatable
+        checkNormal(() -> {
+            client = SocketChannel.open(StandardProtocolFamily.UNIX);
+            client.bind(cAddr);
+        });
+        checkNormal(() -> {
+            server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
+            server.bind(sAddr);
+        });
+        // client bind to null: allowed
+        checkNormal(() -> {
+            client = SocketChannel.open(StandardProtocolFamily.UNIX);
+            client.bind(null);
+            SocketAddress a = client.getLocalAddress();
+            assertAddress(client.getLocalAddress(), nullAddr, "null address");
+        });
+        // server bind to null: not allowed
+        checkException(
+            BindException.class, () -> {
+                server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
+                server.bind(null);
+            }
+        );
+        // server no bind : not allowed
+        checkException(
+            NotYetBoundException.class, () -> {
+                server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
+                server.accept();
+            }
+        );
+        // client implicit bind and connect
+        checkNormal(() -> {
             server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
             client = SocketChannel.open(StandardProtocolFamily.UNIX);
             server.bind(sAddr);
-	    client.connect(sAddr);
-	    assertAddress(client.getLocalAddress(), nullAddr, "null address");
-	    assertServerAddress(server.getLocalAddress());
-	});
-	// client null bind and connect (check all addresses)
-	checkNormal(() -> {
+            client.connect(sAddr);
+            assertAddress(client.getLocalAddress(), nullAddr, "null address");
+            assertServerAddress(server.getLocalAddress());
+        });
+        // client null bind and connect (check all addresses)
+        checkNormal(() -> {
             server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
             client = SocketChannel.open(StandardProtocolFamily.UNIX);
             server.bind(sAddr);
-	    client.bind(null);
-	    client.connect(sAddr);
-	    assertAddress(client.getLocalAddress(), nullAddr, "null address");
-	    assertServerAddress(server.getLocalAddress());
-	});
+            client.bind(null);
+            client.connect(sAddr);
+            assertAddress(client.getLocalAddress(), nullAddr, "null address");
+            assertServerAddress(server.getLocalAddress());
+        });
         // client explicit bind and connect (check all addresses)
         checkNormal(() -> {
             server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
@@ -201,12 +204,12 @@
             server.bind(sAddr);
             client.bind(cAddr);
             client.connect(sAddr);
-	    accept1 = server.accept();
+            accept1 = server.accept();
             assertClientAddress(client.getLocalAddress());
             assertServerAddress(server.getLocalAddress());
-	    assertAddress(client.getRemoteAddress(), sAddr, "client's remote server address");
-	    assertAddress(accept1.getLocalAddress(), sAddr, "accepted local address (server)");
-	    assertAddress(accept1.getRemoteAddress(), cAddr, "accepted remote address (client)");
+            assertAddress(client.getRemoteAddress(), sAddr, "client's remote server address");
+            assertAddress(accept1.getLocalAddress(), sAddr, "accepted local address (server)");
+            assertAddress(accept1.getRemoteAddress(), cAddr, "accepted remote address (client)");
         });
         // server multiple bind : not allowed
         checkException(