{bp-19872} net/arp: fix cross-interface resolution and a device-lock leak - #20070
Merged
Conversation
The -EINPROGRESS path jumps over the netdev_unlock() below it, so the caller waits holding d_lock. The receive path needs that same lock to dispatch the ARP reply, and the interface stalls for good. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
On a cache miss arp_find() returns the MAC of any interface holding the address, ignoring the egress device. Two interfaces on one subnet then leave the peer unreachable until the entry is relearned. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
cederom
approved these changes
Sep 7, 2026
Contributor
Author
|
CI fix |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent defects in net/arp that together make a peer periodically
unreachable when two network interfaces share an IPv4 subnet. Both are needed:
fixing either one alone produces a worse result than the bug, which is why they
are submitted together as separate commits.
arp_find() can answer with another interface's MAC.
The ARP table itself is keyed by (device, address), but on a cache miss
arp_find() falls back to netdev_foreach(arp_match, ...), and arp_match()
compares only the IP address. Any interface holding that address wins and its
MAC is returned, regardless of the device the frame is going out on. A frame
transmitted on interface A can therefore be addressed to the MAC of interface B.
Note the asymmetry with route selection, which already filters on
IFF_IS_RUNNING (netdev_prefixlen_findby_lipv4addr()).
arp_send() leaks dev->d_lock.
The -EINPROGRESS branch does goto wait, jumping over the netdev_unlock(dev)
further down, and arp_wait() does not release the lock either. The caller
therefore sleeps holding d_lock, while netdev_upper_rxpoll_work() needs that
same lock to dispatch incoming frames — so the ARP reply being waited for can
never reach arp_input(). Because d_lock is recursive, retries re-acquire it
and the recursion depth is never unwound, so the interface stays blocked.
Defect 2 is normally invisible: the wrong-MAC shortcut of defect 1 keeps the code
from ever reaching real ARP resolution. Remove the shortcut without fixing the
lock and a self-healing outage becomes a permanent loss of connectivity.
Impact
RELEASE
Testing
CI