Skip to content

Bump pinned Zephyr for ba0bd94d4e9: mDNS listener poll arrays are stack-allocated (intermittent total mDNS death) #52

Description

@mikeysklar

Our pinned Zephyr carries a stack-use-after-return in the mDNS responder that kills all
mDNS answering intermittently, with no user code involved. Fixed upstream on 2026-08-06 by
ba0bd94d4e9 ("Use static storage for listener poll arrays"), which is not in our pin.

subsys/net/lib/dns/mdns_responder.c in our pin declares the arrays inside
init_listener():

1643:  struct zsock_pollfd ipv6_fds[MAX_IPV6_IFACE_COUNT];   automatic storage
1753:  struct zsock_pollfd ipv4_fds[MAX_IPV4_IFACE_COUNT];   automatic storage
1741:  register_dispatcher(&v6_ctx[i], &v6_svc, ..., ipv6_fds, ARRAY_SIZE(ipv6_fds));
1851:  register_dispatcher(&v4_ctx[i], &v4_svc, ..., ipv4_fds, ARRAY_SIZE(ipv4_fds));
1512:  ctx->dispatcher.fds = fds;                            pointer retained

and the retained pointer is dereferenced after the frame dies, at dispatcher.c:398 and in
the ctx->fds[i].fd reads at dispatcher.c:278-288 and 335-349.

Trap for anyone verifying: net_socket_service_register() itself copies the fds
(svc->pev[i].event = fds[i]), so that function looks safe in isolation. The retention is
one level up, via ctx->dispatcher.fds.

Symptom is intermittent, which is the signature: fine while the freed frame happens to be
intact, dead once it is reused. A board can answer nothing from a fresh boot with no Python
object in existence, then answer correctly after the next reset.

Verified on hardware. Applying the upstream commit as a local test patch:

.bss +32 bytes exactly, confirming the arrays moved to file scope

5 hard-reset cycles, 3 probe rounds each, no user mdns.Server
declared pass criterion >=2 of 3 rounds per cycle
result: 3/3, 3/3, 3/3, 3/3, 3/3 -- not one silent round in fifteen

pre-patch, same probe: one healthy window then 0/6, fresh-reset baseline 0

Not landable as a direct edit. tannewt pins Zephyr by SHA in west.yml, so this has to go
through adafruit/zephyr plus a pin bump.

Worth considering a bump rather than a single pick: DNS/mDNS churned nine commits upstream
between 2026-08-04 and 2026-08-11, including 748a0b1b023 (multi-homed A/AAAA and DNS-SD
response interface selection), 19289bd7529 (DNS port per family) and d7859a7117a
(getsockname failure handling). A bump costs a wider retest.

Separate from #51, which survives this fix and is a genuine port bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingport:siwx917SiWx917 CircuitPython port

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions