aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCong Wang <xiyou.wangcong@gmail.com>2018-09-06 17:50:16 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-08 02:05:07 -0400
commita162c3511410b50f09c002fea56fea2153b679d0 (patch)
treea687a142f1edc5d5246cb6b46453ae53ddbd4dc2
parent8edfe2e992b75aee3da9316e9697c531194c2f53 (diff)
net_sched: properly cancel netlink dump on failure
When nla_put*() fails after nla_nest_start(), we need to call nla_nest_cancel() to cancel the message, otherwise we end up calling nla_nest_end() like a success. Fixes: 0ed5269f9e41 ("net/sched: add tunnel option support to act_tunnel_key") Cc: Davide Caratti <dcaratti@redhat.com> Cc: Simon Horman <simon.horman@netronome.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/act_tunnel_key.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 28d58bbc953e..681f6f04e7da 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -412,8 +412,10 @@ static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
412 nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE, 412 nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE,
413 opt->type) || 413 opt->type) ||
414 nla_put(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA, 414 nla_put(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA,
415 opt->length * 4, opt + 1)) 415 opt->length * 4, opt + 1)) {
416 nla_nest_cancel(skb, start);
416 return -EMSGSIZE; 417 return -EMSGSIZE;
418 }
417 419
418 len -= sizeof(struct geneve_opt) + opt->length * 4; 420 len -= sizeof(struct geneve_opt) + opt->length * 4;
419 src += sizeof(struct geneve_opt) + opt->length * 4; 421 src += sizeof(struct geneve_opt) + opt->length * 4;
@@ -427,7 +429,7 @@ static int tunnel_key_opts_dump(struct sk_buff *skb,
427 const struct ip_tunnel_info *info) 429 const struct ip_tunnel_info *info)
428{ 430{
429 struct nlattr *start; 431 struct nlattr *start;
430 int err; 432 int err = -EINVAL;
431 433
432 if (!info->options_len) 434 if (!info->options_len)
433 return 0; 435 return 0;
@@ -439,9 +441,11 @@ static int tunnel_key_opts_dump(struct sk_buff *skb,
439 if (info->key.tun_flags & TUNNEL_GENEVE_OPT) { 441 if (info->key.tun_flags & TUNNEL_GENEVE_OPT) {
440 err = tunnel_key_geneve_opts_dump(skb, info); 442 err = tunnel_key_geneve_opts_dump(skb, info);
441 if (err) 443 if (err)
442 return err; 444 goto err_out;
443 } else { 445 } else {
444 return -EINVAL; 446err_out:
447 nla_nest_cancel(skb, start);
448 return err;
445 } 449 }
446 450
447 nla_nest_end(skb, start); 451 nla_nest_end(skb, start);