- support reading the next timeout in order to determine the poll timeout
- add a callback for fd add/delete/update
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Repeatedly calling a run-time function like strlen() on an
invariant value is inefficient, especially if that value can be
computed once (at initialization) or better yet, computed at
compile-time.
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
If a JSON file might be read by a human, say for debugging, it
could be useful to pretty-print it. We do this in places by
calling "json_dump -i" but it shouldn't be necessary to know the
arguments to "jshn" (and indeed, that's not portable if we retool
the underlying implementation). Conversely output that's ephemeral
doesn't need to be pretty (say being piped as input to another
command).
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
errno needs to be compared against EINTR/EAGAIN instead of the return code,
and only if the return code is < 0.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Using the return value of blobmsg_name as input argument to strcpy can lead
to warnings like these:
error: 'strcpy' offset 6 from the object at 'cur' is out of the bounds of referenced subobject 'name' with type 'uint8_t[]' {aka 'unsigned char[]'} at offset 6 [-Werror=array-bounds]
Fix this by replacing hdr->name with the equivalent hdr + 1
Signed-off-by: Felix Fietkau <nbd@nbd.name>
It may not be clear to all users of this API if the provided maxlen argument
refers to the maximum string length or the maximum buffer size.
In order to improve safety and convenience of this API, make it refer to
the maximum string length.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Yet another macro wrapper around the corresponding avl_* macro.
This new macro makes it possible to iterate over vlists in ways which
may have destructive consequences without being punished by segfault.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This uses the same return type as tv_diff so we don't need to check for
integer overflow.
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
Acked-by: Jo-Philipp Wich <jo@mein.io>
Acked-by: John Crispin <john@phrozen.org>
The uloop_timeout_remaining function is public and changing its return
type breaks ABI. Change the return type back to int, and return INT_MIN
or INT_MAX if the value returned by tv_diff would overflow integer.
Fixes: be3dc7223a ("uloop: avoid integer overflow in tv_diff")
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
Acked-by: Jo-Philipp Wich <jo@mein.io>
Acked-by: John Crispin <john@phrozen.org>
The tv_diff function can potentially overflow as soon as t2->tv_sec is
larger than 2147483. This is very easily hit in ujail, after only
2147484 seconds of uptime, or 24.85 days.
Improve the behaviour by changing the return type to int64_t.
Fixes: FS#3943
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
Currently there is no measure in place to prevent the blob buffer
to exceed its maximum allowed length of 16MB. Continuously
calling blob_add() will expand the buffer until it exceeds
BLOB_ATTR_LEN_MASK and after that will return valid blob_attr
pointer without increasing the buflen.
A test program was added in the previous commit, this one fixes
the issue by asserting that the new bufflen after grow does not
exceed BLOB_ATTR_LEN_MASK.
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@gmail.com>
The blob buffer has no limitation in place
to prevent buflen to exceed maximum size.
This commit adds a test to demonstrate how
a blob increases past the maximum allowd
size of 16MB. It continuously adds chunks
of 64KB and with the 255th one blob_add()
returns a valid attribute pointer but the
blob's buflen does not increase.
The test is used to demonstrate the
failure, which is fixed with a follow-up
commit.
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@gmail.com>
[adjusted test case for cram usage]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Add new utility function mkdir_p(char *path, mode_t mode) to replace
the partially buggy implementations found accross fstools and procd.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
When dealing with 64-bit integers in JSON documents, blobmsg_parse
becomes useless as blobmsg-json only uses BLOBMSG_TYPE_INT64 if the
value exceeds the range of a 32-bit integer, otherwise
BLOBMSG_TYPE_INT32 is used. This is because blobmsg-json parses the
JSON document ad-hoc without knowing the schema in advance and hence
a result of the design of blobmsg-json (and the absence of JSON
schema definitions).
In practise, this made code less readable as instead of using
blobmsg_parse() one had to to deal with *all* attributes manually just
to catch fields which can be both, BLOBMSG_TYPE_INT32 or
BLOBMSG_TYPE_INT64, but are always dealt with as uint64_t in code as
they potentially could exceed the 32-bit range.
To resolve this issue, introduce as special wildcard attribute
type BLOBMSG_CAST_INT64 which should only be used in policies used
by blobmsg_parse(). If used for an attribute in the policy,
blobmsg_parse shall accept all integer types and allow the user
to retrieve the value using the uint64_t blobmsg_cast_u64() and
int64_t blobmsg_cast_s64() functions which is also introduced by this
commit.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Ran into some issues with my fd event being garbage collected. As I
never wanted to call :delete, I had seen no reason to keep the returned
object, as my callback and upvalues were still valid.
Signed-off-by: Karl Palsson <karlp@etactica.com>
Instead of having to adjust the index repeatedly as the stack is
manipulated, use absolute addressing for the function arguments, so they
stay the same throughout the call. Zero functional change, just
subjectively easier to follow variables.
Signed-off-by: Karl Palsson <karlp@etactica.com>
Actually check for flags being valid, instead of simply ignoring the
call if flags was zero.
Use standard lua checks for the function argument, so you can get a
normal "argument #2 was invalid, expected function, got xxx" instead of
the vague, "invalid arg list"
Signed-off-by: Karl Palsson <karlp@etactica.com>
Those functions were moved out of blobmsg.h.
Fixes: 0918243e90 ("move json formatting to the blobmsg_json library")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
blobmsg_check_attr_len was calling blobmsg_check_data for some, but not all
attribute types. These checks was missing for arrays and tables.
Additionally, the length check in blobmsg_check_data was a bit off, since
it was comparing the blobmsg data length against the raw blob attr length.
Fix this by checking the raw blob length against the buffer length in
blobmsg_hdr_from_blob
Signed-off-by: Felix Fietkau <nbd@nbd.name>
blobmsg_hdr_valid_namelen was omitted when name==false
The blob_len vs blobmsg_namelen changes were not taking into account
potential padding between name and data
Signed-off-by: Felix Fietkau <nbd@nbd.name>
blobmsg_check_array_len expects the length of the full attribute buffer,
not just the data length.
Due to other missing length checks (fixed in the next commit), this did
not show up as a test failure
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Following regression was introduced in commit 5e75160f48 ("blobmsg:
fix attrs iteration in the blobmsg_check_array_len()"):
Thread 1 "test-fuzz" received signal SIGSEGV, Segmentation fault.
in blob_len (attr=0x6020000100d4) at libubox/blob.h:102
102 return (be32_to_cpu(attr->id_len) & BLOB_ATTR_LEN_MASK) - sizeof(struct blob_attr);
blob_len (attr=0x6020000100d4) at /libubox/blob.h:102
blob_raw_len (attr=0x6020000100d4) at /libubox/blob.h:111
blob_pad_len (attr=0x6020000100d4) at /libubox/blob.h:120
blobmsg_check_array_len (attr=0x6020000000d0, type=0, blob_len=10) at /libubox/blobmsg.c:145
fuzz_blobmsg_parse (data=0x6020000000d0 "\001\004", size=10) at /libubox/tests/fuzz/test-fuzz.c:57
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Some tools like ucert use concatenations of multiple blobs. Account for
this case by allowing the underlying buffer length to be greater than
the blob length.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Starting with 75e300aeec ("blobmsg: fix wrong payload len passed from
blobmsg_check_array") blobmsg_check_array_len() gets *blob* length
passed as argument. It cannot be used with __blobmsg_for_each_attr()
which expects *data* length.
Use blobmsg_for_each_attr() which calculates *data* length on its own.
The same bug was already reported in the past and there was fix attempt
in the commit cd75136b13 ("blobmsg: fix wrong payload len passed from
blobmsg_check_array"). That change made blobmsg_check_attr_len() calls
fail however.
This is hopefully the correct & complete fix:
1. blobmsg_check_array_len() gets *blob* length
2. It calls blobmsg_check_attr_len() which requires *blob* length
3. It uses blobmsg_for_each_attr() which gets *data* length
This fixes iterating over random memory treated as attrs. That was
resulting in check failing randomly for totally correct blobs. It's
critical e.g. for procd project with its instance_fill_array() failing
and procd not starting services.
Fixes: 75e300aeec ("blobmsg: fix wrong payload len passed from blobmsg_check_array")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Seems like the CI runners are slower and produce different test output:
- [0/1] finish 'sleep 1' (killer)
[1/1] start 'sleep 1' (sleeper)
+ [1/1] finish 'sleep 1' (killer)
+ [1/1] finish 'sleep 1' (killer)
[1/1] cancel 'sleep 1' (sleeper)
[0/1] finish 'sleep 1' (sleeper)
[1/1] start 'sleep 1' (sleeper)
Lets try to fix it by lowering the killing timeout.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Fixes a use-after-free bug in runqueue_task_kill():
Invalid read of size 8
at runqueue_task_kill (runqueue.c:200)
by uloop_process_timeouts (uloop.c:505)
by uloop_run_timeout (uloop.c:542)
by uloop_run (uloop.h:111)
by main (tests/test-runqueue.c:126)
Address 0x5a4b058 is 24 bytes inside a block of size 208 free'd
at free
by runqueue_task_complete (runqueue.c:234)
by runqueue_task_kill (runqueue.c:199)
by uloop_process_timeouts (uloop.c:505)
by uloop_run_timeout (uloop.c:542)
by uloop_run (uloop.h:111)
by main (tests/test-runqueue.c:126)
Block was alloc'd at
at calloc
by add_sleeper (tests/test-runqueue.c:101)
by main (tests/test-runqueue.c:123)
Since commit 11e8afea (runqueue should call the complete handler from
more places) the call to the complete() callback has been moved to
runqueue_task_complete(). However in runqueue_task_kill()
runqueue_task_complete() is called before the kill() callback. This
will result in a use after free if the complete() callback frees the
task struct.
Furthermore runqueue_start_next() is already called at the end of
runqueue_task_complete(), so there is no need to call it again in
runqueue_task_kill().
The issue was that the _complete() callback frees the memory used by the
task struct, which is then read after the _complete() callback returns.
Ref: FS#3016
Signed-off-by: Alban Bedel <albeu@free.fr>
[initial test case, kill cb comment fix]
Signed-off-by: Chris Nisbet <nischris@gmail.com>
[testcase improvements and commit subject/description tweaks]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
The comment relating to the runqueue task structure 'cancel' callback
indicated that the callback 'calls' runqueue_task_complete, which
isn't quite right. The callback _should_ call runqueue_task_complete.
Signed-off-by: Chris Nisbet <nischris@gmail.com>
* add a test for blobmsg_check_array() to test an array with a string in it
This test was added in conjunction with a change to blobmsg_check_array() to
get it to pass the length obtained from blob_len() rather than blobmsg_len().
Signed-off-by: Chris Nisbet <nischris@gmail.com>
Fix incorrect use of blobmsg_len() on passed blobmsg to
blobmsg_check_array_len() introduced in commit 379cd33d19
("fix wrong payload len passed from blobmsg_check_array") by using correct
blob_len().
By using blobmsg_len() a value too small was passed to blobmsg_check_array()
which could lead to this function returning an error when there is none.
Fixes: 379cd33d19 ("fix wrong payload len passed from blobmsg_check_array")
Signed-off-by: Chris Nisbet <nischris@gmail.com>
[add fixes tag, rewrap commit message]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Fix out of bounds read in blobmsg_parse and blobmsg_check_name. The
out of bounds read happens because blob_attr and blobmsg_hdr have
flexible array members, whose size is 0 in the corresponding sizeofs.
For example the __blob_for_each_attr macro checks whether rem >=
sizeof(struct blob_attr). However, what LibFuzzer discovered was,
if the input data was only 4 bytes, the data would be casted to blob_attr,
and later on blob_data(attr) would be called even though attr->data was empty.
The same issue could appear with data larger than 4 bytes, where data
wasn't empty, but contained only the start of the blobmsg_hdr struct,
and blobmsg_hdr name was empty. The bugs were discovered by fuzzing
blobmsg_parse and blobmsg_array_parse with LibFuzzer.
CC: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Jo-Philipp Wich <jo@mein.io>
Signed-off-by: Juraj Vijtiuk <juraj.vijtiuk@sartura.hr>
[refactored some checks, added fuzz inputs, adjusted unit test results]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Help detecting Valgrind OOB reads and other issues.
Conditional jump or move depends on uninitialised value(s)
at 0x5452886: blobmsg_parse (blobmsg.c:203)
by 0x400A8E: test_blobmsg (tests/test-blobmsg-parse.c:66)
by 0x400A8E: main (tests/test-blobmsg-parse.c:82)
Conditional jump or move depends on uninitialised value(s)
at 0x545247F: blobmsg_check_name (blobmsg.c:39)
by 0x545247F: blobmsg_check_attr_len (blobmsg.c:79)
by 0x5452710: blobmsg_parse_array (blobmsg.c:159)
by 0x400AB8: test_blobmsg (tests/test-blobmsg-parse.c:69)
by 0x400AB8: main (tests/test-blobmsg-parse.c:82)
Conditional jump or move depends on uninitialised value(s)
at 0x54524A0: blobmsg_check_name (blobmsg.c:42)
by 0x54524A0: blobmsg_check_attr_len (blobmsg.c:79)
by 0x5452710: blobmsg_parse_array (blobmsg.c:159)
by 0x400AB8: test_blobmsg (tests/test-blobmsg-parse.c:69)
by 0x400AB8: main (tests/test-blobmsg-parse.c:82)
Ref: http://lists.infradead.org/pipermail/openwrt-devel/2020-January/021204.html
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Better safe than sorry and while at it prefer use of PRId16 and PRId32
formatting constants as well.
Reviewed-by: Jo-Philipp Wich <jo@mein.io>
Signed-off-by: Petr Štetiar <ynezz@true.cz>