From 2dab271ff1b7396498746703d88fefcddcc5cec7 Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Wed, 5 Feb 2025 15:43:53 +0000 Subject: [PATCH] route: treat short sockaddr lengths as unspecified Previously, we enforced minimum length requirements for sockaddr, but the route command can legitimately parse shorter lengths. This change treats any sockaddr with length less than the address offset as an unspecified address (0.0.0.0 for IPv4 or :: for IPv6), as discern by monitoring the route command. To replicate the issue, prior to the fix, execute the following: First: route -n monitor Next: sudo route -n add -inet6 -ifscope en11 -net :: \ -netmask :: fe80::2d0:4cff:fe10:15d2 The route command that is actively monitoring will print something such as: RTM_ADD: Add Route: len 152, pid: 81198, seq 1, errno 0, ifscope 13, flags: locks: inits: sockaddrs: :: fe80::2d0:4cff:fe10:15d2 :: Prior to the fix, if you had attempted parse the above message, PareRIB would have returned errInvalidAddr which is clearly false. Fixes golang/go#71557 Change-Id: Iec86cc9b05a765b6e67e95a4e30ff31f66f3d17e GitHub-Last-Rev: 396d8a27da8d8ade966821f75807861559fec495 GitHub-Pull-Request: golang/net#231 Reviewed-on: https://go-review.googlesource.com/c/net/+/646556 Commit-Queue: Ian Lance Taylor Reviewed-by: Damien Neil LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- route/address.go | 8 ++++---- route/address_darwin_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/route/address.go b/route/address.go index d0e9f415f..279505b10 100644 --- a/route/address.go +++ b/route/address.go @@ -178,13 +178,13 @@ func parseInetAddr(af int, b []byte) (Addr, error) { ) switch af { case syscall.AF_INET: - if len(b) < (off4+1) || len(b) < int(b[0]) { + if len(b) < int(b[0]) { return nil, errInvalidAddr } sockAddrLen := int(b[0]) a := &Inet4Addr{} // sockAddrLen of 0 is valid and represents 0.0.0.0 - if sockAddrLen != 0 { + if sockAddrLen > off4 { // Calculate how many bytes of the address to copy: // either full IPv4 length or the available length. n := off4 + ipv4Len @@ -195,13 +195,13 @@ func parseInetAddr(af int, b []byte) (Addr, error) { } return a, nil case syscall.AF_INET6: - if len(b) < (off6+1) || len(b) < int(b[0]) { + if len(b) < int(b[0]) { return nil, errInvalidAddr } sockAddrLen := int(b[0]) a := &Inet6Addr{} // sockAddrLen of 0 is valid and represents :: - if sockAddrLen != 0 { + if sockAddrLen > off6 { n := off6 + ipv6Len if sockAddrLen < n { n = sockAddrLen diff --git a/route/address_darwin_test.go b/route/address_darwin_test.go index 55accff9d..80f686e97 100644 --- a/route/address_darwin_test.go +++ b/route/address_darwin_test.go @@ -96,6 +96,38 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ nil, }, }, + // sudo route -n add -inet6 -ifscope en11 -net :: -netmask :: fe80::2d0:4cff:fe10:15d2 + // RTM_ADD: Add Route: len 152, pid: 81198, seq 1, errno 0, ifscope 13, flags: + // locks: inits: + // sockaddrs: + // :: fe80::2d0:4cff:fe10:15d2 :: + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xd0, 0x4c, 0xff, 0xfe, 0x10, 0x15, 0xd2, + 0x00, 0x00, 0x00, 0x00, + + 0x02, 0x1e, 0x00, 0x00, + }, + []Addr{ + &Inet6Addr{}, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd0, 0x4c, 0xff, 0xfe, 0x10, 0x15, 0xd2}}, + &Inet6Addr{}, + nil, + nil, + nil, + nil, + nil, + }, + }, // golang/go#70528, the kernel can produce addresses of length 0 { syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK,