We have moved to a new Sailfish OS Forum. Please start new discussions there.

Revision history [back]

click to hide/show revision 1
initial version

posted 2018-03-06 10:19:14 +0200

take care of truncations done by sk_filter() in kernel-net-tcp CVE-2016-8645

The TCP stack in the Linux kernel before 4.8.10 mishandles skb truncation, which allows local users to cause a denial of service (system crash) via a crafted application that makes sendto system calls, related to net/ipv4/tcp_ipv4.c and net/ipv6/tcp_ipv6.c.

Suitable Kernel-3.2 backport [bwh: Backported to 3.2: adjust context] is available.

Files affected: kernel-adaptation-sbj-3.4.108.20161101.1/include/net/tcp.h lines 974-978

kernel-adaptation-sbj-3.4.108.20161101.1/net/ipv4/tcp_ipv4.c lines 1656-1661; 1718-1724

kernel-adaptation-sbj-3.4.108.20161101.1/net/ipv6/tcp_ipv6.c lines 1480-1486; 1640-1646

Patch should look like:

tcp.h:

@@ -974,6 +974,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
return 1;
 }

+    int tcp_filter(struct sock *sk, struct sk_buff *skb);

 #undef STATE_TRACE

tcp_ipv4.c:

 @@ -1656,6 +1656,21 @@ csum_err:
 }
 EXPORT_SYMBOL(tcp_v4_do_rcv);

+int tcp_filter(struct sock *sk, struct sk_buff *skb)
+{
+   struct tcphdr *th = (struct tcphdr *)skb->data;
+   unsigned int eaten = skb->len;
+   int err;
+
+   err = sk_filter_trim_cap(sk, skb, th->doff * 4);
+   if (!err) {
+       eaten -= skb->len;
+       TCP_SKB_CB(skb)->end_seq -= eaten;
+   }
+   return err;
+}
+EXPORT_SYMBOL(tcp_filter);
+
 /*
  * From tcp_input.c
  */
@@ -1718,8 +1733,10 @@ process:
    goto discard_and_relse;
nf_reset(skb);

-   if (sk_filter(sk, skb))
+   if (tcp_filter(sk, skb))
    goto discard_and_relse;
+   th = (const struct tcphdr *)skb->data;
+   iph = ip_hdr(skb);

skb->dev = NULL;

tcp_ipv6.c:

@@ -1480,7 +1480,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
    goto discard;
 #endif

-   if (sk_filter(sk, skb))
+   if (tcp_filter(sk, skb))
    goto discard;

/*
@@ -1640,8 +1640,10 @@ process:
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
    goto discard_and_relse;

-   if (sk_filter(sk, skb))
+   if (tcp_filter(sk, skb))
    goto discard_and_relse;
+   th = (const struct tcphdr *)skb->data;
+   hdr = ipv6_hdr(skb);

skb->dev = NULL;