net: add a truesize parameter to skb_add_rx_frag()
authorEric Dumazet <eric.dumazet@gmail.com>
Fri, 23 Mar 2012 23:59:33 +0000 (23:59 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 25 Mar 2012 17:29:58 +0000 (13:29 -0400)
skb_add_rx_frag() API is misleading.

Network skbs built with this helper can use uncharged kernel memory and
eventually stress/crash machine in OOM.

Add a 'truesize' parameter and then fix drivers in followup patches.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/usb/cdc-phonet.c
drivers/net/wireless/iwlegacy/3945.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
drivers/usb/gadget/f_phonet.c
include/linux/skbuff.h
net/core/skbuff.c

index 790cbdea739237758c5bc68137d6c44a9c4d7e2e..3886b30ed37355394e6155f60bb7e559e598391e 100644 (file)
@@ -164,12 +164,14 @@ static void rx_complete(struct urb *req)
                                /* Can't use pskb_pull() on page in IRQ */
                                memcpy(skb_put(skb, 1), page_address(page), 1);
                                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-                                               page, 1, req->actual_length);
+                                               page, 1, req->actual_length,
+                                               req->actual_length);
                                page = NULL;
                        }
                } else {
                        skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-                                       page, 0, req->actual_length);
+                                       page, 0, req->actual_length,
+                                       req->actual_length);
                        page = NULL;
                }
                if (req->actual_length < PAGE_SIZE)
index c5b1d199e0bc9b8cd154f2b217994b684cbbba06..b25c01be0d90c4ad06b833d00bf2d3a5132273e3 100644 (file)
@@ -499,7 +499,8 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
                                      le32_to_cpu(rx_end->status), stats);
 
        skb_add_rx_frag(skb, 0, rxb->page,
-                       (void *)rx_hdr->payload - (void *)pkt, len);
+                       (void *)rx_hdr->payload - (void *)pkt, len,
+                       len);
 
        il_update_stats(il, false, fc, len);
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
index 7b54dbb338be6127bec123f8414cd3231eaabb00..17f1c6853182d23ddfb092c3d0e7787a04ce0731 100644 (file)
@@ -596,7 +596,8 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
                return;
        }
 
-       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len,
+                       len);
 
        il_update_stats(il, false, fc, len);
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
index 44c6f712b77d5f9b5a39359ff7e5e17c86e7b9ab..f4b84d1596e3cd62cc44bea717bf9bc0eb59c3cc 100644 (file)
@@ -796,7 +796,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
 
        offset = (void *)hdr - rxb_addr(rxb);
        p = rxb_steal_page(rxb);
-       skb_add_rx_frag(skb, 0, p, offset, len);
+       skb_add_rx_frag(skb, 0, p, offset, len, len);
 
        iwl_update_stats(priv, false, fc, len);
 
index 7cdcb63b21ff6b3605591d87de5d413bc470c61e..85a5cebe96b3635fb521d648f937c7e938e7a6c2 100644 (file)
@@ -345,7 +345,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
                }
 
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
-                               skb->len <= 1, req->actual);
+                               skb->len <= 1, req->actual, req->actual);
                page = NULL;
 
                if (req->actual < req->length) { /* Last fragment */
index a2b9953b582d9a3f69a97fe31b084a43a2a6a3bd..681a18799140339a0cc5520c45c09ee56d8491c2 100644 (file)
@@ -1244,7 +1244,7 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
 }
 
 extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
-                           int off, int size);
+                           int off, int size, unsigned int truesize);
 
 #define SKB_PAGE_ASSERT(skb)   BUG_ON(skb_shinfo(skb)->nr_frags)
 #define SKB_FRAG_ASSERT(skb)   BUG_ON(skb_has_frag_list(skb))
index 6eb656acdfe53a27680c894b5cd8a6a7222f2db1..a690cae91cdd14641b61844f6ac1f903fbf9666e 100644 (file)
@@ -321,12 +321,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
 EXPORT_SYMBOL(__netdev_alloc_skb);
 
 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
-               int size)
+                    int size, unsigned int truesize)
 {
        skb_fill_page_desc(skb, i, page, off, size);
        skb->len += size;
        skb->data_len += size;
-       skb->truesize += size;
+       skb->truesize += truesize;
 }
 EXPORT_SYMBOL(skb_add_rx_frag);