aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/icmp.c
diff options
context:
space:
mode:
authorCong Wang <amwang@redhat.com>2013-06-02 11:00:52 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-03 03:28:44 -0400
commit9a99d4a50cb8ce516adf0f2436138d4c8e6e4535 (patch)
treef8854a80373f9288f1ee27a8d0ab54d46b256a57 /net/ipv4/icmp.c
parent08578d8d4eb76b7afe314fa03abe167761462fe4 (diff)
icmp: avoid allocating large struct on stack
struct icmp_bxm is a large struct, reduce stack usage by allocating it on heap. Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Joe Perches <joe@perches.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <amwang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r--net/ipv4/icmp.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 2864ca33bedc..5f7d11a45871 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -482,7 +482,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
482{ 482{
483 struct iphdr *iph; 483 struct iphdr *iph;
484 int room; 484 int room;
485 struct icmp_bxm icmp_param; 485 struct icmp_bxm *icmp_param;
486 struct rtable *rt = skb_rtable(skb_in); 486 struct rtable *rt = skb_rtable(skb_in);
487 struct ipcm_cookie ipc; 487 struct ipcm_cookie ipc;
488 struct flowi4 fl4; 488 struct flowi4 fl4;
@@ -558,9 +558,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
558 } 558 }
559 } 559 }
560 560
561 icmp_param = kmalloc(sizeof(*icmp_param), GFP_ATOMIC);
562 if (!icmp_param)
563 return;
564
561 sk = icmp_xmit_lock(net); 565 sk = icmp_xmit_lock(net);
562 if (sk == NULL) 566 if (sk == NULL)
563 return; 567 goto out_free;
564 568
565 /* 569 /*
566 * Construct source address and options. 570 * Construct source address and options.
@@ -586,7 +590,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
586 IPTOS_PREC_INTERNETCONTROL) : 590 IPTOS_PREC_INTERNETCONTROL) :
587 iph->tos; 591 iph->tos;
588 592
589 if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in)) 593 if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb_in))
590 goto out_unlock; 594 goto out_unlock;
591 595
592 596
@@ -594,19 +598,19 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
594 * Prepare data for ICMP header. 598 * Prepare data for ICMP header.
595 */ 599 */
596 600
597 icmp_param.data.icmph.type = type; 601 icmp_param->data.icmph.type = type;
598 icmp_param.data.icmph.code = code; 602 icmp_param->data.icmph.code = code;
599 icmp_param.data.icmph.un.gateway = info; 603 icmp_param->data.icmph.un.gateway = info;
600 icmp_param.data.icmph.checksum = 0; 604 icmp_param->data.icmph.checksum = 0;
601 icmp_param.skb = skb_in; 605 icmp_param->skb = skb_in;
602 icmp_param.offset = skb_network_offset(skb_in); 606 icmp_param->offset = skb_network_offset(skb_in);
603 inet_sk(sk)->tos = tos; 607 inet_sk(sk)->tos = tos;
604 ipc.addr = iph->saddr; 608 ipc.addr = iph->saddr;
605 ipc.opt = &icmp_param.replyopts.opt; 609 ipc.opt = &icmp_param->replyopts.opt;
606 ipc.tx_flags = 0; 610 ipc.tx_flags = 0;
607 611
608 rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, 612 rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
609 type, code, &icmp_param); 613 type, code, icmp_param);
610 if (IS_ERR(rt)) 614 if (IS_ERR(rt))
611 goto out_unlock; 615 goto out_unlock;
612 616
@@ -618,19 +622,21 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
618 room = dst_mtu(&rt->dst); 622 room = dst_mtu(&rt->dst);
619 if (room > 576) 623 if (room > 576)
620 room = 576; 624 room = 576;
621 room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; 625 room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.opt.optlen;
622 room -= sizeof(struct icmphdr); 626 room -= sizeof(struct icmphdr);
623 627
624 icmp_param.data_len = skb_in->len - icmp_param.offset; 628 icmp_param->data_len = skb_in->len - icmp_param->offset;
625 if (icmp_param.data_len > room) 629 if (icmp_param->data_len > room)
626 icmp_param.data_len = room; 630 icmp_param->data_len = room;
627 icmp_param.head_len = sizeof(struct icmphdr); 631 icmp_param->head_len = sizeof(struct icmphdr);
628 632
629 icmp_push_reply(&icmp_param, &fl4, &ipc, &rt); 633 icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
630ende: 634ende:
631 ip_rt_put(rt); 635 ip_rt_put(rt);
632out_unlock: 636out_unlock:
633 icmp_xmit_unlock(sk); 637 icmp_xmit_unlock(sk);
638out_free:
639 kfree(icmp_param);
634out:; 640out:;
635} 641}
636EXPORT_SYMBOL(icmp_send); 642EXPORT_SYMBOL(icmp_send);