Skip to content

Commit

Permalink
linux: fix bind/connect for abstract sockets (#4266)
Browse files Browse the repository at this point in the history
The `\0` character has no special significance in abstract sockets, so
the addrlen field in both `bind()` and `connect()` should take that into
account.
  • Loading branch information
santigimeno authored Dec 25, 2023
1 parent 8861a97 commit 1dd0ab1
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
17 changes: 13 additions & 4 deletions src/unix/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
char* pipe_fname;
int sockfd;
int err;
socklen_t addrlen;

pipe_fname = NULL;

Expand Down Expand Up @@ -100,12 +101,15 @@ int uv_pipe_bind2(uv_pipe_t* handle,
* We unlink the file later but abstract sockets disappear
* automatically since they're not real file system entities.
*/
if (*name != '\0') {
if (*name == '\0') {
addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
} else {
pipe_fname = uv__malloc(namelen + 1);
if (pipe_fname == NULL)
return UV_ENOMEM;
memcpy(pipe_fname, name, namelen);
pipe_fname[namelen] = '\0';
addrlen = sizeof saddr;
}

err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
Expand All @@ -117,7 +121,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
memcpy(&saddr.sun_path, name, namelen);
saddr.sun_family = AF_UNIX;

if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
if (bind(sockfd, (struct sockaddr*)&saddr, addrlen)) {
err = UV__ERR(errno);
/* Convert ENOENT to EACCES for compatibility with Windows. */
if (err == UV_ENOENT)
Expand Down Expand Up @@ -251,6 +255,7 @@ int uv_pipe_connect2(uv_connect_t* req,
int new_sock;
int err;
int r;
socklen_t addrlen;

if (flags & ~UV_PIPE_NO_TRUNCATE)
return UV_EINVAL;
Expand Down Expand Up @@ -285,9 +290,13 @@ int uv_pipe_connect2(uv_connect_t* req,
memcpy(&saddr.sun_path, name, namelen);
saddr.sun_family = AF_UNIX;

if (*name == '\0')
addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
else
addrlen = sizeof saddr;

do {
r = connect(uv__stream_fd(handle),
(struct sockaddr*)&saddr, sizeof saddr);
r = connect(uv__stream_fd(handle), (struct sockaddr*)&saddr, addrlen);
}
while (r == -1 && errno == EINTR);

Expand Down
7 changes: 4 additions & 3 deletions test/test-pipe-getsockname.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ static void pipe_client_connect_cb(uv_connect_t* req, int status) {

if (*buf == '\0') { /* Linux abstract socket. */
const char expected[] = "\0" TEST_PIPENAME;
ASSERT_GE(len, sizeof(expected));
ASSERT_MEM_EQ(buf, expected, sizeof(expected));
ASSERT_EQ(len, sizeof(expected) - 1);
ASSERT_MEM_EQ(buf, expected, len);
} else {
ASSERT_NE(0, buf[len - 1]);
ASSERT_MEM_EQ(buf, TEST_PIPENAME, len);
Expand Down Expand Up @@ -191,7 +191,8 @@ TEST_IMPL(pipe_getsockname_abstract) {
ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_server, 0));
ASSERT_OK(uv_pipe_bind2(&pipe_server, name, sizeof(name) - 1, 0));
ASSERT_OK(uv_pipe_getsockname(&pipe_server, buf, &buflen));
ASSERT_MEM_EQ(name, buf, sizeof(name));
ASSERT_UINT64_EQ(sizeof(name) - 1, buflen);
ASSERT_MEM_EQ(name, buf, buflen);
ASSERT_OK(uv_listen((uv_stream_t*) &pipe_server,
0,
pipe_server_connection_cb));
Expand Down

0 comments on commit 1dd0ab1

Please sign in to comment.