Skip to content

Commit caa07bb

Browse files
Fix Socket reading of abstract unix domain addresses (#16010)
Motivation: How we calculated the length of the unix domain socket address was not correct. Motification: Follow the manpage in how the length is calculated Result: Always return the correct name for abstract unix domain sockets --------- Co-authored-by: Chris Vest <[email protected]>
1 parent 640b6b7 commit caa07bb

File tree

2 files changed

+34
-28
lines changed

2 files changed

+34
-28
lines changed

transport-native-epoll/src/test/java/io/netty/channel/epoll/LinuxSocketTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.junit.jupiter.api.Test;
2929
import org.junit.jupiter.api.function.Executable;
3030

31+
import static org.junit.jupiter.api.Assertions.assertEquals;
3132
import static org.junit.jupiter.api.Assertions.assertThrows;
3233

3334
public class LinuxSocketTest {
@@ -94,4 +95,21 @@ public void execute() throws Throwable {
9495
socket.close();
9596
}
9697
}
98+
99+
@Test
100+
public void testUnixAbstractDomainSocket() throws IOException {
101+
String address = "\0" + UUID.randomUUID();
102+
103+
final DomainSocketAddress domainSocketAddress = new DomainSocketAddress(address);
104+
final Socket socket = Socket.newSocketDomain();
105+
try {
106+
socket.bind(domainSocketAddress);
107+
DomainSocketAddress local = socket.localDomainSocketAddress();
108+
assertEquals(domainSocketAddress, local);
109+
assertEquals(address, domainSocketAddress.path());
110+
assertEquals(address, local.path());
111+
} finally {
112+
socket.close();
113+
}
114+
}
97115
}

transport-native-unix-common/src/main/c/netty_unix_socket.c

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -133,23 +133,23 @@ static jobject createDatagramSocketAddress(JNIEnv* env, const struct sockaddr_st
133133
return obj;
134134
}
135135

136-
static jobject createDomainDatagramSocketAddress(JNIEnv* env, const struct sockaddr_storage* addr, int len, jobject local) {
137-
jclass domainDatagramSocketAddressClass = NULL;
138-
jobject obj = NULL;
139-
struct sockaddr_un* s = (struct sockaddr_un*) addr;
136+
static int domainSocketPathLength(const struct sockaddr_un* s, const socklen_t addrlen) {
140137
#ifdef __linux__
141138
// Linux supports abstract domain sockets so we need to handle it.
142139
// https://man7.org/linux/man-pages/man7/unix.7.html
143-
int pathLength = 0;
144-
if (s->sun_path[0] == '\0') {
140+
if (addrlen >= sizeof(sa_family_t) && s->sun_path[0] == '\0') {
145141
// This is an abstract domain socket address
146-
pathLength = strlen(&(s->sun_path[1])) + 1;
147-
} else {
148-
pathLength = strlen(s->sun_path);
142+
return (addrlen - sizeof(sa_family_t));
149143
}
150-
#else
151-
int pathLength = strlen(s->sun_path);
152144
#endif
145+
return strlen(s->sun_path);
146+
}
147+
148+
static jobject createDomainDatagramSocketAddress(JNIEnv* env, const struct sockaddr_storage* addr, const socklen_t addrlen, int len, jobject local) {
149+
jclass domainDatagramSocketAddressClass = NULL;
150+
jobject obj = NULL;
151+
struct sockaddr_un* s = (struct sockaddr_un*) addr;
152+
int pathLength = domainSocketPathLength(s, addrlen);
153153
jbyteArray pathBytes = (*env)->NewByteArray(env, pathLength);
154154
if (pathBytes == NULL) {
155155
return NULL;
@@ -169,21 +169,9 @@ static jobject createDomainDatagramSocketAddress(JNIEnv* env, const struct socka
169169
return obj;
170170
}
171171

172-
static jbyteArray netty_unix_socket_createDomainSocketAddressArray(JNIEnv* env, const struct sockaddr_storage* addr) {
172+
static jbyteArray netty_unix_socket_createDomainSocketAddressArray(JNIEnv* env, const struct sockaddr_storage* addr, const socklen_t addrlen) {
173173
struct sockaddr_un* s = (struct sockaddr_un*) addr;
174-
#ifdef __linux__
175-
// Linux supports abstract domain sockets so we need to handle it.
176-
// https://man7.org/linux/man-pages/man7/unix.7.html
177-
int pathLength = 0;
178-
if (s->sun_path[0] == '\0') {
179-
// This is an abstract domain socket address
180-
pathLength = strlen(&(s->sun_path[1])) + 1;
181-
} else {
182-
pathLength = strlen(s->sun_path);
183-
}
184-
#else
185-
int pathLength = strlen(s->sun_path);
186-
#endif
174+
int pathLength = domainSocketPathLength(s, addrlen);
187175
jbyteArray pathBytes = (*env)->NewByteArray(env, pathLength);
188176
if (pathBytes == NULL) {
189177
return NULL;
@@ -488,7 +476,7 @@ static jobject _recvFromDomainSocket(JNIEnv* env, jint fd, void* buffer, jint po
488476
return NULL;
489477
}
490478

491-
return createDomainDatagramSocketAddress(env, &addr, res, NULL);
479+
return createDomainDatagramSocketAddress(env, &addr, addrlen, res, NULL);
492480
}
493481

494482
static jint _send(JNIEnv* env, jclass clazz, jint fd, void* buffer, jint pos, jint limit) {
@@ -733,7 +721,7 @@ static jbyteArray netty_unix_socket_remoteDomainSocketAddress(JNIEnv* env, jclas
733721
if (getpeername(fd, (struct sockaddr*) &addr, &len) == -1) {
734722
return NULL;
735723
}
736-
return netty_unix_socket_createDomainSocketAddressArray(env, &addr);
724+
return netty_unix_socket_createDomainSocketAddressArray(env, &addr, len);
737725
}
738726

739727
static jbyteArray netty_unix_socket_localAddress(JNIEnv* env, jclass clazz, jint fd) {
@@ -751,7 +739,7 @@ static jbyteArray netty_unix_socket_localDomainSocketAddress(JNIEnv* env, jclass
751739
if (getsockname(fd, (struct sockaddr*) &addr, &len) == -1) {
752740
return NULL;
753741
}
754-
return netty_unix_socket_createDomainSocketAddressArray(env, &addr);
742+
return netty_unix_socket_createDomainSocketAddressArray(env, &addr, len);
755743
}
756744

757745
static jint netty_unix_socket_newSocketDgramFd(JNIEnv* env, jclass clazz, jboolean ipv6) {

0 commit comments

Comments
 (0)