diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2018-09-06 17:50:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-09-08 02:05:07 -0400 |
commit | a162c3511410b50f09c002fea56fea2153b679d0 (patch) | |
tree | a687a142f1edc5d5246cb6b46453ae53ddbd4dc2 | |
parent | 8edfe2e992b75aee3da9316e9697c531194c2f53 (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.c | 12 |
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; | 446 | err_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); |