]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
[net/sfc] limit number of segments per skb on tx
authorMaxim Uvarov <maxim.uvarov@oracle.com>
Thu, 18 Oct 2012 17:43:58 +0000 (10:43 -0700)
committerMaxim Uvarov <maxim.uvarov@oracle.com>
Thu, 18 Oct 2012 18:23:11 +0000 (11:23 -0700)
Orabug: 14769994
This fixes: CVE-2012-3412
The kernels have 5b6262d0ccf759a16fabe11d904a2531125a4b71 (sfc: Replace
some literal constants with EFX_PAGE_SIZE/EFX_BUF_SIZE) and
7e6d06f0de3f74ca929441add094518ae332257c (sfc: Fix maximum number of TSO
segments and minimum TX queue size) from upstream but the upstream
version relies on the TCP layer limiting the maximum number of GSO
segments which isn't in UEK.  30b678d844af3305cda5953467005cebb5d7b687
(net: Allow driver to limit number of GSO segments per skb) provided
this in mainline. Instead of modifing network stack we fix add additional
check to efx_enqueue_skb_tso().
Signed-off-by: Maxim Uvarov <maxim.uvarov@oracle.com>
drivers/net/sfc/tx.c

index 6d3b68a8478c83d45bcba895c82f5ecbde674388..aa51c0957113153368af3f35d5261ca3096adbfc 100644 (file)
@@ -1132,6 +1132,21 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
        int frag_i, rc, rc2 = NETDEV_TX_OK;
        struct tso_state state;
 
+       /* Since the stack does not limit the number of segments per
+        * skb, we must do so.  Otherwise an attacker may be able to
+        * make the TCP produce skbs that will never fit in our TX
+        * queue, causing repeated resets.
+        */
+       if (unlikely(skb_shinfo(skb)->gso_segs > EFX_TSO_MAX_SEGS)) {
+               unsigned int excess =
+                       (skb_shinfo(skb)->gso_segs - EFX_TSO_MAX_SEGS) *
+                       skb_shinfo(skb)->gso_size;
+               if (__pskb_trim(skb, skb->len - excess)) {
+                       dev_kfree_skb_any(skb);
+                       return NETDEV_TX_OK;
+               }
+       }
+
        /* Find the packet protocol and sanity-check it */
        state.protocol = efx_tso_check_protocol(skb);