kern/99779: kernel panic due to Invlalid next packet identification
in soreceive()
JINMEI Tatuya
jinmei at isl.rdc.toshiba.co.jp
Tue Jul 4 12:20:25 UTC 2006
>Number: 99779
>Category: kern
>Synopsis: kernel panic due to Invlalid next packet identification in soreceive()
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Jul 04 12:20:23 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: JINMEI Tatuya
>Release: FreeBSD 6.1-RELEASE-p2 i386
>Organization:
Toshiba Corporation / KAME Project
>Environment:
System: FreeBSD opera.isl.rdc.toshiba.co.jp 6.1-RELEASE-p2 FreeBSD 6.1-RELEASE-p2 #2: Tue Jul 4 20:29:29 JST 2006 jinmei at opera.isl.rdc.toshiba.co.jp:/local/usr.local/freebsd/src/sys/i386/compile/GENERIC i386
Intel Pentium 4 1.7GHZ, FreeBSD 6.1R, no particular patch
>Description:
If an AF_INET6 socket receives an empty packet with ancillary data
object, soreceive() will point to a bogus place in the socket buffer,
which can subsequenlty causes kernel panic. Such an empty packet
can be sent to the socket by the use of the IPv6 IPV6_RECVPATHMTU
socket option.
Any non-privileged user can (potentially) trigger this bug.
>How-To-Repeat:
Compile the following code, set the MTU of the loopback interface
to some small value (e.g., 1500) by
# ifconfig lo0 mtu 1500
and then run this program.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
main() {
int cc, s, on, error;
char buf[4096];
struct addrinfo *res, hints;
struct sockaddr_in6 from;
socklen_t fromlen;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
getaddrinfo("::1", "5000", &hints, &res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
on = 1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU, &on, sizeof(on))
!= 0) {
perror("setsockopt(IPV6_RECVPATHMTU)");
exit(1);
}
on = 1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG, &on, sizeof(on)) != 0) {
perror("setsockopt(IPV6_DONTFRAG)");
exit(1);
}
if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
perror("bind");
exit(1);
}
cc = sendto(s, buf, sizeof(buf), 0, res->ai_addr, res->ai_addrlen);
if (cc < 0)
perror("sendto");
fromlen = sizeof(from);
cc = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from,
&fromlen);
if (cc < 0)
perror("recvfrom");
exit(0);
}
>Fix:
A patch that fixes the problem is attached below. FreeBSD 5.x also seems
to have the same bug.
--- uipc_socket.c Tue Jul 4 20:29:16 2006
+++ uipc_socket.c.new Mon Jul 3 14:04:42 2006
@@ -1169,7 +1169,10 @@
}
cm = cmn;
}
- nextrecord = so->so_rcv.sb_mb->m_nextpkt;
+ if (m != NULL)
+ nextrecord = so->so_rcv.sb_mb->m_nextpkt;
+ else
+ nextrecord = so->so_rcv.sb_mb;
orig_resid = 0;
}
if (m != NULL) {
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list