diff options
author | glebius <glebius@FreeBSD.org> | 2016-01-14 10:11:10 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2016-01-14 10:11:10 +0000 |
commit | 51f55053b6565d2fe9b61f63460dddc23284a103 (patch) | |
tree | 236ea1e153963e1dfadb774eb356675d2e50d9e0 /sys/netinet6/sctp6_usrreq.c | |
parent | d697e9a3e47062061cf162a3fe8bff412f41dcc1 (diff) | |
download | FreeBSD-src-51f55053b6565d2fe9b61f63460dddc23284a103.zip FreeBSD-src-51f55053b6565d2fe9b61f63460dddc23284a103.tar.gz |
Verify the packet length in sctp6_input().
The sctp6_ctlinput() function does not properly check the length of the packet
it receives from the ICMP6 input routine. This means that an attacker can craft
a packet that will cause a kernel panic.
When the kernel receives an ICMP6 error message with one of the types/codes
it handles, it calls icmp6_notify_error() to deliver it to the upper-level
protocol. icmp6_notify_error() cycles through the extension headers (if any)
to find the protocol number of the first non-extension header. It does NOT
verify the length of the non-extension header.
It passes information about the packet (including the actual packet) to the
upper-level protocol's pr_ctlinput function. In the case of SCTP for IPv6,
icmp6_notify_error() calls sctp6_ctlinput().
sctp6_ctlinput() assumes that the incoming packet contains a sufficiently-long
SCTP header and calls m_copydata() to extract a copy of that header. In turn,
m_copydata() assumes that the caller has already verified that the offset and
length parameters are correct. If they are incorrect, it will dereference a
NULL pointer and cause a kernel panic.
In short, no one is sufficiently verifying the input, and the result is a
kernel panic.
Submitted by: jtl
Security: SA-16:01.sctp
Diffstat (limited to 'sys/netinet6/sctp6_usrreq.c')
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 43df06e..40c1b41 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -379,7 +379,6 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d) * XXX: We assume that when IPV6 is non NULL, M and OFF are * valid. */ - /* check if we can safely examine src and dst ports */ struct sctp_inpcb *inp = NULL; struct sctp_tcb *stcb = NULL; struct sctp_nets *net = NULL; @@ -388,6 +387,10 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d) if (ip6cp->ip6c_m == NULL) return; + /* Check if we can safely examine the SCTP header. */ + if (ip6cp->ip6c_m->m_pkthdr.len < ip6cp->ip6c_off + sizeof(sh)) + return; + bzero(&sh, sizeof(sh)); bzero(&final, sizeof(final)); inp = NULL; |