From: Haishuang Yan <hidden> Date: 2018-09-12 09:22:55
gre_parse_header stops parsing when csum_err is encountered, which means
tpi->key is undefined and ip_tunnel_lookup will return NULL improperly.
This patch introduce a NULL pointer as csum_err parameter. Even when
csum_err is encountered, it won't return error and continue parsing gre
header as expected.
Fixes: 9f57c67c379d ("gre: Remove support for sharing GRE protocol hook.")
Reported-by: Jiri Benc <redacted>
Signed-off-by: Haishuang Yan <redacted>
---
net/ipv4/gre_demux.c | 2 +-
net/ipv4/ip_gre.c | 9 +++------
2 files changed, 4 insertions(+), 7 deletions(-)
From: Haishuang Yan <hidden> Date: 2018-09-12 09:22:56
Same as ip_gre, use gre_parse_header to parse gre header in gre error
handler code.
Signed-off-by: Haishuang Yan <redacted>
---
net/ipv6/ip6_gre.c | 26 ++++----------------------
1 file changed, 4 insertions(+), 22 deletions(-)
@@ -86,7 +86,7 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, options = (__be32 *)(greh + 1); if (greh->flags & GRE_CSUM) {- if (skb_checksum_simple_validate(skb)) {+ if (csum_err && skb_checksum_simple_validate(skb)) { *csum_err = true; return -EINVAL; }
You want to ignore csum errors, but you do not want to elide the side
effects of the skb_checksum_simple_validate() call which are to set
skb->csum_valid and skb->csum.
Therefore, the skb_checksum_simple_validate() call still needs to be
performed. We just wont return -EINVAL in the NULL csum_err case.
options = (__be32 *)(greh + 1);
if (greh->flags & GRE_CSUM) {
- if (skb_checksum_simple_validate(skb)) {
+ if (csum_err && skb_checksum_simple_validate(skb)) {
*csum_err = true;
return -EINVAL;
}
You want to ignore csum errors, but you do not want to elide the side
effects of the skb_checksum_simple_validate() call which are to set
skb->csum_valid and skb->csum.
Therefore, the skb_checksum_simple_validate() call still needs to be
performed. We just wont return -EINVAL in the NULL csum_err case.
@@ -86,7 +86,7 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, options = (__be32 *)(greh + 1); if (greh->flags & GRE_CSUM) {- if (skb_checksum_simple_validate(skb)) {+ if (csum_err && skb_checksum_simple_validate(skb)) { *csum_err = true; return -EINVAL; }
You want to ignore csum errors, but you do not want to elide the side
effects of the skb_checksum_simple_validate() call which are to set
skb->csum_valid and skb->csum.
Therefore, the skb_checksum_simple_validate() call still needs to be
performed. We just wont return -EINVAL in the NULL csum_err case.
How about just reversing the order of the AND?
if (skb_checksum_simple_validate(skb) && csum_err) {
*csum_err = true;
return -EINVAL;
}
options = (__be32 *)(greh + 1);
if (greh->flags & GRE_CSUM) {
- if (skb_checksum_simple_validate(skb)) {
+ if (csum_err && skb_checksum_simple_validate(skb)) {
*csum_err = true;
return -EINVAL;
}
You want to ignore csum errors, but you do not want to elide the side
effects of the skb_checksum_simple_validate() call which are to set
skb->csum_valid and skb->csum.
Therefore, the skb_checksum_simple_validate() call still needs to be
performed. We just wont return -EINVAL in the NULL csum_err case.
How about just reversing the order of the AND?
if (skb_checksum_simple_validate(skb) && csum_err) {
*csum_err = true;
return -EINVAL;
}
It looks good to me, thanks!
But skb_checksum_try_convert only need to be called after the checksum is
validated, so I suggested a better solution as following:
89 if (!skb_checksum_simple_validate(skb)) {
90 skb_checksum_try_convert(skb, IPPROTO_GRE, 0,
91 null_compute_pseudo);
92 } else if (csum_err) {
93 *csum_err = true;
94 return -EINVAL;
95 }