Compare commits

..

2 Commits

Author SHA1 Message Date
Kim Alvefur
cc6c881ce4
Merge 2c97c5d146f05ad7693fcd6d6472857ae44ae4bf into 93eef5015e0dfe8d24071dd036f9a7f02160abeb 2024-04-27 22:53:56 +02:00
Kim Alvefur
2c97c5d146 fix(unix): Pass correct path length for abstract sockets
Since they start with NUL byte, strlen() does the wrong thing.
The Lua API can already pass the real string length, so passing that on
seems the sensible thing to do.

Fixes #216

Removes SUN_LEN macro in favor of the approach used in unixstream.c
since it does not depend on strlen(), which would not work with
NUL-prefixed abstract stream socket paths.
2024-04-27 22:52:59 +02:00
2 changed files with 22 additions and 21 deletions

View File

@ -16,13 +16,6 @@
#define UNIXDGRAM_DATAGRAMSIZE 8192 #define UNIXDGRAM_DATAGRAMSIZE 8192
/* provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android) */
#ifndef SUN_LEN
#define SUN_LEN(ptr) \
((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path))
#endif
/*=========================================================================*\ /*=========================================================================*\
* Internal function prototypes * Internal function prototypes
\*=========================================================================*/ \*=========================================================================*/
@ -133,13 +126,12 @@ static int meth_send(lua_State *L)
static int meth_sendto(lua_State *L) static int meth_sendto(lua_State *L)
{ {
p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1); p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
size_t count, sent = 0; size_t count, sent, len = 0;
const char *data = luaL_checklstring(L, 2, &count); const char *data = luaL_checklstring(L, 2, &count);
const char *path = luaL_checkstring(L, 3); const char *path = luaL_checklstring(L, 3, &len);
p_timeout tm = &un->tm; p_timeout tm = &un->tm;
int err; int err;
struct sockaddr_un remote; struct sockaddr_un remote;
size_t len = strlen(path);
if (len >= sizeof(remote.sun_path)) { if (len >= sizeof(remote.sun_path)) {
lua_pushnil(L); lua_pushnil(L);
@ -148,7 +140,7 @@ static int meth_sendto(lua_State *L)
} }
memset(&remote, 0, sizeof(remote)); memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path); memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX; remote.sun_family = AF_UNIX;
timeout_markstart(tm); timeout_markstart(tm);
#ifdef UNIX_HAS_SUN_LEN #ifdef UNIX_HAS_SUN_LEN
@ -266,15 +258,20 @@ static int meth_dirty(lua_State *L) {
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static const char *unixdgram_trybind(p_unix un, const char *path, size_t len) { static const char *unixdgram_trybind(p_unix un, const char *path, size_t len) {
struct sockaddr_un local; struct sockaddr_un local;
int err;
if (len >= sizeof(local.sun_path)) return "path too long"; if (len >= sizeof(local.sun_path)) return "path too long";
memset(&local, 0, sizeof(local)); memset(&local, 0, sizeof(local));
strcpy(local.sun_path, path); memcpy(local.sun_path, path, len);
local.sun_family = AF_UNIX; local.sun_family = AF_UNIX;
size_t addrlen = SUN_LEN(&local);
#ifdef UNIX_HAS_SUN_LEN #ifdef UNIX_HAS_SUN_LEN
local.sun_len = addrlen + 1; local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ len + 1;
err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
#else
err = socket_bind(&un->sock, (SA *) &local,
sizeof(local.sun_family) + len);
#endif #endif
int err = socket_bind(&un->sock, (SA *) &local, addrlen);
if (err != IO_DONE) socket_destroy(&un->sock); if (err != IO_DONE) socket_destroy(&un->sock);
return socket_strerror(err); return socket_strerror(err);
} }
@ -316,16 +313,20 @@ static int meth_getsockname(lua_State *L)
static const char *unixdgram_tryconnect(p_unix un, const char *path, size_t len) static const char *unixdgram_tryconnect(p_unix un, const char *path, size_t len)
{ {
struct sockaddr_un remote; struct sockaddr_un remote;
int err;
if (len >= sizeof(remote.sun_path)) return "path too long"; if (len >= sizeof(remote.sun_path)) return "path too long";
memset(&remote, 0, sizeof(remote)); memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path); memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX; remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm); timeout_markstart(&un->tm);
size_t addrlen = SUN_LEN(&remote);
#ifdef UNIX_HAS_SUN_LEN #ifdef UNIX_HAS_SUN_LEN
remote.sun_len = addrlen + 1; remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ len + 1;
err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
#else
err = socket_connect(&un->sock, (SA *) &remote,
sizeof(remote.sun_family) + len, &un->tm);
#endif #endif
int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm);
if (err != IO_DONE) socket_destroy(&un->sock); if (err != IO_DONE) socket_destroy(&un->sock);
return socket_strerror(err); return socket_strerror(err);
} }

View File

@ -186,7 +186,7 @@ static const char *unixstream_trybind(p_unix un, const char *path, size_t len) {
int err; int err;
if (len >= sizeof(local.sun_path)) return "path too long"; if (len >= sizeof(local.sun_path)) return "path too long";
memset(&local, 0, sizeof(local)); memset(&local, 0, sizeof(local));
strcpy(local.sun_path, path); memcpy(local.sun_path, path, len);
local.sun_family = AF_UNIX; local.sun_family = AF_UNIX;
#ifdef UNIX_HAS_SUN_LEN #ifdef UNIX_HAS_SUN_LEN
local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
@ -240,7 +240,7 @@ static const char *unixstream_tryconnect(p_unix un, const char *path, size_t len
int err; int err;
if (len >= sizeof(remote.sun_path)) return "path too long"; if (len >= sizeof(remote.sun_path)) return "path too long";
memset(&remote, 0, sizeof(remote)); memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path); memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX; remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm); timeout_markstart(&un->tm);
#ifdef UNIX_HAS_SUN_LEN #ifdef UNIX_HAS_SUN_LEN