<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ubus, branch master</title>
<subtitle>OpenWrt system message/RPC bus</subtitle>
<id>https://git-03.infra.openwrt.org/project/ubus/atom?h=master</id>
<link rel='self' href='https://git-03.infra.openwrt.org/project/ubus/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/'/>
<updated>2026-09-25T07:46:40Z</updated>
<entry>
<title>ubus/lua: store event handler ref without polluting the callback table</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T20:00:41Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=414c60a2e29e72c2c4f573bc50ad54aef076d169'/>
<id>urn:sha1:414c60a2e29e72c2c4f573bc50ad54aef076d169</id>
<content type='text'>
ubus_lua_load_event() registered the listener via luaL_ref() into
__ubus_cb_event and then called

    lua_setfield(L, -1, lua_tostring(L, -3));

At that point index -1 is the __ubus_cb_event table itself and the
value on top of the stack is also that table, so the call assigned
__ubus_cb_event[&lt;event name&gt;] = __ubus_cb_event, a self-reference that
serves no purpose: event dispatch resolves the handler solely through
the integer luaL_ref stored in listener-&gt;r. Drop the bogus assignment
and just pop the table to keep the stack balanced.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>tests/fuzz: use size of blob_attr, not of a pointer, in length guard</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:44:54Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=b27014cf7978cd797d3f7933299b9d295e338178'/>
<id>urn:sha1:b27014cf7978cd797d3f7933299b9d295e338178</id>
<content type='text'>
_ubus_parse_msg() guarded against short input with
sizeof(struct blob_attr *), the size of a pointer, instead of
sizeof(struct blob_attr), the header it is about to dereference. The
two happen to differ (8 vs 4 bytes on LP64), so the harness skipped
valid 4- to 7-byte messages that the real parser accepts. Compare
against the size of the structure itself.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>tests/fuzz: fix out-of-bounds read in header validation harness</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:44:24Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=3930745d8593bb9dffb3d0755affcdefb37585e9'/>
<id>urn:sha1:3930745d8593bb9dffb3d0755affcdefb37585e9</id>
<content type='text'>
_ubus_validate_hdr() passed the input straight to ubus_validate_hdr()
whenever size was not greater than sizeof(struct ubus_msghdr). That
condition is backwards and too small: ubus_validate_hdr() dereferences
the struct blob_attr located immediately after the header, so the
harness needs at least sizeof(ubus_msghdr) + sizeof(blob_attr) bytes.
An 8-byte input (exactly the header size) reached the validator and
read blob_raw_len() one blob_attr past the end of the buffer.

Require the full header plus the trailing blob_attr before validating.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>ubusd: close the forwarded fd when the invoke reply cannot be built</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:26:34Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=eb5a8284d176fd53c8caf1a8fcf4c270c9919176'/>
<id>urn:sha1:eb5a8284d176fd53c8caf1a8fcf4c270c9919176</id>
<content type='text'>
ubusd_handle_invoke() transfers the caller's SCM_RIGHTS fd to the
forwarded message and then clears ub-&gt;fd unconditionally. If
ubus_proto_send_msg_from_blob() fails to allocate the reply buffer it
returned without sending or closing that fd, so it was leaked. Close it
on the allocation-failure path.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>ubus/lua: copy the Lua strings stored in registered objects</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:25:41Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=fdd9ff1fe0fc1e0b0a97b072cce9e593c36b06c5'/>
<id>urn:sha1:fdd9ff1fe0fc1e0b0a97b072cce9e593c36b06c5</id>
<content type='text'>
Object name, type name and policy field names were stored as raw
lua_tostring() pointers into the caller's argument table. Once that table
is garbage-collected (the idiomatic case: the script does not retain it),
the backing strings are freed while the ubus_object/ubus_method
structures still reference them. libubus reads obj-&gt;name and the policy
names again when re-registering every object after a ubusd reconnect, and
obj-&gt;name is read on each incoming invoke (req.acl.object), so the freed
memory is used well after add(). Only method names survived, by accident,
because they double as keys in the persistent callback table. Keep owned
strdup() copies instead.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>ubus/lua: fix Lua stack imbalance on policy allocation failure</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:24:31Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=17525550a36b947dd7899d7adad91ee810e97126'/>
<id>urn:sha1:17525550a36b947dd7899d7adad91ee810e97126</id>
<content type='text'>
ubus_lua_load_methods() leaves the function pointer and policy table it
pushed on the Lua stack when the policy allocation fails, unlike the two
other exit paths which pop both. The caller only pops one value, so each
occurrence permanently unbalances the stack. Pop both before returning.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>libubus: free queued pending messages on shutdown</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:21:59Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=297baef62eeeb5959649f148ead71fe2a9905bcd'/>
<id>urn:sha1:297baef62eeeb5959649f148ead71fe2a9905bcd</id>
<content type='text'>
Messages received while the dispatch stack is non-empty are copied onto
ctx-&gt;pending by ubus_queue_msg() and are only freed as they are drained
by the pending timer. ubus_shutdown() cancelled that timer and freed the
msgbuf without draining the queue, so any messages still queued at
shutdown were leaked. Drain and free the list explicitly.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>libubus: do not restart the ACL query while one is in flight</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:21:05Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=2ec13d49ba376e2723399bad6fe8a558a2f6cfb2'/>
<id>urn:sha1:2ec13d49ba376e2723399bad6fe8a558a2f6cfb2</id>
<content type='text'>
acl_query() reuses a single static ubus_request. Each ubus.acl.sequence
event triggers a fresh query, and ubus_invoke_async() memset()s that
request at the start. If a new sequence event is processed while the
previous query is still linked in ctx-&gt;requests (its DATA reply seen but
the terminating STATUS not yet processed), the memset() zeroes a live
list node and corrupts the request list, which ubus_find_request() then
walks. Track an in-flight flag and defer the refresh until the running
query completes, re-running it afterwards so the newest ACL state is
still fetched.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>ubusd: stop writing to a client already flagged for disconnect</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:20:15Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=cbc27b66d8135a75c81af5f60d309ac4c63b97ee'/>
<id>urn:sha1:cbc27b66d8135a75c81af5f60d309ac4c63b97ee</id>
<content type='text'>
When ubus_msg_send() abandons a partially transmitted message it sets
sock.eof so the client is torn down once control returns to the event
loop, but it leaves the tx queue empty. Any further ubus_msg_send() to
that client in the same callback therefore re-enters the direct-write
branch and writes a fresh message from offset 0, appending it to the few
bytes of the abandoned message still on the wire. The peer then reads a
spliced byte stream and desynchronises its framing before the disconnect
takes effect. Bail out early once sock.eof is set so no more bytes reach
the poisoned stream.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
<entry>
<title>libubus: close the passed fd when the request exceeds the size limit</title>
<updated>2026-09-25T07:46:40Z</updated>
<author>
<name>Felix Fietkau</name>
</author>
<published>2026-07-17T19:19:47Z</published>
<link rel='alternate' type='text/html' href='https://git-03.infra.openwrt.org/project/ubus/commit/?id=11e411e36f089bda4e206db3e7ece0d79c2a4272'/>
<id>urn:sha1:11e411e36f089bda4e206db3e7ece0d79c2a4272</id>
<content type='text'>
__ubus_start_request() rejects an over-sized message before calling
ubus_send_msg(), which is the function that otherwise takes ownership of
the caller-supplied fd and closes it on every path. Callers of
ubus_invoke_fd()/ubus_invoke_async_fd() rely on that ownership transfer
and do not close the fd themselves, so the early return leaked it. Close
it explicitly on this path to keep the ownership contract consistent.

Signed-off-by: Felix Fietkau &lt;nbd@nbd.name&gt;
</content>
</entry>
</feed>
