osrg / gobgp

BGP implemented in the Go Programming Language
https://osrg.github.io/gobgp/
Apache License 2.0
3.59k stars 684 forks source link

Panic on failing to decode message from zebra on debian bookworm #2681

Open growse opened 1 year ago

growse commented 1 year ago

Problem

Latest gobgpd panics when trying to connect to zebra API. Also reproduced on gobgpd shipped with Debian bookworm (3.10 I think?)

Actual behaviour

./gobgpd -f /etc/gobgpd.conf  -l debug
{"level":"info","msg":"gobgpd started","time":"2023-08-02T10:25:16Z"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2023-08-02T10:25:16Z"}
{"Body":{},"Header":{"Len":10,"Marker":254,"Version":6,"VrfID":0,"Command":18},"Topic":"Zebra","level":"debug","msg":"send command to zebra","time":"2023-08-02T10:25:16Z"}
{"Body":{},"Header":{"Len":10,"Marker":254,"Version":6,"VrfID":0,"Command":15},"Topic":"Zebra","level":"debug","msg":"send command to zebra","time":"2023-08-02T10:25:16Z"}
{"Body":{},"Header":{"Len":10,"Marker":254,"Version":6,"VrfID":0,"Command":15},"Topic":"Zebra","level":"debug","msg":"send command to zebra","time":"2023-08-02T10:25:16Z"}
{"Message":{"Header":{"Len":20,"Marker":254,"Version":6,"VrfID":0,"Command":19},"Body":{"Data":"AAAAAAAAAAEAAA=="}},"Topic":"Zebra","level":"debug","msg":"read message from zebra","time":"2023-08-02T10:25:16Z"}
{"Topic":"Zebra","Version":6,"level":"info","msg":"success to connect to Zebra","time":"2023-08-02T10:25:16Z"}
{"Body":null,"Header":{"Len":10,"Marker":254,"Version":6,"VrfID":0,"Command":0},"Topic":"Zebra","level":"debug","msg":"send command to zebra","time":"2023-08-02T10:25:16Z"}
{"Data":"/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlZmF1bHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==","Error":"unknown route type: 254 in version: 6 (frr8.100000)","Header":{"Len":86,"Marker":254,"Version":6,"VrfID":0,"Command":33},"Topic":"Zebra","level":"warning","msg":"failed to decode body","time":"2023-08-02T10:25:16Z"}
{"Message":{"Header":{"Len":28,"Marker":254,"Version":6,"VrfID":0,"Command":17},"Body":{}},"Topic":"Zebra","level":"debug","msg":"read message from zebra","time":"2023-08-02T10:25:16Z"}
{"Data":"ZW5wMXMwAAAAAAAAAAAAAAAAAAIFAAAAAAABEEMAAgAAAAD/////AAAF3AAABdwAAAAAAAAAAAAAAAEAAAAGVgAEetORAA==","Error":"lack of bytes in remain data. need 1442841726 but 7","Header":{"Len":80,"Marker":254,"Version":6,"VrfID":0,"Command":0},"Topic":"Zebra","level":"warning","msg":"failed to decode body","time":"2023-08-02T10:25:16Z"}
{"Message":{"Header":{"Len":49,"Marker":254,"Version":6,"VrfID":0,"Command":2},"Body":{}},"Topic":"Zebra","level":"debug","msg":"read message from zebra","time":"2023-08-02T10:25:16Z"}
{"Message":{"Header":{"Len":49,"Marker":254,"Version":6,"VrfID":0,"Command":2},"Body":{}},"Topic":"Zebra","level":"debug","msg":"read message from zebra","time":"2023-08-02T10:25:16Z"}
{"Message":{"Header":{"Len":49,"Marker":254,"Version":6,"VrfID":0,"Command":2},"Body":{}},"Topic":"Zebra","level":"debug","msg":"read message from zebra","time":"2023-08-02T10:25:16Z"}
panic: runtime error: slice bounds out of range [:4] with capacity 1

goroutine 30 [running]:
github.com/osrg/gobgp/v3/internal/pkg/zebra.(*interfaceUpdateBody).decodeFromBytes(0xc0002d05b0, {0xc0000a5340, 0x40, 0x40}, 0x6, {{0xda77fa?, 0xc0000a5340?}, 0x40?})
        /home/runner/work/gobgp/gobgp/internal/pkg/zebra/zapi.go:1953 +0x856
github.com/osrg/gobgp/v3/internal/pkg/zebra.parseMessage(0xc0001ddce0, {0xc0000a5340, 0x40, 0x40}, {{0xda77fa?, 0xc00022de78?}, 0x43bd20?})
        /home/runner/work/gobgp/gobgp/internal/pkg/zebra/zapi.go:3577 +0x591
github.com/osrg/gobgp/v3/internal/pkg/zebra.NewClient.func2()
        /home/runner/work/gobgp/gobgp/internal/pkg/zebra/zapi.go:1453 +0x451
github.com/osrg/gobgp/v3/internal/pkg/zebra.NewClient.func3()
        /home/runner/work/gobgp/gobgp/internal/pkg/zebra/zapi.go:1486 +0x70
created by github.com/osrg/gobgp/v3/internal/pkg/zebra.NewClient
        /home/runner/work/gobgp/gobgp/internal/pkg/zebra/zapi.go:1483 +0x499

Expected behaviour:

gobgpd connects to zebra and communicates routes with frr

Context

Config:

# cat /etc/gobgpd.conf
[global.config]
    as = 204946
    router-id = "127.0.0.5"
    local-address-list = ['2a05:f480:3400:2148:5400:4ff:fe7a:d391']

[global.apply-policy.config]
    default-import-policy = "accept-route"
    default-export-policy = "accept-route"

[zebra]
    [zebra.config]
    enabled = true
    url = "unix:/run/frr/zserv.api"
    version = 6

Versions:

# ./gobgpd --version
gobgpd version 3.17.0
# dpkg --list |grep frr
ii  frr                             8.4.2-1                              amd64        FRRouting suite of internet protocols (BGP, OSPF, IS-IS, ...)
ii  frr-pythontools                 8.4.2-1                              all          FRRouting suite - Python tools
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
fujita commented 1 year ago

I guess that zebra API was updated. @irino

growse commented 1 year ago

i have done some digging. Will try and update this as I go.

The issue seems to be that interfaceNameSize should not be 20. On my test system, it seems like it should actually be... 16?

Here's some bytes from the interfaceAdd message body:

Data length is 70 [101 110 115 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 5 0 0 0 0 0 1 16 67 0 2 0 0 0 0 0 0 3 232 0 0 5 220 0 0 5 220 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 6 82 84 0 18 52 86 0]

Corresponding ip link

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    altname enp0s3

The name is at the front as you'd expect, but the ifIndex appears at 0x10 (=2). Then the status at 0x14 (5). If I manugally change interfaceNameSize to be 16, the interface is correctly parsed, all the waythrough tot he hwaddr.

Where did the value of 20 originally come from?

edit should add that I've worked around this for the moment by downgrading frr to 8.2 and specifying software-name as "8.2"

irino commented 1 year ago

Thank you for debugging. I found INTEFACE_NAMSIZ is changed in newer version than frr8.2

FRR8.2:

grep -e IFNAMSIZ -e INTERFACE_NAMSIZ frr-frr-8.2.2/lib/if.h
   #define IFNAMSIZ        16
   #define IFNAMSIZ        16
#define INTERFACE_NAMSIZ      20
        char name[INTERFACE_NAMSIZ];

FRR8.4.2

grep -e IFNAMSIZ -e INTERFACE_NAMSIZ frr-frr-8.4.2/lib/if.h
   #define IFNAMSIZ        16
   #define IFNAMSIZ        16
#define INTERFACE_NAMSIZ      IFNAMSIZ
        char name[INTERFACE_NAMSIZ];

INTERFACE_NAMSIZ is originally 20. However recent version is 16.