This fuzzer is based on test-bus-match. Even the initial corpus is
derived entirely from it.
https://bugzilla.redhat.com/show_bug.cgi?id=1935084 shows an crash
in bus_match_parse(). I checked the coverage stats on oss-fuzz, and
sadly existing fuzzing did not cover this code at all.
I'm getting the following error under valgrind:
==305970== Invalid free() / delete / delete[] / realloc()
==305970== at 0x483E9F1: free (vg_replace_malloc.c:538)
==305970== by 0x4012CD: mfree (alloc-util.h:48)
==305970== by 0x4012EF: freep (alloc-util.h:83)
==305970== by 0x4017F4: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970== by 0x401A58: main (fuzz-main.c:39)
==305970== Address 0x59972f0 is 0 bytes inside a block of size 8,192 free'd
==305970== at 0x483FCE4: realloc (vg_replace_malloc.c:834)
==305970== by 0x4C986F7: _IO_mem_finish (in /usr/lib64/libc-2.33.so)
==305970== by 0x4C8F5E0: fclose@@GLIBC_2.2.5 (in /usr/lib64/libc-2.33.so)
==305970== by 0x49D2CDB: fclose_nointr (fd-util.c:108)
==305970== by 0x49D2D3D: safe_fclose (fd-util.c:124)
==305970== by 0x4A4BCCC: fclosep (fd-util.h:41)
==305970== by 0x4A4E00F: bus_match_to_string (bus-match.c:859)
==305970== by 0x4016C2: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970== by 0x401A58: main (fuzz-main.c:39)
==305970== Block was alloc'd at
==305970== at 0x483FAE5: calloc (vg_replace_malloc.c:760)
==305970== by 0x4C98787: open_memstream (in /usr/lib64/libc-2.33.so)
==305970== by 0x49D56D6: open_memstream_unlocked (fileio.c:97)
==305970== by 0x4A4DEC5: bus_match_to_string (bus-match.c:859)
==305970== by 0x4016C2: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970== by 0x401A58: main (fuzz-main.c:39)
==305970==
So the fclose() which is called from _cleanup_fclose_ clearly reallocates the
buffer (maybe to save memory?). open_memstream(3) says:
The locations referred to by these pointers are updated each time the
stream is flushed (fflush(3)) and when the stream is closed (fclose(3)).
This seems to mean that we should close the stream first before grabbing the
buffer pointer.
BPF filtering accesses fields in the netlink header that are
only filled in by libudev, never by the kernel. Therefore adding
BPF filters for kernel monitors is pointless. Even false filtering
of kernel events might be possible; at least it's hard to prove that
it can't occur.
As sd_device_get_sysattr_value() may be already used to read uevent
file. The read value of uevent file may be usually quite different
from the action string.
There are three calls of device_cache_sysattr_value(). Two of them are
just caching the value. Hence, let's ignore its failure, and propagate
original error code.
One exception is the last call in sd_device_get_sysattr_value().
Unfortunately, it returns `const char *` instead of `char *`. So,
sd_device object must have the reference of the returned value.
Hence, error in updating the cache by device_cache_sysattr_value()
is critical, and we need to propagate the error in that case.
It is not intuitive, and I do not know why the function behave so.
But let's keep that behavior for compatibility, as such behavior
may be already used explicitly by callers.
To make sd-device properly usable for all programs we need to provide an
API for the "action" field of an event, it's one of the most relevant
ones, and it was so far missing.
This also adds sd_device_get_seqnum(), which isn't that interesting,
except for generating pretty debug output, which we use it ourselves
for.
This also makes device_new_from_stat_rdev() public, as it is truly
useful, as we can see in our own uses of it, and I think is fairly
generic to show up in the public APIs.
Apparently, in our current public headers (i.e. those called sd-*.h) we
suffixed typedefs that we use as values with _t, but we didn't do this
for enum typedefs. Fix that while this stuff is not actually public yet.
With this scheme "value typedefs" now end systematically in _t, and
"object typedefs" (i.e. structures that are typically passed around via
pointers and not values) do not.
No code changes, just some renaming.
The existing set_offline() short-circuit erroneously included
when f->archive was true and header->state was STATE_OFFLINE.
This commit makes the short-circuit f->archive aware, so it will
only catch scenarios where there's not an offlining in progress
and the header state matches the target state of either archived
or offline.
Fixes https://github.com/systemd/systemd/issues/17770