diff mbox

[ovs-dev,v2] conntrack: Fix checks for TCP, UDP, and IPv6 header sizes.

Message ID 20170304051845.24737-1-blp@ovn.org
State Accepted
Headers show

Commit Message

Ben Pfaff March 4, 2017, 5:18 a.m. UTC
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>
---
v1->v2: Eliminate duplicate check in extract_l3_ipv6().  Thanks Daniele!

 lib/conntrack.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

Comments

Daniele Di Proietto March 6, 2017, 7 p.m. UTC | #1
2017-03-03 21:18 GMT-08:00 Ben Pfaff <blp@ovn.org>:
> 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>

> ---
> v1->v2: Eliminate duplicate check in extract_l3_ipv6().  Thanks Daniele!
>
>  lib/conntrack.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/lib/conntrack.c b/lib/conntrack.c
> index 9bea3d93e4ad..677c0d2a3cdc 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;
>      }
> --
> 2.10.2
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Ben Pfaff March 6, 2017, 10:02 p.m. UTC | #2
On Mon, Mar 06, 2017 at 11:00:05AM -0800, Daniele Di Proietto wrote:
> 2017-03-03 21:18 GMT-08:00 Ben Pfaff <blp@ovn.org>:
> > 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>

Thanks, applied to master, branch-2.7, branch-2.6.
diff mbox

Patch

diff --git a/lib/conntrack.c b/lib/conntrack.c
index 9bea3d93e4ad..677c0d2a3cdc 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;
     }