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));

Reply via email to