Skip to content

Commit 9a99d4a

Browse files
Cong Wangdavem330
authored andcommitted
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>
1 parent 08578d8 commit 9a99d4a

File tree

1 file changed

+23
-17
lines changed

1 file changed

+23
-17
lines changed

net/ipv4/icmp.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
482482
{
483483
struct iphdr *iph;
484484
int room;
485-
struct icmp_bxm icmp_param;
485+
struct icmp_bxm *icmp_param;
486486
struct rtable *rt = skb_rtable(skb_in);
487487
struct ipcm_cookie ipc;
488488
struct flowi4 fl4;
@@ -558,9 +558,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
558558
}
559559
}
560560

561+
icmp_param = kmalloc(sizeof(*icmp_param), GFP_ATOMIC);
562+
if (!icmp_param)
563+
return;
564+
561565
sk = icmp_xmit_lock(net);
562566
if (sk == NULL)
563-
return;
567+
goto out_free;
564568

565569
/*
566570
* Construct source address and options.
@@ -586,27 +590,27 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
586590
IPTOS_PREC_INTERNETCONTROL) :
587591
iph->tos;
588592

589-
if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
593+
if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb_in))
590594
goto out_unlock;
591595

592596

593597
/*
594598
* Prepare data for ICMP header.
595599
*/
596600

597-
icmp_param.data.icmph.type = type;
598-
icmp_param.data.icmph.code = code;
599-
icmp_param.data.icmph.un.gateway = info;
600-
icmp_param.data.icmph.checksum = 0;
601-
icmp_param.skb = skb_in;
602-
icmp_param.offset = skb_network_offset(skb_in);
601+
icmp_param->data.icmph.type = type;
602+
icmp_param->data.icmph.code = code;
603+
icmp_param->data.icmph.un.gateway = info;
604+
icmp_param->data.icmph.checksum = 0;
605+
icmp_param->skb = skb_in;
606+
icmp_param->offset = skb_network_offset(skb_in);
603607
inet_sk(sk)->tos = tos;
604608
ipc.addr = iph->saddr;
605-
ipc.opt = &icmp_param.replyopts.opt;
609+
ipc.opt = &icmp_param->replyopts.opt;
606610
ipc.tx_flags = 0;
607611

608612
rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
609-
type, code, &icmp_param);
613+
type, code, icmp_param);
610614
if (IS_ERR(rt))
611615
goto out_unlock;
612616

@@ -618,19 +622,21 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
618622
room = dst_mtu(&rt->dst);
619623
if (room > 576)
620624
room = 576;
621-
room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
625+
room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.opt.optlen;
622626
room -= sizeof(struct icmphdr);
623627

624-
icmp_param.data_len = skb_in->len - icmp_param.offset;
625-
if (icmp_param.data_len > room)
626-
icmp_param.data_len = room;
627-
icmp_param.head_len = sizeof(struct icmphdr);
628+
icmp_param->data_len = skb_in->len - icmp_param->offset;
629+
if (icmp_param->data_len > room)
630+
icmp_param->data_len = room;
631+
icmp_param->head_len = sizeof(struct icmphdr);
628632

629-
icmp_push_reply(&icmp_param, &fl4, &ipc, &rt);
633+
icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
630634
ende:
631635
ip_rt_put(rt);
632636
out_unlock:
633637
icmp_xmit_unlock(sk);
638+
out_free:
639+
kfree(icmp_param);
634640
out:;
635641
}
636642
EXPORT_SYMBOL(icmp_send);

0 commit comments

Comments
 (0)