From 4d38db76854b199960801a1734443fd02870d7e1 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Wed, 20 Jul 2016 12:23:22 +0900 Subject: [PATCH] route: don't crash or hang up with corrupted messages Fixes golang/go#16438. Change-Id: I2a97e57cae298e8eecdd5637c9e03493a449fc62 Reviewed-on: https://go-review.googlesource.com/25070 Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- route/address.go | 18 +++++++++++++++--- route/interface_freebsd.go | 12 ++++++------ route/interface_openbsd.go | 9 ++++++++- route/message.go | 6 ++++++ route/message_test.go | 23 +++++++++++++++++++++++ route/route_openbsd.go | 6 +++++- 6 files changed, 63 insertions(+), 11 deletions(-) diff --git a/route/address.go b/route/address.go index 206a8371..a56909c1 100644 --- a/route/address.go +++ b/route/address.go @@ -234,7 +234,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] case sysAF_INET, sysAF_INET6: af = int(b[1]) a, err := parseInetAddr(af, b) @@ -242,7 +246,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] default: l, a, err := fn(af, b) if err != nil { @@ -262,7 +270,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( return nil, err } as[i] = a - b = b[roundup(int(b[0])):] + l := roundup(int(b[0])) + if len(b) < l { + return nil, errMessageTooShort + } + b = b[l:] } } return as[:], nil diff --git a/route/interface_freebsd.go b/route/interface_freebsd.go index c8305391..9f6f50c0 100644 --- a/route/interface_freebsd.go +++ b/route/interface_freebsd.go @@ -13,12 +13,12 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro extOff = int(nativeEndian.Uint16(b[18:20])) bodyOff = int(nativeEndian.Uint16(b[16:18])) } else { - if len(b) < w.bodyOff { - return nil, errMessageTooShort - } extOff = w.extOff bodyOff = w.bodyOff } + if len(b) < extOff || len(b) < bodyOff { + return nil, errInvalidMessage + } l := int(nativeEndian.Uint16(b[:2])) if len(b) < l { return nil, errInvalidMessage @@ -53,11 +53,11 @@ func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, } bodyOff = int(nativeEndian.Uint16(b[16:18])) } else { - if len(b) < w.bodyOff { - return nil, errMessageTooShort - } bodyOff = w.bodyOff } + if len(b) < bodyOff { + return nil, errInvalidMessage + } l := int(nativeEndian.Uint16(b[:2])) if len(b) < l { return nil, errInvalidMessage diff --git a/route/interface_openbsd.go b/route/interface_openbsd.go index 24451d8c..e4a143c1 100644 --- a/route/interface_openbsd.go +++ b/route/interface_openbsd.go @@ -24,7 +24,11 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { Addrs: make([]Addr, sysRTAX_MAX), raw: b[:l], } - a, err := parseLinkAddr(b[int(nativeEndian.Uint16(b[4:6])):]) + ll := int(nativeEndian.Uint16(b[4:6])) + if len(b) < ll { + return nil, errInvalidMessage + } + a, err := parseLinkAddr(b[ll:]) if err != nil { return nil, err } @@ -42,6 +46,9 @@ func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, erro return nil, errInvalidMessage } bodyOff := int(nativeEndian.Uint16(b[4:6])) + if len(b) < bodyOff { + return nil, errInvalidMessage + } m := &InterfaceAddrMessage{ Version: int(b[2]), Type: int(b[3]), diff --git a/route/message.go b/route/message.go index 27cbf6b7..d7ae0eb5 100644 --- a/route/message.go +++ b/route/message.go @@ -42,6 +42,12 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) { for len(b) > 4 { nmsgs++ l := int(nativeEndian.Uint16(b[:2])) + if l == 0 { + return nil, errInvalidMessage + } + if len(b) < l { + return nil, errMessageTooShort + } if b[2] != sysRTM_VERSION { b = b[l:] continue diff --git a/route/message_test.go b/route/message_test.go index a1263d8f..c0c7c57a 100644 --- a/route/message_test.go +++ b/route/message_test.go @@ -93,3 +93,26 @@ func TestMonitorAndParseRIB(t *testing.T) { time.Sleep(200 * time.Millisecond) } } + +func TestParseRIBWithFuzz(t *testing.T) { + for _, fuzz := range []string{ + "0\x00\x05\x050000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "0000000000000\x02000000" + + "00000000", + "\x02\x00\x05\f0000000000000000" + + "0\x0200000000000000", + "\x02\x00\x05\x100000000000000\x1200" + + "0\x00\xff\x00", + "\x02\x00\x05\f0000000000000000" + + "0\x12000\x00\x02\x0000", + "\x00\x00\x00\x01\x00", + "00000", + } { + for typ := RIBType(0); typ < 256; typ++ { + ParseRIB(typ, []byte(fuzz)) + } + } +} diff --git a/route/route_openbsd.go b/route/route_openbsd.go index b07862f0..76eae40d 100644 --- a/route/route_openbsd.go +++ b/route/route_openbsd.go @@ -19,7 +19,11 @@ func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) { Index: int(nativeEndian.Uint16(b[6:8])), raw: b[:l], } - as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[int(nativeEndian.Uint16(b[4:6])):]) + ll := int(nativeEndian.Uint16(b[4:6])) + if len(b) < ll { + return nil, errInvalidMessage + } + as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:]) if err != nil { return nil, err }