From e9cd716925e5c6cfb200c82f9d9bf6bc4118d47a Mon Sep 17 00:00:00 2001 From: James Tucker Date: Mon, 25 Nov 2024 22:52:41 +0000 Subject: [PATCH] route: fix parse of zero-length sockaddrs in RIBs Zero-length sockaddrs were observed in RIBs within golang/go#70528. These records are to be skipped, and an invariant for later slice manipulation is to be enforced by a defensive check in parseAddr. Fixes golang/go#70528 Change-Id: I4b8b5bd2339bbadc1d1be1ce14deeb6dd3b8e536 GitHub-Last-Rev: 066ba8a559e8ff543a445246279ad808cc67660f GitHub-Pull-Request: golang/net#228 Reviewed-on: https://go-review.googlesource.com/c/net/+/631475 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil --- route/address.go | 18 ++++++----- route/address_darwin_test.go | 58 ++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/route/address.go b/route/address.go index bae63003f..b649f4314 100644 --- a/route/address.go +++ b/route/address.go @@ -176,7 +176,7 @@ 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) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -188,7 +188,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { copy(a.IP[:], b[off4:n]) return a, nil case syscall.AF_INET6: - if len(b) < (off6+1) || len(b) < int(b[0]) { + if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -404,12 +404,16 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( } b = b[l:] case syscall.AF_INET, syscall.AF_INET6: - af = int(b[1]) - a, err := parseInetAddr(af, b) - if err != nil { - return nil, err + // #70528: if the sockaddrlen is 0, no address to parse inside, + // skip over the record. + if b[0] > 0 { + af = int(b[1]) + a, err := parseInetAddr(af, b) + if err != nil { + return nil, err + } + as[i] = a } - as[i] = a l := roundup(int(b[0])) if len(b) < l { return nil, errMessageTooShort diff --git a/route/address_darwin_test.go b/route/address_darwin_test.go index 0b5c72d1d..add72e37e 100644 --- a/route/address_darwin_test.go +++ b/route/address_darwin_test.go @@ -86,9 +86,61 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, }, []Addr{ - &Inet6Addr{IP: [16]byte{ 0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81 }}, - &Inet6Addr{IP: [16]byte{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff }, ZoneID: 33}, - &Inet6Addr{IP: [16]byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}}, + &Inet6Addr{IP: [16]byte{0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81}}, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + 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, + parseKernelInetAddr, + []byte{ + 0x00, 0x1e, 0x00, 0x00, + + 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, + 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff, + 0x00, 0x00, 0x00, 0x00, + + 0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + }, + []Addr{ + nil, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + nil, + nil, + nil, + nil, + nil, + }, + }, + // Additional case: golang/go/issues/70528#issuecomment-2498692877 + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x84, 0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0xF5, 0x5A, 0x00, 0x00, 0x03, 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, 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, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + []Addr{ + &Inet4Addr{IP: [4]byte{0x0, 0x0, 0x0, 0x0}}, + nil, + nil, nil, nil, nil,