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: https://github.com/nodejs/node/pull/12601 Refs: https://github.com/nodejs/node/issues/12708 PR-URL: https://github.com/libuv/libuv/pull/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>
This commit is contained in:
parent
239ab6b012
commit
66319cf494
@ -49,16 +49,20 @@ API
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
If a path on Unix exceeds ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes, ``uv_pipe_bind`` will fail with ``UV_ENAMETOOLONG``.
|
||||
|
||||
.. versionchanged: 2.0.0 long filenames will lead to an error rather than being truncated
|
||||
|
||||
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the named pipe.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
If a path on Unix exceeds ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes, ``uv_pipe_bind`` will fail with ``UV_ENAMETOOLONG``.
|
||||
|
||||
.. versionchanged: 2.0.0 long filenames will lead to an error rather than being truncated
|
||||
|
||||
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
|
||||
|
||||
@ -45,9 +45,14 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
||||
const char* pipe_fname;
|
||||
int sockfd;
|
||||
int err;
|
||||
size_t name_len;
|
||||
|
||||
pipe_fname = NULL;
|
||||
sockfd = -1;
|
||||
name_len = strlen(name);
|
||||
|
||||
if (name_len > sizeof(saddr.sun_path) - 1)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
/* Already bound? */
|
||||
if (uv__stream_fd(handle) >= 0)
|
||||
@ -67,8 +72,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
||||
sockfd = err;
|
||||
|
||||
memset(&saddr, 0, sizeof saddr);
|
||||
strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1);
|
||||
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
|
||||
memcpy(saddr.sun_path, pipe_fname, name_len);
|
||||
saddr.sun_family = AF_UNIX;
|
||||
|
||||
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
|
||||
@ -160,6 +164,14 @@ void uv_pipe_connect(uv_connect_t* req,
|
||||
int new_sock;
|
||||
int err;
|
||||
int r;
|
||||
size_t name_len;
|
||||
|
||||
name_len = strlen(name);
|
||||
|
||||
if (name_len > sizeof(saddr.sun_path) - 1) {
|
||||
err = -ENAMETOOLONG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_sock = (uv__stream_fd(handle) == -1);
|
||||
|
||||
@ -171,8 +183,7 @@ void uv_pipe_connect(uv_connect_t* req,
|
||||
}
|
||||
|
||||
memset(&saddr, 0, sizeof saddr);
|
||||
strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1);
|
||||
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
|
||||
memcpy(saddr.sun_path, name, name_len);
|
||||
saddr.sun_family = AF_UNIX;
|
||||
|
||||
do {
|
||||
|
||||
@ -135,10 +135,16 @@ TEST_DECLARE (udp_try_send)
|
||||
TEST_DECLARE (pipe_bind_error_addrinuse)
|
||||
TEST_DECLARE (pipe_bind_error_addrnotavail)
|
||||
TEST_DECLARE (pipe_bind_error_inval)
|
||||
#ifndef _WIN32
|
||||
TEST_DECLARE (pipe_bind_error_long_path)
|
||||
#endif
|
||||
TEST_DECLARE (pipe_connect_multiple)
|
||||
TEST_DECLARE (pipe_listen_without_bind)
|
||||
TEST_DECLARE (pipe_connect_bad_name)
|
||||
TEST_DECLARE (pipe_connect_to_file)
|
||||
#ifndef _WIN32
|
||||
TEST_DECLARE (pipe_connect_to_long_path)
|
||||
#endif
|
||||
TEST_DECLARE (pipe_connect_on_prepare)
|
||||
TEST_DECLARE (pipe_getsockname)
|
||||
TEST_DECLARE (pipe_getsockname_abstract)
|
||||
@ -401,6 +407,9 @@ TASK_LIST_START
|
||||
|
||||
TEST_ENTRY (pipe_connect_bad_name)
|
||||
TEST_ENTRY (pipe_connect_to_file)
|
||||
#ifndef _WIN32
|
||||
TEST_ENTRY (pipe_connect_to_long_path)
|
||||
#endif
|
||||
TEST_ENTRY (pipe_connect_on_prepare)
|
||||
|
||||
TEST_ENTRY (pipe_server_close)
|
||||
@ -526,6 +535,9 @@ TASK_LIST_START
|
||||
TEST_ENTRY (pipe_bind_error_addrinuse)
|
||||
TEST_ENTRY (pipe_bind_error_addrnotavail)
|
||||
TEST_ENTRY (pipe_bind_error_inval)
|
||||
#ifndef _WIN32
|
||||
TEST_ENTRY (pipe_bind_error_long_path)
|
||||
#endif
|
||||
TEST_ENTRY (pipe_connect_multiple)
|
||||
TEST_ENTRY (pipe_listen_without_bind)
|
||||
TEST_ENTRY (pipe_getsockname)
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -134,3 +135,27 @@ TEST_IMPL(pipe_listen_without_bind) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_bind_error_long_path) {
|
||||
char path[2048];
|
||||
uv_pipe_t server;
|
||||
int r;
|
||||
|
||||
memset(path, '.', sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&server, path);
|
||||
ASSERT(r == UV_ENAMETOOLONG);
|
||||
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -56,6 +57,13 @@ static void connect_cb_file(uv_connect_t* connect_req, int status) {
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb_long_path(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == UV_ENAMETOOLONG);
|
||||
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_bad_name) {
|
||||
uv_pipe_t client;
|
||||
uv_connect_t req;
|
||||
@ -93,3 +101,26 @@ TEST_IMPL(pipe_connect_to_file) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_to_long_path) {
|
||||
char path[2048];
|
||||
uv_pipe_t client;
|
||||
uv_connect_t req;
|
||||
int r;
|
||||
|
||||
memset(path, '.', sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&req, &client, path, connect_cb_long_path);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user