Commit 50269e19 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net: add a truesize parameter to skb_add_rx_frag()

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: default avatarEric Dumazet <eric.dumazet@gmail.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0015e551
...@@ -164,12 +164,14 @@ static void rx_complete(struct urb *req) ...@@ -164,12 +164,14 @@ static void rx_complete(struct urb *req)
/* Can't use pskb_pull() on page in IRQ */ /* Can't use pskb_pull() on page in IRQ */
memcpy(skb_put(skb, 1), page_address(page), 1); memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, 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; page = NULL;
} }
} else { } else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, 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; page = NULL;
} }
if (req->actual_length < PAGE_SIZE) if (req->actual_length < PAGE_SIZE)
......
...@@ -499,7 +499,8 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, ...@@ -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); le32_to_cpu(rx_end->status), stats);
skb_add_rx_frag(skb, 0, rxb->page, 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); il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
......
...@@ -596,7 +596,8 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, ...@@ -596,7 +596,8 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
return; 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); il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
......
...@@ -796,7 +796,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, ...@@ -796,7 +796,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
offset = (void *)hdr - rxb_addr(rxb); offset = (void *)hdr - rxb_addr(rxb);
p = rxb_steal_page(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); iwl_update_stats(priv, false, fc, len);
......
...@@ -345,7 +345,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -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_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
skb->len <= 1, req->actual); skb->len <= 1, req->actual, req->actual);
page = NULL; page = NULL;
if (req->actual < req->length) { /* Last fragment */ if (req->actual < req->length) { /* Last fragment */
......
...@@ -1244,7 +1244,7 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i, ...@@ -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, 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_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags)
#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb)) #define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb))
......
...@@ -321,12 +321,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, ...@@ -321,12 +321,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
EXPORT_SYMBOL(__netdev_alloc_skb); EXPORT_SYMBOL(__netdev_alloc_skb);
void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, 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_fill_page_desc(skb, i, page, off, size);
skb->len += size; skb->len += size;
skb->data_len += size; skb->data_len += size;
skb->truesize += size; skb->truesize += truesize;
} }
EXPORT_SYMBOL(skb_add_rx_frag); EXPORT_SYMBOL(skb_add_rx_frag);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment