Compare commits

..

2 Commits

Author SHA1 Message Date
Kim Alvefur
b13c4b223b
Merge 81a3d0a8e6e0122f5ef4583a3778cc1883a26e64 into 93eef5015e0dfe8d24071dd036f9a7f02160abeb 2024-04-27 15:43:28 +00:00
Kim Alvefur
81a3d0a8e6 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
2024-04-27 17:37:24 +02:00
2 changed files with 21 additions and 22 deletions

View File

@ -16,6 +16,13 @@
#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
\*=========================================================================*/ \*=========================================================================*/
@ -126,12 +133,13 @@ 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, len = 0; size_t count, sent = 0;
const char *data = luaL_checklstring(L, 2, &count); const char *data = luaL_checklstring(L, 2, &count);
const char *path = luaL_checklstring(L, 3, &len); const char *path = luaL_checkstring(L, 3);
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);
@ -140,7 +148,7 @@ static int meth_sendto(lua_State *L)
} }
memset(&remote, 0, sizeof(remote)); memset(&remote, 0, sizeof(remote));
memcpy(remote.sun_path, path, len); strcpy(remote.sun_path, path);
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
@ -258,20 +266,15 @@ 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));
memcpy(local.sun_path, path, len); strcpy(local.sun_path, path);
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 = sizeof(local.sun_family) + sizeof(local.sun_len) local.sun_len = addrlen + 1;
+ 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);
} }
@ -313,20 +316,16 @@ 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));
memcpy(remote.sun_path, path, len); strcpy(remote.sun_path, path);
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 = sizeof(remote.sun_family) + sizeof(remote.sun_len) remote.sun_len = addrlen + 1;
+ 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));
memcpy(local.sun_path, path, len); strcpy(local.sun_path, path);
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));
memcpy(remote.sun_path, path, len); strcpy(remote.sun_path, path);
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