You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.1 KiB
66 lines
2.1 KiB
From c562b61ed91605dc0c5790aaf2df09b566df77b6 Mon Sep 17 00:00:00 2001
|
|
From: Ben Pfaff <blp@ovn.org>
|
|
Date: Fri, 3 Mar 2017 21:16:17 -0800
|
|
Subject: [PATCH] conntrack: Fix checks for TCP, UDP, and IPv6 header sizes.
|
|
|
|
Otherwise a malformed packet could cause a read up to about 40 bytes past
|
|
the end of the packet. The packet would still likely be dropped because
|
|
of checksum verification.
|
|
|
|
Reported-by: Bhargava Shastry <bshastry@sec.t-labs.tu-berlin.de>
|
|
Signed-off-by: Ben Pfaff <blp@ovn.org>
|
|
Acked-by: Daniele Di Proietto <diproiettod@vmware.com>
|
|
---
|
|
lib/conntrack.c | 16 +++++++++++-----
|
|
1 file changed, 11 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/lib/conntrack.c b/lib/conntrack.c
|
|
index 9bea3d93e4..677c0d2a3c 100644
|
|
--- a/lib/conntrack.c
|
|
+++ b/lib/conntrack.c
|
|
@@ -568,15 +568,15 @@ extract_l3_ipv6(struct conn_key *key, const void *data, size_t size,
|
|
const char **new_data)
|
|
{
|
|
const struct ovs_16aligned_ip6_hdr *ip6 = data;
|
|
- uint8_t nw_proto = ip6->ip6_nxt;
|
|
- uint8_t nw_frag = 0;
|
|
-
|
|
if (new_data) {
|
|
if (OVS_UNLIKELY(size < sizeof *ip6)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
+ uint8_t nw_proto = ip6->ip6_nxt;
|
|
+ uint8_t nw_frag = 0;
|
|
+
|
|
data = ip6 + 1;
|
|
size -= sizeof *ip6;
|
|
|
|
@@ -623,8 +623,11 @@ check_l4_tcp(const struct conn_key *key, const void *data, size_t size,
|
|
const void *l3)
|
|
{
|
|
const struct tcp_header *tcp = data;
|
|
- size_t tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
|
|
+ if (size < sizeof *tcp) {
|
|
+ return false;
|
|
+ }
|
|
|
|
+ size_t tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
|
|
if (OVS_UNLIKELY(tcp_len < TCP_HEADER_LEN || tcp_len > size)) {
|
|
return false;
|
|
}
|
|
@@ -637,8 +640,11 @@ check_l4_udp(const struct conn_key *key, const void *data, size_t size,
|
|
const void *l3)
|
|
{
|
|
const struct udp_header *udp = data;
|
|
- size_t udp_len = ntohs(udp->udp_len);
|
|
+ if (size < sizeof *udp) {
|
|
+ return false;
|
|
+ }
|
|
|
|
+ size_t udp_len = ntohs(udp->udp_len);
|
|
if (OVS_UNLIKELY(udp_len < UDP_HEADER_LEN || udp_len > size)) {
|
|
return false;
|
|
}
|