Skip to content

Commit

Permalink
fix(unix): Pass correct path length for abstract sockets
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Zash committed Apr 27, 2024
1 parent 93eef50 commit 00faac8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 38 deletions.
49 changes: 23 additions & 26 deletions src/unixdgram.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@

#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
\*=========================================================================*/
Expand All @@ -42,8 +35,8 @@ static int meth_receivefrom(lua_State *L);
static int meth_sendto(lua_State *L);
static int meth_getsockname(lua_State *L);

static const char *unixdgram_tryconnect(p_unix un, const char *path);
static const char *unixdgram_trybind(p_unix un, const char *path);
static const char *unixdgram_tryconnect(p_unix un, const char *path, size_t len);
static const char *unixdgram_trybind(p_unix un, const char *path, size_t len);

/* unixdgram object methods */
static luaL_Reg unixdgram_methods[] = {
Expand Down Expand Up @@ -133,13 +126,12 @@ static int meth_send(lua_State *L)
static int meth_sendto(lua_State *L)
{
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 *path = luaL_checkstring(L, 3);
const char *path = luaL_checklstring(L, 3, &len);
p_timeout tm = &un->tm;
int err;
struct sockaddr_un remote;
size_t len = strlen(path);

if (len >= sizeof(remote.sun_path)) {
lua_pushnil(L);
Expand All @@ -148,7 +140,7 @@ static int meth_sendto(lua_State *L)
}

memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path);
memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX;
timeout_markstart(tm);
#ifdef UNIX_HAS_SUN_LEN
Expand Down Expand Up @@ -264,27 +256,32 @@ static int meth_dirty(lua_State *L) {
/*-------------------------------------------------------------------------*\
* Binds an object to an address
\*-------------------------------------------------------------------------*/
static const char *unixdgram_trybind(p_unix un, const char *path) {
static const char *unixdgram_trybind(p_unix un, const char *path, size_t len) {
struct sockaddr_un local;
size_t len = strlen(path);
int err;
if (len >= sizeof(local.sun_path)) return "path too long";
memset(&local, 0, sizeof(local));
strcpy(local.sun_path, path);
memcpy(local.sun_path, path, len);
local.sun_family = AF_UNIX;
size_t addrlen = SUN_LEN(&local);
#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
int err = socket_bind(&un->sock, (SA *) &local, addrlen);
if (err != IO_DONE) socket_destroy(&un->sock);
return socket_strerror(err);
}

static int meth_bind(lua_State *L)
{
p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
const char *path = luaL_checkstring(L, 2);
const char *err = unixdgram_trybind(un, path);
size_t len;
const char *path = luaL_checklstring(L, 2, &len);
const char *err = unixdgram_trybind(un, path, len);
if (err) {
lua_pushnil(L);
lua_pushstring(L, err);
Expand Down Expand Up @@ -313,13 +310,12 @@ static int meth_getsockname(lua_State *L)
/*-------------------------------------------------------------------------*\
* Turns a master unixdgram object into a client object.
\*-------------------------------------------------------------------------*/
static const char *unixdgram_tryconnect(p_unix un, const char *path)
static const char *unixdgram_tryconnect(p_unix un, const char *path, size_t len)
{
struct sockaddr_un remote;
size_t len = strlen(path);
if (len >= sizeof(remote.sun_path)) return "path too long";
memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path);
memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm);
size_t addrlen = SUN_LEN(&remote);
Expand All @@ -334,8 +330,9 @@ static const char *unixdgram_tryconnect(p_unix un, const char *path)
static int meth_connect(lua_State *L)
{
p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
const char *path = luaL_checkstring(L, 2);
const char *err = unixdgram_tryconnect(un, path);
size_t len;
const char *path = luaL_checklstring(L, 2, &len);
const char *err = unixdgram_tryconnect(un, path, len);
if (err) {
lua_pushnil(L);
lua_pushstring(L, err);
Expand Down
24 changes: 12 additions & 12 deletions src/unixstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ static int meth_getstats(lua_State *L);
static int meth_setstats(lua_State *L);
static int meth_getsockname(lua_State *L);

static const char *unixstream_tryconnect(p_unix un, const char *path);
static const char *unixstream_trybind(p_unix un, const char *path);
static const char *unixstream_tryconnect(p_unix un, const char *path, size_t len);
static const char *unixstream_trybind(p_unix un, const char *path, size_t len);

/* unixstream object methods */
static luaL_Reg unixstream_methods[] = {
Expand Down Expand Up @@ -181,13 +181,12 @@ static int meth_accept(lua_State *L) {
/*-------------------------------------------------------------------------*\
* Binds an object to an address
\*-------------------------------------------------------------------------*/
static const char *unixstream_trybind(p_unix un, const char *path) {
static const char *unixstream_trybind(p_unix un, const char *path, size_t len) {
struct sockaddr_un local;
size_t len = strlen(path);
int err;
if (len >= sizeof(local.sun_path)) return "path too long";
memset(&local, 0, sizeof(local));
strcpy(local.sun_path, path);
memcpy(local.sun_path, path, len);
local.sun_family = AF_UNIX;
#ifdef UNIX_HAS_SUN_LEN
local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
Expand All @@ -204,8 +203,9 @@ static const char *unixstream_trybind(p_unix un, const char *path) {

static int meth_bind(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
const char *path = luaL_checkstring(L, 2);
const char *err = unixstream_trybind(un, path);
size_t len;
const char *path = luaL_checklstring(L, 2, &len);
const char *err = unixstream_trybind(un, path, len);
if (err) {
lua_pushnil(L);
lua_pushstring(L, err);
Expand Down Expand Up @@ -234,14 +234,13 @@ static int meth_getsockname(lua_State *L)
/*-------------------------------------------------------------------------*\
* Turns a master unixstream object into a client object.
\*-------------------------------------------------------------------------*/
static const char *unixstream_tryconnect(p_unix un, const char *path)
static const char *unixstream_tryconnect(p_unix un, const char *path, size_t len)
{
struct sockaddr_un remote;
int err;
size_t len = strlen(path);
if (len >= sizeof(remote.sun_path)) return "path too long";
memset(&remote, 0, sizeof(remote));
strcpy(remote.sun_path, path);
memcpy(remote.sun_path, path, len);
remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm);
#ifdef UNIX_HAS_SUN_LEN
Expand All @@ -259,8 +258,9 @@ static const char *unixstream_tryconnect(p_unix un, const char *path)
static int meth_connect(lua_State *L)
{
p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
const char *path = luaL_checkstring(L, 2);
const char *err = unixstream_tryconnect(un, path);
size_t len;
const char *path = luaL_checklstring(L, 2, &len);
const char *err = unixstream_tryconnect(un, path, len);
if (err) {
lua_pushnil(L);
lua_pushstring(L, err);
Expand Down

0 comments on commit 00faac8

Please sign in to comment.