aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_fragment.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r--net/ipv4/ip_fragment.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index eb9d63a570cd..b6d30acb600c 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -122,7 +122,7 @@ int ip_frag_nqueues(struct net *net)
122 122
123int ip_frag_mem(struct net *net) 123int ip_frag_mem(struct net *net)
124{ 124{
125 return atomic_read(&net->ipv4.frags.mem); 125 return sum_frag_mem_limit(&net->ipv4.frags);
126} 126}
127 127
128static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, 128static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
@@ -161,13 +161,6 @@ static bool ip4_frag_match(struct inet_frag_queue *q, void *a)
161 qp->user == arg->user; 161 qp->user == arg->user;
162} 162}
163 163
164/* Memory Tracking Functions. */
165static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
166{
167 atomic_sub(skb->truesize, &nf->mem);
168 kfree_skb(skb);
169}
170
171static void ip4_frag_init(struct inet_frag_queue *q, void *a) 164static void ip4_frag_init(struct inet_frag_queue *q, void *a)
172{ 165{
173 struct ipq *qp = container_of(q, struct ipq, q); 166 struct ipq *qp = container_of(q, struct ipq, q);
@@ -340,6 +333,7 @@ static inline int ip_frag_too_far(struct ipq *qp)
340static int ip_frag_reinit(struct ipq *qp) 333static int ip_frag_reinit(struct ipq *qp)
341{ 334{
342 struct sk_buff *fp; 335 struct sk_buff *fp;
336 unsigned int sum_truesize = 0;
343 337
344 if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) { 338 if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) {
345 atomic_inc(&qp->q.refcnt); 339 atomic_inc(&qp->q.refcnt);
@@ -349,9 +343,12 @@ static int ip_frag_reinit(struct ipq *qp)
349 fp = qp->q.fragments; 343 fp = qp->q.fragments;
350 do { 344 do {
351 struct sk_buff *xp = fp->next; 345 struct sk_buff *xp = fp->next;
352 frag_kfree_skb(qp->q.net, fp); 346
347 sum_truesize += fp->truesize;
348 kfree_skb(fp);
353 fp = xp; 349 fp = xp;
354 } while (fp); 350 } while (fp);
351 sub_frag_mem_limit(&qp->q, sum_truesize);
355 352
356 qp->q.last_in = 0; 353 qp->q.last_in = 0;
357 qp->q.len = 0; 354 qp->q.len = 0;
@@ -496,7 +493,8 @@ found:
496 qp->q.fragments = next; 493 qp->q.fragments = next;
497 494
498 qp->q.meat -= free_it->len; 495 qp->q.meat -= free_it->len;
499 frag_kfree_skb(qp->q.net, free_it); 496 sub_frag_mem_limit(&qp->q, free_it->truesize);
497 kfree_skb(free_it);
500 } 498 }
501 } 499 }
502 500
@@ -519,7 +517,7 @@ found:
519 qp->q.stamp = skb->tstamp; 517 qp->q.stamp = skb->tstamp;
520 qp->q.meat += skb->len; 518 qp->q.meat += skb->len;
521 qp->ecn |= ecn; 519 qp->ecn |= ecn;
522 atomic_add(skb->truesize, &qp->q.net->mem); 520 add_frag_mem_limit(&qp->q, skb->truesize);
523 if (offset == 0) 521 if (offset == 0)
524 qp->q.last_in |= INET_FRAG_FIRST_IN; 522 qp->q.last_in |= INET_FRAG_FIRST_IN;
525 523
@@ -531,9 +529,7 @@ found:
531 qp->q.meat == qp->q.len) 529 qp->q.meat == qp->q.len)
532 return ip_frag_reasm(qp, prev, dev); 530 return ip_frag_reasm(qp, prev, dev);
533 531
534 write_lock(&ip4_frags.lock); 532 inet_frag_lru_move(&qp->q);
535 list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list);
536 write_unlock(&ip4_frags.lock);
537 return -EINPROGRESS; 533 return -EINPROGRESS;
538 534
539err: 535err:
@@ -594,7 +590,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
594 goto out_oversize; 590 goto out_oversize;
595 591
596 /* Head of list must not be cloned. */ 592 /* Head of list must not be cloned. */
597 if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) 593 if (skb_unclone(head, GFP_ATOMIC))
598 goto out_nomem; 594 goto out_nomem;
599 595
600 /* If the first fragment is fragmented itself, we split 596 /* If the first fragment is fragmented itself, we split
@@ -617,7 +613,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
617 head->len -= clone->len; 613 head->len -= clone->len;
618 clone->csum = 0; 614 clone->csum = 0;
619 clone->ip_summed = head->ip_summed; 615 clone->ip_summed = head->ip_summed;
620 atomic_add(clone->truesize, &qp->q.net->mem); 616 add_frag_mem_limit(&qp->q, clone->truesize);
621 } 617 }
622 618
623 skb_push(head, head->data - skb_network_header(head)); 619 skb_push(head, head->data - skb_network_header(head));
@@ -645,7 +641,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
645 } 641 }
646 fp = next; 642 fp = next;
647 } 643 }
648 atomic_sub(sum_truesize, &qp->q.net->mem); 644 sub_frag_mem_limit(&qp->q, sum_truesize);
649 645
650 head->next = NULL; 646 head->next = NULL;
651 head->dev = dev; 647 head->dev = dev;
@@ -851,14 +847,22 @@ static inline void ip4_frags_ctl_register(void)
851 847
852static int __net_init ipv4_frags_init_net(struct net *net) 848static int __net_init ipv4_frags_init_net(struct net *net)
853{ 849{
854 /* 850 /* Fragment cache limits.
855 * Fragment cache limits. We will commit 256K at one time. Should we 851 *
856 * cross that limit we will prune down to 192K. This should cope with 852 * The fragment memory accounting code, (tries to) account for
857 * even the most extreme cases without allowing an attacker to 853 * the real memory usage, by measuring both the size of frag
858 * measurably harm machine performance. 854 * queue struct (inet_frag_queue (ipv4:ipq/ipv6:frag_queue))
855 * and the SKB's truesize.
856 *
857 * A 64K fragment consumes 129736 bytes (44*2944)+200
858 * (1500 truesize == 2944, sizeof(struct ipq) == 200)
859 *
860 * We will commit 4MB at one time. Should we cross that limit
861 * we will prune down to 3MB, making room for approx 8 big 64K
862 * fragments 8x128k.
859 */ 863 */
860 net->ipv4.frags.high_thresh = 256 * 1024; 864 net->ipv4.frags.high_thresh = 4 * 1024 * 1024;
861 net->ipv4.frags.low_thresh = 192 * 1024; 865 net->ipv4.frags.low_thresh = 3 * 1024 * 1024;
862 /* 866 /*
863 * Important NOTE! Fragment queue must be destroyed before MSL expires. 867 * Important NOTE! Fragment queue must be destroyed before MSL expires.
864 * RFC791 is wrong proposing to prolongate timer each fragment arrival 868 * RFC791 is wrong proposing to prolongate timer each fragment arrival