If we synthesize a stub reply from multiple upstream packet (i.e. a
series of CNAME/DNAME redirects), it might happen that we add the same
RR to a different reply section at a different CNAME/DNAME redirect
chain element. Let's clean this up once we are about to send the reply
message to the client: let's remove sections from "lower-priority"
sections when they are already listed in a "higher-priority" section.
In 2f4d8e577c I argued that following
CNAMEs in the stub is not necessary anymore. However, I think it' better
to revert to the status quo ante and follow it after all, given it is
easy for us and makes sure our D-Bus/varlink replies are more similar to
our DNS stub replies that way, and we save clients potential roundtrips.
Hence, whenever we hit a CNAME/DNAME redirect, let's restart the query
like we do for the D-Bus/Varlink case, and collect replies as we go.
www.netflix.com responds with a chain of CNAMEs in the same packet.
Let's handle that properly (so far we only followed CNAMEs a single step
when in the same packet)
Fixes: #18819
Let's refuse to consider CNAME/DNAME replies matching for RR types where
that is not really conceptually allow (i.e. on CNAME/DNAME lookups
themselves).
(And add a similar check to dns_resource_key_match_cname_or_dname() too,
which implements a smilar match)
Also use structued initialization in one more place, use '\0' for NUL bytes,
and move variable to the right block (the code was OK, but it is strange to
have 'char *value' defined in a different scope then 'size_t value_allocated').
The fuzzer seems to have no trouble with this sample. It seems that the
problem reported in the bug is not caused by the match parsing code. But
let's add the sample just in case.
https://bugzilla.redhat.com/show_bug.cgi?id=1935084
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.
In PR #17431 we have introduced retry loop in link_update() in order to
maximize the chance that we end up with correct target when there are
multiple contenders for given symlink.
Number of iterations in retry loop is either 1 or
LINK_UPDATE_MAX_RETRIES, depending on the value of 'initialized' db
flag. When device appears for the first time we need to set the
flag before calling link_update() via update_devnode() for the second
time to make sure we run the second invocation with higher retry loop
counter.
When running integration tests under sanitizers D-Bus fails to
shutdown cleanly, causing unnecessary noise in the logs:
```
dbus-daemon[272]: ==272==LeakSanitizer has encountered a fatal error.
dbus-daemon[272]: ==272==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
dbus-daemon[272]: ==272==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
```
Since we're not "sanitizing" D-Bus anyway let's disable LSan's at_exit
check for the dbus.service to get rid of this error.
NULLSTR_FOREACH expects two terminating NULs, but the joined string
for extension-release.d only had the canonical one.
Use a placeholder when joining and fix it manually.
Given these files are part of procfs, let's use the correct API calls
for reading them.
This changes one occasion of read_one_line_file() to
read_full_virtual_file(), which superficially is a different thing, but
shouldn't actually be a difference, since sysctls can't be longer than
4K anyway, and the piecemeal logic behind read_one_line_file() cannot
work with the special semantics of procfs anyway.