Skip to content
Draft
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
7 changes: 0 additions & 7 deletions lib/luadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@

#include "luadata.h"


typedef struct luadata_s {
void *ptr;
size_t size;
uint8_t opt;
} luadata_t;

#define LUADATA_NUMBER_SZ (sizeof(lua_Integer))

static int luadata_lnew(lua_State *L);
Expand Down
7 changes: 7 additions & 0 deletions lib/luadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,12 @@ static inline void luadata_close(lunatik_object_t *object)

#define luadata_attach(L, obj, field, opt) lunatik_attach(L, obj, field, luadata_new, opt)

typedef struct luadata_s {
void *ptr;
size_t size;
uint8_t opt;
} luadata_t;


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line ?

#endif

212 changes: 64 additions & 148 deletions lib/luasocket.c

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions lunatik.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kref.h>
#include <linux/version.h>

Expand Down Expand Up @@ -194,7 +195,7 @@ static inline lunatik_object_t *lunatik_checkruntime(lua_State *L, lunatik_opt_t
#define lunatik_setruntime(L, libname, priv) ((priv)->runtime = lunatik_checkruntime((L), lua##libname##_class.opt))
#define lunatik_monitormt(class, monitor) ((monitor) ? (void *)&(class)->opt : (void *)(class))

static inline void lunatik_checkclass(lua_State *L, const lunatik_class_t *class)
static inline void lunatik_checkcontext(lua_State *L, const lunatik_class_t *class)
{
if (lunatik_cannotsleep(L, !lunatik_issoftirq(class->opt)))
luaL_error(L, "'%s': %s", class->name, LUNATIK_ERR_CONTEXT);
Expand Down Expand Up @@ -299,6 +300,15 @@ static inline lunatik_object_t **lunatik_checkpobject(lua_State *L, int ix)
return pobject;
}

static inline lunatik_object_t *lunatik_checkclass(lua_State *L, int ix,
const char *name, lunatik_opt_t opt)
{
lunatik_object_t *object = lunatik_checkobject(L, ix);
luaL_argcheck(L, strcmp(object->class->name, name) == 0, ix, name);
luaL_argcheck(L, !opt || (object->opt & opt) == opt, ix, name);
return object;
}

static inline void lunatik_newnamespaces(lua_State *L, const lunatik_namespace_t *namespaces)
{
for (; namespaces->name; namespaces++) {
Expand All @@ -320,7 +330,7 @@ int luaopen_##libname(lua_State *L) \
const lunatik_namespace_t *nss = namespaces; /* avoid -Waddress */ \
luaL_newlib(L, funcs); \
if (cls) { \
lunatik_checkclass(L, cls); \
lunatik_checkcontext(L, cls); \
if (lunatik_ismonitor(cls->opt)) \
lunatik_newclass(L, cls, true); \
lunatik_newclass(L, cls, false); \
Expand Down
4 changes: 2 additions & 2 deletions lunatik_obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ lunatik_object_t *lunatik_newobject(lua_State *L, const lunatik_class_t *class,
lunatik_object_t *object = lunatik_checkalloc(L, sizeof(lunatik_object_t));

/* SOFTIRQ runtime requires a SOFTIRQ class */
lunatik_checkclass(L, class);
lunatik_checkcontext(L, class);

lunatik_setobject(object, class, opt);
lunatik_setclass(L, class, lunatik_ismonitor(object->opt));
Expand Down Expand Up @@ -62,7 +62,7 @@ void lunatik_cloneobject(lua_State *L, lunatik_object_t *object)
lunatik_require(L, class->name);
lunatik_object_t **pobject = lunatik_newpobject(L, 1);

lunatik_checkclass(L, class);
lunatik_checkcontext(L, class);
lunatik_setclass(L, class, lunatik_ismonitor(object->opt));
*pobject = object;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/runtime/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ DIR="$(dirname "$(readlink -f "$0")")"
FAILED=0

SEP=""
for t in "$DIR"/refcnt_leak.sh "$DIR"/resume_shared.sh "$DIR"/resume_mailbox.sh "$DIR"/rcu_shared.sh "$DIR"/opt_guards.sh "$DIR"/opt_skb_single.sh; do
for t in "$DIR"/refcnt_leak.sh "$DIR"/resume_shared.sh "$DIR"/resume_mailbox.sh "$DIR"/rcu_shared.sh "$DIR"/opt_guards.sh "$DIR"/opt_skb_single.sh "$DIR"/socket_data.sh "$DIR"/socket_data_reject.sh; do
echo "${SEP}# --- $(basename "$t") ---"
SEP=$'\n'
bash "$t" || FAILED=$((FAILED+1))
Expand Down
43 changes: 43 additions & 0 deletions tests/runtime/socket_data.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--
-- SPDX-FileCopyrightText: (c) 2026 Ring Zero Desenvolvimento de Software LTDA
-- SPDX-License-Identifier: MIT OR GPL-2.0-only
--
-- Kernel-side script for the socket_data regression test (see socket_data.sh).

local socket = require("socket")
local net = require("net")
local data = require("data")

local af = socket.af
local sock = socket.sock
local ip = socket.ipproto
local PORT = 19876
local MSG = "hello socket data!"
local SIZE = #MSG

local s = socket.new(af.INET, sock.DGRAM, ip.UDP)
s:bind(net.aton("127.0.0.1"), PORT)

local sbuf = data.new(SIZE, "single")
sbuf:setstring(0, MSG)
local rbuf = data.new(SIZE, "single")

-- data → data
s:send(sbuf, net.aton("127.0.0.1"), PORT)
local n = s:receive(rbuf)
assert(n == SIZE, "data→data: expected " .. SIZE .. " bytes, got " .. tostring(n))
assert(rbuf:getstring(0, n) == MSG, "data→data: content mismatch")

-- string → data
s:send(MSG, net.aton("127.0.0.1"), PORT)
local n2 = s:receive(rbuf)
assert(n2 == SIZE, "string→data: expected " .. SIZE .. " bytes, got " .. tostring(n2))
assert(rbuf:getstring(0, n2) == MSG, "string→data: content mismatch")

-- data → string
s:send(sbuf, net.aton("127.0.0.1"), PORT)
local str = s:receive(SIZE)
assert(str == MSG, "data→string: content mismatch")

s:close()

37 changes: 37 additions & 0 deletions tests/runtime/socket_data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash
#
# SPDX-FileCopyrightText: (c) 2026 Ring Zero Desenvolvimento de Software LTDA
# SPDX-License-Identifier: MIT OR GPL-2.0-only
#
# Tests socket send/receive with data objects via a UDP loopback socket.
# Verifies valid combinations: data→data, string→data, data→string.
#
# Usage: sudo bash tests/runtime/socket_data.sh

SCRIPT="tests/runtime/socket_data"
MODULE="luasocket"

source "$(dirname "$(readlink -f "$0")")/../lib.sh"

cleanup() { lunatik stop "$SCRIPT" 2>/dev/null; }
trap cleanup EXIT
cleanup

ktap_header
ktap_plan 1

cat /sys/module/$MODULE/refcnt > /dev/null 2>&1 || {
echo "# SKIP: $MODULE not loaded"
ktap_totals
exit 0
}

mark_dmesg

run_script "$SCRIPT"

check_dmesg || { ktap_totals; exit 1; }
ktap_pass "socket send/receive with data objects: data→data, string→data, data→string"

ktap_totals

37 changes: 37 additions & 0 deletions tests/runtime/socket_data_reject.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--
-- SPDX-FileCopyrightText: (c) 2026 Ring Zero Desenvolvimento de Software LTDA
-- SPDX-License-Identifier: MIT OR GPL-2.0-only
--
-- Kernel-side script for the socket_data_reject regression test (see socket_data_reject.sh).

local socket = require("socket")
local net = require("net")
local data = require("data")

local af = socket.af
local sock = socket.sock
local ip = socket.ipproto
local PORT = 19877
local SIZE = 16

local s = socket.new(af.INET, sock.DGRAM, ip.UDP)
s:bind(net.aton("127.0.0.1"), PORT)

-- rejection: wrong-type userdata (socket instead of data)
local ok, err = pcall(function() s:send(s, net.aton("127.0.0.1"), PORT) end)
assert(not ok and err:find("bad argument"), "send: wrong type not rejected: " .. tostring(err))

local ok2, err2 = pcall(function() s:receive(s) end)
assert(not ok2 and err2:find("bad argument"), "receive: wrong type not rejected: " .. tostring(err2))

-- rejection: non-SINGLE (shared) data
local shared = data.new(SIZE, "shared")

local ok3, err3 = pcall(function() s:send(shared, net.aton("127.0.0.1"), PORT) end)
assert(not ok3 and err3:find("bad argument"), "send: non-SINGLE data not rejected: " .. tostring(err3))

local ok4, err4 = pcall(function() s:receive(shared) end)
assert(not ok4 and err4:find("bad argument"), "receive: non-SINGLE data not rejected: " .. tostring(err4))

s:close()

37 changes: 37 additions & 0 deletions tests/runtime/socket_data_reject.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash
#
# SPDX-FileCopyrightText: (c) 2026 Ring Zero Desenvolvimento de Software LTDA
# SPDX-License-Identifier: MIT OR GPL-2.0-only
#
# Verifies that socket send/receive reject wrong-type userdata and non-SINGLE
# data objects with a proper Lua error rather than crashing the kernel.
#
# Usage: sudo bash tests/runtime/socket_data_reject.sh

SCRIPT="tests/runtime/socket_data_reject"
MODULE="luasocket"

source "$(dirname "$(readlink -f "$0")")/../lib.sh"

cleanup() { lunatik stop "$SCRIPT" 2>/dev/null; }
trap cleanup EXIT
cleanup

ktap_header
ktap_plan 1

cat /sys/module/$MODULE/refcnt > /dev/null 2>&1 || {
echo "# SKIP: $MODULE not loaded"
ktap_totals
exit 0
}

mark_dmesg

run_script "$SCRIPT"

check_dmesg || { ktap_totals; exit 1; }
ktap_pass "socket send/receive correctly reject wrong-type and non-SINGLE data"

ktap_totals

Loading