On Wed, Sep 19, 2018 at 01:45:03PM +0000, Aaron A. Glenn wrote:
> * Theo de Raadt <[email protected]> [2018-09-19 11:34]:
> > 
> > Repeat the test please.
> 
> (gdb) bt
> #0  0x00000bcf682ccf80 in memcpy (dst0=0x7f7ffffec304, src0=0xbceff4c9ffd,
> length=4)
>     at /usr/src/lib/libc/string/memcpy.c:97
> #1  0x00000bccac440498 in aspath_verify (data=Variable "data" is not
> available.
> ) at /usr/src/usr.sbin/bgpd/util.c:488
> #2  0x00000bccac41a404 in rde_attr_parse (p=Variable "p" is not available.
> ) at /usr/src/usr.sbin/bgpd/rde.c:1509
> #3  0x00000bccac417ee9 in rde_update_dispatch (imsg=0x7f7ffffec560) at
> /usr/src/usr.sbin/bgpd/rde.c:1066
> #4  0x00000bccac41708a in rde_dispatch_imsg_session (ibuf=0xbceccd84000) at
> /usr/src/usr.sbin/bgpd/rde.c:400
> #5  0x00000bccac41577b in rde_main (debug=0, verbose=Variable "verbose" is not
> available.
> ) at /usr/src/usr.sbin/bgpd/rde.c:309
> #6  0x00000bccac401047 in main (argc=0, argv=0x7f7ffffed248) at
> /usr/src/usr.sbin/bgpd/bgpd.c:183
> (gdb) bt full
> #0  0x00000bcf682ccf80 in memcpy (dst0=0x7f7ffffec304, src0=0xbceff4c9ffd,
> length=4)
>     at /usr/src/lib/libc/string/memcpy.c:97
>         dst = 0x7f7ffffec304 ""
>         src = 0xbceff4ca000 <Address 0xbceff4ca000 out of bounds>
>         t = 4
> #1  0x00000bccac440498 in aspath_verify (data=Variable "data" is not
> available.
> ) at /usr/src/usr.sbin/bgpd/util.c:488
>         as = Cannot access memory at address 0x0
> (gdb) 
> 
> Had to build bgpd w/ symbols on another machine (though a timestamp matched
> source tree)
> 

Please try the following diff. This shuffles a few things around and fixes
two issues:
a) The 0 lenght check needs to be made agains seg_len not seg_size (since
that can never be 0). I moved the check a bit up to make it clearer.
b) don't increase the ptr in the AS 0 check before the memcpy().

b) results in the 4 byte read overflow which you tripped on.

-- 
:wq Claudio

Index: util.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
retrieving revision 1.35
diff -u -p -r1.35 util.c
--- util.c      14 Sep 2018 10:22:11 -0000      1.35
+++ util.c      19 Sep 2018 14:24:32 -0000
@@ -451,7 +451,7 @@ aspath_verify(void *data, u_int16_t len,
                as_size = 4;
 
        for (; len > 0; len -= seg_size, seg += seg_size) {
-               const u_char    *ptr;
+               const u_int8_t  *ptr;
                int              pos;
 
                if (len < 2)    /* header length check */
@@ -459,6 +459,10 @@ aspath_verify(void *data, u_int16_t len,
                seg_type = seg[0];
                seg_len = seg[1];
 
+               if (seg_len == 0)
+                       /* empty aspath segments are not allowed */
+                       return (AS_ERR_BAD);
+
                /*
                 * BGP confederations should not show up but consider them
                 * as a soft error which invalidates the path but keeps the
@@ -475,19 +479,15 @@ aspath_verify(void *data, u_int16_t len,
                if (seg_size > len)
                        return (AS_ERR_LEN);
 
-               if (seg_size == 0)
-                       /* empty aspath segments are not allowed */
-                       return (AS_ERR_BAD);
-
                /* RFC 7607 - AS 0 is considered malformed */
                ptr = seg + 2;
                for (pos = 0; pos < seg_len; pos++) {
-                       u_int32_t        as = 0;
+                       u_int32_t as;
 
-                       ptr += as_size;
                        memcpy(&as, ptr, as_size);
                        if (as == 0)
                                error = AS_ERR_SOFT;
+                       ptr += as_size;
                }
        }
        return (error); /* aspath is valid but probably not loop free */

Reply via email to