Skip to content

Commit 050f0f7

Browse files
committed
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. Ref: nodejs/node#12601 Ref: nodejs/node#12708
1 parent adedc27 commit 050f0f7

File tree

4 files changed

+75
-4
lines changed

4 files changed

+75
-4
lines changed

src/unix/pipe.c

+15-4
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) + 1;
53+
54+
if (name_len > sizeof(saddr.sun_path))
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) + 1;
170+
171+
if (name_len > sizeof(saddr.sun_path)) {
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

+4
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,12 @@ 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+
TEST_DECLARE (pipe_bind_error_long_path)
138139
TEST_DECLARE (pipe_connect_multiple)
139140
TEST_DECLARE (pipe_listen_without_bind)
140141
TEST_DECLARE (pipe_connect_bad_name)
141142
TEST_DECLARE (pipe_connect_to_file)
143+
TEST_DECLARE (pipe_connect_to_long_path)
142144
TEST_DECLARE (pipe_connect_on_prepare)
143145
TEST_DECLARE (pipe_getsockname)
144146
TEST_DECLARE (pipe_getsockname_abstract)
@@ -398,6 +400,7 @@ TASK_LIST_START
398400

399401
TEST_ENTRY (pipe_connect_bad_name)
400402
TEST_ENTRY (pipe_connect_to_file)
403+
TEST_ENTRY (pipe_connect_to_long_path)
401404
TEST_ENTRY (pipe_connect_on_prepare)
402405

403406
TEST_ENTRY (pipe_server_close)
@@ -523,6 +526,7 @@ TASK_LIST_START
523526
TEST_ENTRY (pipe_bind_error_addrinuse)
524527
TEST_ENTRY (pipe_bind_error_addrnotavail)
525528
TEST_ENTRY (pipe_bind_error_inval)
529+
TEST_ENTRY (pipe_bind_error_long_path)
526530
TEST_ENTRY (pipe_connect_multiple)
527531
TEST_ENTRY (pipe_listen_without_bind)
528532
TEST_ENTRY (pipe_getsockname)

test/test-pipe-bind-error.c

+25
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[256];
142+
uv_pipe_t server;
143+
int r;
144+
145+
memset(path, '.', 255);
146+
path[255] = '\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

+31
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[256];
108+
uv_pipe_t client;
109+
uv_connect_t req;
110+
int r;
111+
112+
memset(path, '.', 255);
113+
path[255] = '\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)