diff mbox

net: gre: don't pull skb if dealing with icmp message

Message ID 52DB8E4A.7050809@cn.fujitsu.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Duan Jiong Jan. 19, 2014, 8:35 a.m. UTC
When dealing with icmp messages, the skb->data points the
ip header that triggered the sending of the icmp message.

In gre_cisco_err(), the parse_gre_header() is called, and the
iptunnel_pull_header() is called to pull the skb at the end of
the parse_gre_header(). Unfortunately, the ipgre_err still needs
the skb->data points the ip header following the icmp layer,
and those ip addresses in ip header will be used to look up
tunnel by ip_tunnel_lookup().

Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
 net/ipv4/gre_demux.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Comments

Pravin B Shelar Jan. 19, 2014, 9:08 p.m. UTC | #1
On Sun, Jan 19, 2014 at 12:35 AM, Duan Jiong <duanj.fnst@cn.fujitsu.com> wrote:
>
> When dealing with icmp messages, the skb->data points the
> ip header that triggered the sending of the icmp message.
>
> In gre_cisco_err(), the parse_gre_header() is called, and the
> iptunnel_pull_header() is called to pull the skb at the end of
> the parse_gre_header(). Unfortunately, the ipgre_err still needs
> the skb->data points the ip header following the icmp layer,
> and those ip addresses in ip header will be used to look up
> tunnel by ip_tunnel_lookup().
>
This looks like bug.
Can you use ip_hdr() rather than skb->data in ipgre_err().
Same is done in ipgre_rcv().
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Duan Jiong Jan. 20, 2014, 1:37 a.m. UTC | #2
于 2014年01月20日 05:08, Pravin Shelar 写道:
> On Sun, Jan 19, 2014 at 12:35 AM, Duan Jiong <duanj.fnst@cn.fujitsu.com> wrote:
>>
>> When dealing with icmp messages, the skb->data points the
>> ip header that triggered the sending of the icmp message.
>>
>> In gre_cisco_err(), the parse_gre_header() is called, and the
>> iptunnel_pull_header() is called to pull the skb at the end of
>> the parse_gre_header(). Unfortunately, the ipgre_err still needs
>> the skb->data points the ip header following the icmp layer,
>> and those ip addresses in ip header will be used to look up
>> tunnel by ip_tunnel_lookup().
>>
> This looks like bug.
> Can you use ip_hdr() rather than skb->data in ipgre_err().
> Same is done in ipgre_rcv().

That's maybe not a good idea. The ip_hdr() will the return the outmost
ip header, but we need inner ip header following the icmp layer.

Thanks,
  Duan

> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pravin B Shelar Jan. 21, 2014, 6:27 p.m. UTC | #3
On Sun, Jan 19, 2014 at 5:37 PM, Duan Jiong <duanj.fnst@cn.fujitsu.com> wrote:
> 于 2014年01月20日 05:08, Pravin Shelar 写道:
>> On Sun, Jan 19, 2014 at 12:35 AM, Duan Jiong <duanj.fnst@cn.fujitsu.com> wrote:
>>>
>>> When dealing with icmp messages, the skb->data points the
>>> ip header that triggered the sending of the icmp message.
>>>
>>> In gre_cisco_err(), the parse_gre_header() is called, and the
>>> iptunnel_pull_header() is called to pull the skb at the end of
>>> the parse_gre_header(). Unfortunately, the ipgre_err still needs
>>> the skb->data points the ip header following the icmp layer,
>>> and those ip addresses in ip header will be used to look up
>>> tunnel by ip_tunnel_lookup().
>>>
>> This looks like bug.
>> Can you use ip_hdr() rather than skb->data in ipgre_err().
>> Same is done in ipgre_rcv().
>
> That's maybe not a good idea. The ip_hdr() will the return the outmost
> ip header, but we need inner ip header following the icmp layer.
>
Why do you want to use inner ip header?
If you want to really look at original packet header, you can
calculate it from outer iph header rather than changing fast path
parse_gre_header() function.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Jan. 22, 2014, 12:49 a.m. UTC | #4
From: Duan Jiong <duanj.fnst@cn.fujitsu.com>
Date: Sun, 19 Jan 2014 16:35:22 +0800

> 
> When dealing with icmp messages, the skb->data points the
> ip header that triggered the sending of the icmp message.
> 
> In gre_cisco_err(), the parse_gre_header() is called, and the
> iptunnel_pull_header() is called to pull the skb at the end of
> the parse_gre_header(). Unfortunately, the ipgre_err still needs
> the skb->data points the ip header following the icmp layer,
> and those ip addresses in ip header will be used to look up
> tunnel by ip_tunnel_lookup().
> 
> Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>

Conditional pulling of headers based upon caller context leads to
impossible to maintain code.

Please find another way to fix this.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c
index 5893e99..35bfba4 100644
--- a/net/ipv4/gre_demux.c
+++ b/net/ipv4/gre_demux.c
@@ -116,7 +116,7 @@  static __sum16 check_checksum(struct sk_buff *skb)
 }
 
 static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
-			    bool *csum_err)
+			    bool *csum_err, bool in_err)
 {
 	unsigned int ip_hlen = ip_hdrlen(skb);
 	const struct gre_base_hdr *greh;
@@ -160,6 +160,9 @@  static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 	} else
 		tpi->seq = 0;
 
+	if (in_err)
+		return 0;
+
 	/* WCCP version 1 and 2 protocol decoding.
 	 * - Change protocol to IP
 	 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
@@ -182,7 +185,7 @@  static int gre_cisco_rcv(struct sk_buff *skb)
 	int i;
 	bool csum_err = false;
 
-	if (parse_gre_header(skb, &tpi, &csum_err) < 0)
+	if (parse_gre_header(skb, &tpi, &csum_err, false) < 0)
 		goto drop;
 
 	rcu_read_lock();
@@ -229,7 +232,7 @@  static void gre_cisco_err(struct sk_buff *skb, u32 info)
 	bool csum_err = false;
 	int i;
 
-	if (parse_gre_header(skb, &tpi, &csum_err)) {
+	if (parse_gre_header(skb, &tpi, &csum_err, true)) {
 		if (!csum_err)		/* ignore csum errors. */
 			return;
 	}