On Tue, Mar 21, 2023 at 10:36:16AM +0800, cjt wrote: > Hello, I have find a bug in openbgpd. RFC 4760 says that the length of > MP_REACH_NLRI is bigger than 5. > +---------------------------------------------------------+ > | Address Family Identifier (2 octets) | > +---------------------------------------------------------+ > | Subsequent Address Family Identifier (1 octet) | > +---------------------------------------------------------+ > | Length of Next Hop Network Address (1 octet) | > +---------------------------------------------------------+ > | Network Address of Next Hop (variable) | > +---------------------------------------------------------+ > | Reserved (1 octet) | > +---------------------------------------------------------+ > | Network Layer Reachability Information (variable) | > +---------------------------------------------------------+ > While, I found that in the code snippet of Function "rde_attr_parse" only > check 4 bytes. > > > rde_attr_parse(){ > case ATTR_MP_REACH_NLRI: > if (attr_len < 4) > goto bad_len; > break; > } > When I construct a MP_REACH_NLRI packet only have four bytes, it will make > the rde_get_mp_nexthop function without check the length of the data, > directly +1 to the "totlen". And make the "pos" is bigger than the "mplen" > in the rde_update_dispatch. As "mplen" is unsigned int , it will be a large > number and execute the following code. > int rde_get_mp_nexthop(u_char *data, uint16_t len, uint8_t aid, struct > filterstate *state){ > > /* ignore reserved (old SNPA) field as per RFC4760 */ > totlen += nhlen + 1; > data += nhlen + 1; > return (totlen); > } > > > void rde_update_dispatch(struct rde_peer *peer, struct imsg *imsg){ > if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, &state)) == -1) { > .... > goto done; > } > mpp += pos; > mplen -= pos; > while (mplen > 0) { > switch (aid) { > case AID_INET6: > .... > } > }
Thanks for the report. The following diff should fix the issue. -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.596 diff -u -p -r1.596 rde.c --- rde.c 13 Mar 2023 16:52:42 -0000 1.596 +++ rde.c 21 Mar 2023 08:00:45 -0000 @@ -2117,7 +2117,7 @@ bad_flags: goto bad_flags; goto optattr; case ATTR_MP_REACH_NLRI: - if (attr_len < 4) + if (attr_len < 5) goto bad_len; if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0)) goto bad_flags; @@ -2310,7 +2310,7 @@ rde_get_mp_nexthop(u_char *data, uint16_ totlen = 1; len--; - if (nhlen > len) + if (nhlen + 1 > len) return (-1); memset(&nexthop, 0, sizeof(nexthop));