mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									08578d8d4e
								
							
						
					
					
						commit
						9a99d4a50c
					
				
					 1 changed files with 23 additions and 17 deletions
				
			
		| 
						 | 
					@ -482,7 +482,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct iphdr *iph;
 | 
						struct iphdr *iph;
 | 
				
			||||||
	int room;
 | 
						int room;
 | 
				
			||||||
	struct icmp_bxm icmp_param;
 | 
						struct icmp_bxm *icmp_param;
 | 
				
			||||||
	struct rtable *rt = skb_rtable(skb_in);
 | 
						struct rtable *rt = skb_rtable(skb_in);
 | 
				
			||||||
	struct ipcm_cookie ipc;
 | 
						struct ipcm_cookie ipc;
 | 
				
			||||||
	struct flowi4 fl4;
 | 
						struct flowi4 fl4;
 | 
				
			||||||
| 
						 | 
					@ -558,9 +558,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						icmp_param = kmalloc(sizeof(*icmp_param), GFP_ATOMIC);
 | 
				
			||||||
 | 
						if (!icmp_param)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sk = icmp_xmit_lock(net);
 | 
						sk = icmp_xmit_lock(net);
 | 
				
			||||||
	if (sk == NULL)
 | 
						if (sk == NULL)
 | 
				
			||||||
		return;
 | 
							goto out_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 *	Construct source address and options.
 | 
						 *	Construct source address and options.
 | 
				
			||||||
| 
						 | 
					@ -586,7 +590,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
				
			||||||
					   IPTOS_PREC_INTERNETCONTROL) :
 | 
										   IPTOS_PREC_INTERNETCONTROL) :
 | 
				
			||||||
					  iph->tos;
 | 
										  iph->tos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
 | 
						if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb_in))
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -594,19 +598,19 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
				
			||||||
	 *	Prepare data for ICMP header.
 | 
						 *	Prepare data for ICMP header.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	icmp_param.data.icmph.type	 = type;
 | 
						icmp_param->data.icmph.type	 = type;
 | 
				
			||||||
	icmp_param.data.icmph.code	 = code;
 | 
						icmp_param->data.icmph.code	 = code;
 | 
				
			||||||
	icmp_param.data.icmph.un.gateway = info;
 | 
						icmp_param->data.icmph.un.gateway = info;
 | 
				
			||||||
	icmp_param.data.icmph.checksum	 = 0;
 | 
						icmp_param->data.icmph.checksum	 = 0;
 | 
				
			||||||
	icmp_param.skb	  = skb_in;
 | 
						icmp_param->skb	  = skb_in;
 | 
				
			||||||
	icmp_param.offset = skb_network_offset(skb_in);
 | 
						icmp_param->offset = skb_network_offset(skb_in);
 | 
				
			||||||
	inet_sk(sk)->tos = tos;
 | 
						inet_sk(sk)->tos = tos;
 | 
				
			||||||
	ipc.addr = iph->saddr;
 | 
						ipc.addr = iph->saddr;
 | 
				
			||||||
	ipc.opt = &icmp_param.replyopts.opt;
 | 
						ipc.opt = &icmp_param->replyopts.opt;
 | 
				
			||||||
	ipc.tx_flags = 0;
 | 
						ipc.tx_flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
 | 
						rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
 | 
				
			||||||
			       type, code, &icmp_param);
 | 
								       type, code, icmp_param);
 | 
				
			||||||
	if (IS_ERR(rt))
 | 
						if (IS_ERR(rt))
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -618,19 +622,21 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
				
			||||||
	room = dst_mtu(&rt->dst);
 | 
						room = dst_mtu(&rt->dst);
 | 
				
			||||||
	if (room > 576)
 | 
						if (room > 576)
 | 
				
			||||||
		room = 576;
 | 
							room = 576;
 | 
				
			||||||
	room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
 | 
						room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.opt.optlen;
 | 
				
			||||||
	room -= sizeof(struct icmphdr);
 | 
						room -= sizeof(struct icmphdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	icmp_param.data_len = skb_in->len - icmp_param.offset;
 | 
						icmp_param->data_len = skb_in->len - icmp_param->offset;
 | 
				
			||||||
	if (icmp_param.data_len > room)
 | 
						if (icmp_param->data_len > room)
 | 
				
			||||||
		icmp_param.data_len = room;
 | 
							icmp_param->data_len = room;
 | 
				
			||||||
	icmp_param.head_len = sizeof(struct icmphdr);
 | 
						icmp_param->head_len = sizeof(struct icmphdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	icmp_push_reply(&icmp_param, &fl4, &ipc, &rt);
 | 
						icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
 | 
				
			||||||
ende:
 | 
					ende:
 | 
				
			||||||
	ip_rt_put(rt);
 | 
						ip_rt_put(rt);
 | 
				
			||||||
out_unlock:
 | 
					out_unlock:
 | 
				
			||||||
	icmp_xmit_unlock(sk);
 | 
						icmp_xmit_unlock(sk);
 | 
				
			||||||
 | 
					out_free:
 | 
				
			||||||
 | 
						kfree(icmp_param);
 | 
				
			||||||
out:;
 | 
					out:;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(icmp_send);
 | 
					EXPORT_SYMBOL(icmp_send);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue