Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion security/lua/lsm_defs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/syscalls.h> /* for __MAP */
#include <linux/timekeeping.h> /* for ktime_get */
#include <net/ipv6.h>
#include <uapi/linux/un.h>
#include <linux/lsm_hooks.h>
#include <uapi/linux/lsm.h>
#include <linux/lua.h>
Expand Down Expand Up @@ -2662,8 +2663,17 @@ static int build_sockaddr(lua_State *L, struct sockaddr *address, int addrlen)
if (addrlen < SIN6_LEN_RFC2133)
return 0;
break;
case AF_UNIX:
if (addrlen < offsetof(struct sockaddr_un, sun_path))
return 0;
break;
}
{
struct lua_sockaddr *p = newsockaddr(L);

p->addr = address;
p->addrlen = addrlen;
}
*newsockaddr(L) = address;
return 1;
}

Expand Down
45 changes: 41 additions & 4 deletions security/lua/lua_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "debug.h"
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/security.h>
#include <linux/inet.h>
#include <net/inet_sock.h>
Expand Down Expand Up @@ -70,6 +71,30 @@ static const char *family_tostring(sa_family_t sa_family)
return family;
}

static size_t sockaddr_un_path_len(const struct sockaddr_un *sunaddr, int addrlen)
{
int offset = offsetof(struct sockaddr_un, sun_path);
size_t path_len;

if (addrlen <= offset)
return 0;

path_len = addrlen - offset;

/*
* Pathname sockets are C strings; abstract sockets keep their full
* declared length, including embedded NUL bytes.
*/
if (sunaddr->sun_path[0] != '\0') {
const char *nul = memchr(sunaddr->sun_path, '\0', path_len);

if (nul)
path_len = nul - sunaddr->sun_path;
}

return path_len;
}

/*********************************** sock ***********************************/

static int net_sock_socket(lua_State *L)
Expand Down Expand Up @@ -368,11 +393,16 @@ static int sockaddr_addrs(lua_State *L)
}
lua_pushinteger(L, ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
return 3;
case AF_UNIX:
case AF_UNIX: {
struct sockaddr_un *sunaddr = (struct sockaddr_un *)sa;
int addrlen = tosockaddr_addrlen(L, 1);
size_t path_len = sockaddr_un_path_len(sunaddr, addrlen);

lua_pushstring(L, "unix");
lua_pushstring(L, ((struct sockaddr_un *)sa)->sun_path);
lua_pushlstring(L, sunaddr->sun_path, path_len);
return 2;
}
}
return 0;
}

Expand All @@ -391,9 +421,16 @@ static int meth_sockaddr_tostring(lua_State *L)
l = snprintf(buffer, sizeof(buffer), "sa.inet6: %pISpc", sa);
lua_pushlstring(L, buffer, l);
break;
case AF_UNIX:
lua_pushfstring(L, "sa.unix: %s", ((struct sockaddr_un *)sa)->sun_path);
case AF_UNIX: {
struct sockaddr_un *sunaddr = (struct sockaddr_un *)sa;
int addrlen = tosockaddr_addrlen(L, 1);
size_t sp_len = sockaddr_un_path_len(sunaddr, addrlen);

lua_pushliteral(L, "sa.unix: ");
lua_pushlstring(L, sunaddr->sun_path, sp_len);
lua_concat(L, 2);
break;
}
case AF_NETLINK:
lua_pushfstring(L, "sa.netlink: %d", ((struct sockaddr_nl *)sa)->nl_pid);
break;
Expand Down
80 changes: 79 additions & 1 deletion security/lua/lua_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@
LUA_OBJECT(func, net, tundev, void *, NULL) \
LUA_OBJECT(func, net, socket, struct socket *, NULL) \
LUA_OBJECT(func, net, skb, struct sk_buff *, NULL) \
LUA_OBJECT(func, net, sockaddr, struct sockaddr *, NULL) \
LUA_OBJECT(func, security, key, struct key *, NULL) \
LUA_OBJECT(object, block, bdev, struct block_device *, NULL) \
LUA_OBJECT(object, fs, inode, struct inode *, NULL) \
Expand All @@ -157,4 +156,83 @@
LUA_OBJECTS_LIST
#undef LUA_OBJECT

/*
* sockaddr is defined manually because it needs to carry addrlen alongside
* the pointer, so Lua-side methods can derive correct bounds for AF_UNIX
* sun_path (including abstract namespace sockets with embedded NULs).
*
* NOTE: These definitions mirror what LUA_OBJECT_func_DEFINE would generate.
* If that macro is ever extended (e.g. new raw/gc helpers), update this
* section to stay in sync.
*/
struct lua_sockaddr {
struct sockaddr *addr;
int addrlen;
};

static inline struct lua_sockaddr *newsockaddr_nomain(lua_State *L)
{
struct lua_sockaddr *p = lua_newuserdata(L, sizeof(*p));

p->addr = NULL;
p->addrlen = 0;
luaL_getmetatable(L, METHOD_NAME(sockaddr));
lua_setmetatable(L, -2);
return p;
}

static inline struct lua_sockaddr *newsockaddr(lua_State *L)
{
struct lua_sockaddr *p = newsockaddr_nomain(L);

lua_getfield(L, LUA_REGISTRYINDEX, CURR_ENV);
lua_setfenv(L, -2);
return p;
}

static inline struct lua_sockaddr *tosockaddarp(lua_State *L, int idx)
{
return (struct lua_sockaddr *)checkudata3(L, idx, METHOD_NAME(sockaddr));
}

static inline struct sockaddr *tosockaddr(lua_State *L, int idx)
{
return tosockaddarp(L, idx)->addr;
}

static inline int tosockaddr_addrlen(lua_State *L, int idx)
{
return tosockaddarp(L, idx)->addrlen;
}

static int rawmeth_sockaddr_type(lua_State *L)
{
lua_pushstring(L, "sockaddr");
lua_pushboolean(L, 0);
return 2;
}

static int rawmeth_sockaddr_tostring(lua_State *L)
{
struct sockaddr *o = tosockaddr(L, 1);

lua_pushfstring(L, "sockaddr: <%p>", o);
return 1;
}

static inline void create_sockaddr_meta(lua_State *L,
const luaL_Reg *funcs, const luaL_Reg *gc)
{
static const luaL_Reg basemeths[] = {
{ "__tostring", rawmeth_sockaddr_tostring },
{ NULL, NULL }
};
static const luaL_Reg rawmeths[] = {
{ "type", rawmeth_sockaddr_type },
{ NULL, NULL }
};
createmeta3(L, "sockaddr", basemeths, METHOD_NAME_GC(sockaddr), gc,
METHOD_NAME(sockaddr), funcs, METHOD_NAME_RAW(sockaddr), rawmeths);
}

#endif /* ! _SECURITY_LUA_LSM_LUA_OBJECT_H */