kern/99425: ping6 memory leak due to IPV6_RTHDR setsockopt behavior and inet6_rth_* functions.

Clément Lecigne clemun at gmail.com
Sat Jun 24 16:00:47 UTC 2006


>Number:         99425
>Category:       kern
>Synopsis:       ping6 memory leak due to IPV6_RTHDR setsockopt behavior and inet6_rth_* functions.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jun 24 16:00:34 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Clément Lecigne
>Release:        6.1
>Organization:
>Environment:
FreeBSD pouik 6.1-STABLE FreeBSD 6.1-STABLE #0: Mon May 29 06:09:07 CEST 2006     clem1 at pouik:/usr/src/sys/i386/compile/GENERIC  i386
>Description:
$ ping6 -v -h 255 `perl -e 'print "::1 "x124'`
PING6(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1: Echo Request
Routing: nxt 58, len 246 (1976 bytes), type 0, 123 segments, 0 left
 [1]::1
 (...)
 [57]::1
 [58]::1
 [59]::208.231.191.191
 [60]1c00:0:80e2:bfbf:100:0:90e2:bfbf
 [61]4:0:2000:0:9060:728::
 [62]f4e6:bfbf:d45d:528:4050:708:90e2:bfbf
 [63]1c00:0:7b00:0:100:0:ffff:ffff
 [64]ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
 [65]ffff:ffff:ffff:ffff:ffff:ffff::
 [66]84e7:bfbf:a35e:528:100:0:58e7:bfbf
 [67]100:0:5ce7:bfbf:0:528:50:728
 (...)

When we specify a larger number of intermediate hops with verbose output, ping6 displays stack data whereas ::1 after the 58th hop.

This bug can be reveal data stored on stack and seems due to a behavior of setsockopt with IPV6_RTHDR optname and the absence of bound checkings in inet6_rth_* functions from /usr/src/lib/libc/net/rthdr.c.

  setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR, (void *)rthdr, (rthdr->ip6r_len + 1) << 3);

If rthdr size is greater than approximatively 936 bytes (~60 segments), only rthdr first 936 bytes will be considered and sended in the routing extension header without altering rthdr->ip6r_len or rthdr->ip6r_segment.

ping6 calls init6_rth_segments() function which returns the rthdr->ip6r_segment value without checking if it's true...
>How-To-Repeat:
ping6 -v -h 255 `perl -e 'print "::1 "x124'`
>Fix:
What RFC3542 said about that ?

"For an IPv6 Type 0 Routing header, the number of segments must be between 0 and 127, inclusive."

The old init6_rthdr_space make sure that segment value is between 1 and 23. 
    
To be compliant with the RFC, it seems that we must:
   
    - check that segment value is between 0 and 127 (inclusive) in init6_rth_space, if not return 0.
    - check that ip6r_segment is not greater than 127 in init6_rth_add.
    - increase buffer size (optbuf_storage) in ip6_output.c (line 1767) to hold the possible 128 segments.
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list