netstack: return EADDRNOTAVAIL for SIOCGIFADDR/SIOCGIFNETMASK without IPv4#13433
Open
notandruu wants to merge 1 commit into
Open
netstack: return EADDRNOTAVAIL for SIOCGIFADDR/SIOCGIFNETMASK without IPv4#13433notandruu wants to merge 1 commit into
notandruu wants to merge 1 commit into
Conversation
… IPv4 On an interface with no IPv4 address assigned (for example an IPv6-only interface), SIOCGIFADDR and SIOCGIFNETMASK returned success without writing the ifreq, letting callers read back stale ifreq union data. ifconfig displays this as a fabricated IPv4 address. Linux returns EADDRNOTAVAIL for both ioctls in this case (net/ipv4/devinet.c:devinet_ioctl). Also populate sa_family (AF_INET) and the port bytes in the SIOCGIFADDR success path; previously only the address bytes were written, while Linux fills in the full sockaddr_in. SIOCGIFNETMASK already did this. Verified against Linux: a probe running SIOCGIFMTU, SIOCGIFADDR, and SIOCGIFNETMASK against an interface without IPv4 returns EADDRNOTAVAIL for the latter two on native Linux and on patched runsc, while stock runsc returns success with the caller's poison bytes intact. On an interface with IPv4, patched runsc output matches native Linux byte for byte. Fixes google#13431
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
ayushr2
reviewed
Jun 12, 2026
| hostarch.ByteOrder.PutUint16(ifr.Data[2:], 0) | ||
| copy(ifr.Data[4:8], addr.Addr) | ||
| break | ||
| return nil |
Collaborator
There was a problem hiding this comment.
Why return here instead of breaking? The other "success" cases don't return, they allow execution after the switch statement. It doesn't matter today since nothing happens outside the switch, but that might change in the future. Same for line 3692
Collaborator
|
Thanks for the fix! Could you sign the CLA? |
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.
Fixes #13431
Root cause
In
interfaceIoctl(pkg/sentry/socket/netstack/netstack.go), theSIOCGIFADDRandSIOCGIFNETMASKcases loop over interface addresses looking for AF_INET. When the interface has no IPv4 address (for example an IPv6-only interface), the loop finds nothing and the function returns success without writing the ifreq. The caller then reads back whatever was previously in the ifreq union, which is how ifconfig ends up displaying a fabricated IPv4 address built from stale bytes (in the issue's strace, remnants of the preceding SIOCGIFMTU call).Linux returns EADDRNOTAVAIL for both ioctls in this case (net/ipv4/devinet.c:devinet_ioctl, the
ifa == NULLpath shared by the SIOCGIF* address ioctls).Changes
SIOCGIFADDRandSIOCGIFNETMASKnow return EADDRNOTAVAIL when the interface has no IPv4 address.SIOCGIFADDRsuccess path now also populatessa_family(AF_INET) and the port bytes; previously only the 4 address bytes were written, while Linux fills in the full sockaddr_in. TheSIOCGIFNETMASKsuccess path already did this.NetdeviceTest.InterfaceAddr(loopback, family + address) andNetdeviceTest.InterfaceAddrIoctlsNoIPv4Addr(TUN device with no addresses, expects EADDRNOTAVAIL for both ioctls; gated on CAP_NET_ADMIN).Verification
Probe calling SIOCGIFMTU, then SIOCGIFADDR and SIOCGIFNETMASK with the ifreq poisoned with 0xAA bytes:
02000000+ addr02000000+ addr (matches Linux)The IPv6-only scenario was reproduced with runsc under Docker on an IPv6-only network (
docker network create --ipv6 --ipv4=false), matching the issue's EKS setup. A standalone mirror of the new test cases passes on native Linux and patched runsc, and fails on stock runsc with exactly the three asserted behaviors.Authored with the help of an AI assistant, per AGENTS.md the ABI change was verified against Linux kernel behavior as described above.