Date: Sat, 24 Jun 2006 15:56:38 GMT From: Clément Lecigne <clemun@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/99425: ping6 memory leak due to IPV6_RTHDR setsockopt behavior and inet6_rth_* functions. Message-ID: <200606241556.k5OFucm8003402@www.freebsd.org> Resent-Message-ID: <200606241600.k5OG0Y6U072036@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606241556.k5OFucm8003402>
