Skip to content

Commit 66319cf

Browse files
addaleaxsantigimeno
authored andcommitted
unix: fail with ENAMETOOLONG in uv_pipe_*
Fail with ENAMETOOLONG when the name of a Unix socket exceeds `sizeof(saddr.sun_path)`. Previously the path was just truncated, which could result in nasty bugs, and even though that behaviour has been always been around, it’s hard to imagine a situation in which ending up with an incorrect path is better than not creating a socket at all. Refs: nodejs/node#12601 Refs: nodejs/node#12708 PR-URL: #1329 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
1 parent 239ab6b commit 66319cf

5 files changed

Lines changed: 91 additions & 8 deletions

File tree

docs/src/pipe.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,20 @@ API
4949
Bind the pipe to a file path (Unix) or a name (Windows).
5050
5151
.. note::
52-
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
53-
92 and 108 bytes.
52+
If a path on Unix exceeds ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
53+
92 and 108 bytes, ``uv_pipe_bind`` will fail with ``UV_ENAMETOOLONG``.
54+
55+
.. versionchanged: 2.0.0 long filenames will lead to an error rather than being truncated
5456
5557
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
5658
5759
Connect to the Unix domain socket or the named pipe.
5860
5961
.. note::
60-
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
61-
92 and 108 bytes.
62+
If a path on Unix exceeds ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
63+
92 and 108 bytes, ``uv_pipe_bind`` will fail with ``UV_ENAMETOOLONG``.
64+
65+
.. versionchanged: 2.0.0 long filenames will lead to an error rather than being truncated
6266
6367
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
6468

src/unix/pipe.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,14 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
4545
const char* pipe_fname;
4646
int sockfd;
4747
int err;
48+
size_t name_len;
4849

4950
pipe_fname = NULL;
5051
sockfd = -1;
52+
name_len = strlen(name);
53+
54+
if (name_len > sizeof(saddr.sun_path) - 1)
55+
return -ENAMETOOLONG;
5156

5257
/* Already bound? */
5358
if (uv__stream_fd(handle) >= 0)
@@ -67,8 +72,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
6772
sockfd = err;
6873

6974
memset(&saddr, 0, sizeof saddr);
70-
strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1);
71-
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
75+
memcpy(saddr.sun_path, pipe_fname, name_len);
7276
saddr.sun_family = AF_UNIX;
7377

7478
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
@@ -160,6 +164,14 @@ void uv_pipe_connect(uv_connect_t* req,
160164
int new_sock;
161165
int err;
162166
int r;
167+
size_t name_len;
168+
169+
name_len = strlen(name);
170+
171+
if (name_len > sizeof(saddr.sun_path) - 1) {
172+
err = -ENAMETOOLONG;
173+
goto out;
174+
}
163175

164176
new_sock = (uv__stream_fd(handle) == -1);
165177

@@ -171,8 +183,7 @@ void uv_pipe_connect(uv_connect_t* req,
171183
}
172184

173185
memset(&saddr, 0, sizeof saddr);
174-
strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1);
175-
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
186+
memcpy(saddr.sun_path, name, name_len);
176187
saddr.sun_family = AF_UNIX;
177188

178189
do {

test/test-list.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,16 @@ TEST_DECLARE (udp_try_send)
135135
TEST_DECLARE (pipe_bind_error_addrinuse)
136136
TEST_DECLARE (pipe_bind_error_addrnotavail)
137137
TEST_DECLARE (pipe_bind_error_inval)
138+
#ifndef _WIN32
139+
TEST_DECLARE (pipe_bind_error_long_path)
140+
#endif
138141
TEST_DECLARE (pipe_connect_multiple)
139142
TEST_DECLARE (pipe_listen_without_bind)
140143
TEST_DECLARE (pipe_connect_bad_name)
141144
TEST_DECLARE (pipe_connect_to_file)
145+
#ifndef _WIN32
146+
TEST_DECLARE (pipe_connect_to_long_path)
147+
#endif
142148
TEST_DECLARE (pipe_connect_on_prepare)
143149
TEST_DECLARE (pipe_getsockname)
144150
TEST_DECLARE (pipe_getsockname_abstract)
@@ -401,6 +407,9 @@ TASK_LIST_START
401407

402408
TEST_ENTRY (pipe_connect_bad_name)
403409
TEST_ENTRY (pipe_connect_to_file)
410+
#ifndef _WIN32
411+
TEST_ENTRY (pipe_connect_to_long_path)
412+
#endif
404413
TEST_ENTRY (pipe_connect_on_prepare)
405414

406415
TEST_ENTRY (pipe_server_close)
@@ -526,6 +535,9 @@ TASK_LIST_START
526535
TEST_ENTRY (pipe_bind_error_addrinuse)
527536
TEST_ENTRY (pipe_bind_error_addrnotavail)
528537
TEST_ENTRY (pipe_bind_error_inval)
538+
#ifndef _WIN32
539+
TEST_ENTRY (pipe_bind_error_long_path)
540+
#endif
529541
TEST_ENTRY (pipe_connect_multiple)
530542
TEST_ENTRY (pipe_listen_without_bind)
531543
TEST_ENTRY (pipe_getsockname)

test/test-pipe-bind-error.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "task.h"
2424
#include <stdio.h>
2525
#include <stdlib.h>
26+
#include <string.h>
2627

2728

2829
#ifdef _WIN32
@@ -134,3 +135,27 @@ TEST_IMPL(pipe_listen_without_bind) {
134135
MAKE_VALGRIND_HAPPY();
135136
return 0;
136137
}
138+
139+
140+
TEST_IMPL(pipe_bind_error_long_path) {
141+
char path[2048];
142+
uv_pipe_t server;
143+
int r;
144+
145+
memset(path, '.', sizeof(path) - 1);
146+
path[sizeof(path) - 1] = '\0';
147+
148+
r = uv_pipe_init(uv_default_loop(), &server, 0);
149+
ASSERT(r == 0);
150+
r = uv_pipe_bind(&server, path);
151+
ASSERT(r == UV_ENAMETOOLONG);
152+
153+
uv_close((uv_handle_t*)&server, close_cb);
154+
155+
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
156+
157+
ASSERT(close_cb_called == 1);
158+
159+
MAKE_VALGRIND_HAPPY();
160+
return 0;
161+
}

test/test-pipe-connect-error.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "task.h"
2424
#include <stdio.h>
2525
#include <stdlib.h>
26+
#include <string.h>
2627

2728

2829
#ifdef _WIN32
@@ -56,6 +57,13 @@ static void connect_cb_file(uv_connect_t* connect_req, int status) {
5657
}
5758

5859

60+
static void connect_cb_long_path(uv_connect_t* connect_req, int status) {
61+
ASSERT(status == UV_ENAMETOOLONG);
62+
uv_close((uv_handle_t*)connect_req->handle, close_cb);
63+
connect_cb_called++;
64+
}
65+
66+
5967
TEST_IMPL(pipe_connect_bad_name) {
6068
uv_pipe_t client;
6169
uv_connect_t req;
@@ -93,3 +101,26 @@ TEST_IMPL(pipe_connect_to_file) {
93101
MAKE_VALGRIND_HAPPY();
94102
return 0;
95103
}
104+
105+
106+
TEST_IMPL(pipe_connect_to_long_path) {
107+
char path[2048];
108+
uv_pipe_t client;
109+
uv_connect_t req;
110+
int r;
111+
112+
memset(path, '.', sizeof(path) - 1);
113+
path[sizeof(path) - 1] = '\0';
114+
115+
r = uv_pipe_init(uv_default_loop(), &client, 0);
116+
ASSERT(r == 0);
117+
uv_pipe_connect(&req, &client, path, connect_cb_long_path);
118+
119+
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
120+
121+
ASSERT(close_cb_called == 1);
122+
ASSERT(connect_cb_called == 1);
123+
124+
MAKE_VALGRIND_HAPPY();
125+
return 0;
126+
}

0 commit comments

Comments
 (0)