net: sched: use temporary variable for actions indexes [Linux 4.19.66]

This Linux kernel change "net: sched: use temporary variable for actions indexes" is included in the Linux 4.19.66 release. This change is authored by Dmytro Linkin <dmitrolin [at] mellanox.com> on Thu Aug 1 13:02:51 2019 +0000. The commit for this change in Linux stable tree is 51d240a (patch) which is from upstream commit 7be8ef2. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 7be8ef2.

net: sched: use temporary variable for actions indexes

[ Upstream commit 7be8ef2cdbfe41a2e524b7c6cc3f8e6cfaa906e4 ]

Currently init call of all actions (except ipt) init their 'parm'
structure as a direct pointer to nla data in skb. This leads to race
condition when some of the filter actions were initialized successfully
(and were assigned with idr action index that was written directly
into nla data), but then were deleted and retried (due to following
action module missing or classifier-initiated retry), in which case
action init code tries to insert action to idr with index that was
assigned on previous iteration. During retry the index can be reused
by another action that was inserted concurrently, which causes
unintended action sharing between filters.
To fix described race condition, save action idr index to temporary
stack-allocated variable instead on nla data.

Fixes: 0190c1d452a9 ("net: sched: atomically check-allocate action")
Signed-off-by: Dmytro Linkin <dmitrolin@mellanox.com>
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 149 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/sched/act_bpf.c        |  9 +++++----
 net/sched/act_connmark.c   |  9 +++++----
 net/sched/act_csum.c       |  9 +++++----
 net/sched/act_gact.c       |  8 +++++---
 net/sched/act_ife.c        |  8 +++++---
 net/sched/act_mirred.c     | 13 +++++++------
 net/sched/act_nat.c        |  9 +++++----
 net/sched/act_pedit.c      | 10 ++++++----
 net/sched/act_police.c     |  8 +++++---
 net/sched/act_sample.c     | 10 +++++-----
 net/sched/act_simple.c     | 10 ++++++----
 net/sched/act_skbedit.c    | 11 ++++++-----
 net/sched/act_skbmod.c     | 11 ++++++-----
 net/sched/act_tunnel_key.c |  8 +++++---
 net/sched/act_vlan.c       | 16 +++++++++-------
 15 files changed, 85 insertions(+), 64 deletions(-)

diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 0c68bc9..20fae5c 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -287,6 +287,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
    struct tcf_bpf *prog;
    bool is_bpf, is_ebpf;
    int ret, res = 0;
+   u32 index;

    if (!nla)
        return -EINVAL;
@@ -299,13 +300,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        return -EINVAL;

    parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
-
-   ret = tcf_idr_check_alloc(tn, &parm->index, act, bind);
+   index = parm->index;
+   ret = tcf_idr_check_alloc(tn, &index, act, bind);
    if (!ret) {
-       ret = tcf_idr_create(tn, parm->index, est, act,
+       ret = tcf_idr_create(tn, index, est, act,
                     &act_bpf_ops, bind, true);
        if (ret < 0) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 6f0f273..6054367 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -104,6 +104,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
    struct tcf_connmark_info *ci;
    struct tc_connmark *parm;
    int ret = 0;
+   u32 index;

    if (!nla)
        return -EINVAL;
@@ -117,13 +118,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
        return -EINVAL;

    parm = nla_data(tb[TCA_CONNMARK_PARMS]);
-
-   ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   ret = tcf_idr_check_alloc(tn, &index, a, bind);
    if (!ret) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_connmark_ops, bind, false);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b8a67ae..4043719 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -55,6 +55,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
    struct tc_csum *parm;
    struct tcf_csum *p;
    int ret = 0, err;
+   u32 index;

    if (nla == NULL)
        return -EINVAL;
@@ -66,13 +67,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
    if (tb[TCA_CSUM_PARMS] == NULL)
        return -EINVAL;
    parm = nla_data(tb[TCA_CSUM_PARMS]);
-
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (!err) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_csum_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index cd1d9bd..72d3347 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -64,6 +64,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
    struct tc_gact *parm;
    struct tcf_gact *gact;
    int ret = 0;
+   u32 index;
    int err;
 #ifdef CONFIG_GACT_PROB
    struct tc_gact_p *p_parm = NULL;
@@ -79,6 +80,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
    if (tb[TCA_GACT_PARMS] == NULL)
        return -EINVAL;
    parm = nla_data(tb[TCA_GACT_PARMS]);
+   index = parm->index;

 #ifndef CONFIG_GACT_PROB
    if (tb[TCA_GACT_PROB] != NULL)
@@ -91,12 +93,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
    }
 #endif

-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (!err) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_gact_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 915b6e9..24047e0 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -482,6 +482,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
    u8 *saddr = NULL;
    bool exists = false;
    int ret = 0;
+   u32 index;
    int err;

    if (!nla) {
@@ -509,7 +510,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
    if (!p)
        return -ENOMEM;

-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0) {
        kfree(p);
        return err;
@@ -521,10 +523,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
    }

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
+       ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
                     bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            kfree(p);
            return ret;
        }
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index f767e78..548614b 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
    struct net_device *dev;
    bool exists = false;
    int ret, err;
+   u32 index;

    if (!nla) {
        NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
@@ -117,8 +118,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        return -EINVAL;
    }
    parm = nla_data(tb[TCA_MIRRED_PARMS]);
-
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -135,21 +136,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        if (exists)
            tcf_idr_release(*a, bind);
        else
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
        NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
        return -EINVAL;
    }

    if (!exists) {
        if (!parm->ifindex) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
            return -EINVAL;
        }
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_mirred_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 4313aa1..6198289 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -45,6 +45,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
    struct tc_nat *parm;
    int ret = 0, err;
    struct tcf_nat *p;
+   u32 index;

    if (nla == NULL)
        return -EINVAL;
@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
    if (tb[TCA_NAT_PARMS] == NULL)
        return -EINVAL;
    parm = nla_data(tb[TCA_NAT_PARMS]);
-
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (!err) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_nat_ops, bind, false);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index ca535a8..82d258b 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
    struct tcf_pedit *p;
    int ret = 0, err;
    int ksize;
+   u32 index;

    if (!nla) {
        NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed");
@@ -178,18 +179,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
    if (IS_ERR(keys_ex))
        return PTR_ERR(keys_ex);

-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (!err) {
        if (!parm->nkeys) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
            ret = -EINVAL;
            goto out_free;
        }
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_pedit_ops, bind, false);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            goto out_free;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 5d8bfa8..997c34d 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -85,6 +85,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
    struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
    struct tc_action_net *tn = net_generic(net, police_net_id);
    bool exists = false;
+   u32 index;
    int size;

    if (nla == NULL)
@@ -101,7 +102,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        return -EINVAL;

    parm = nla_data(tb[TCA_POLICE_TBF]);
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -109,10 +111,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        return 0;

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, NULL, a,
+       ret = tcf_idr_create(tn, index, NULL, a,
                     &act_police_ops, bind, false);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index c7f5d63..ac37654 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -43,7 +43,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
    struct tc_action_net *tn = net_generic(net, sample_net_id);
    struct nlattr *tb[TCA_SAMPLE_MAX + 1];
    struct psample_group *psample_group;
-   u32 psample_group_num, rate;
+   u32 psample_group_num, rate, index;
    struct tc_sample *parm;
    struct tcf_sample *s;
    bool exists = false;
@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        return -EINVAL;

    parm = nla_data(tb[TCA_SAMPLE_PARMS]);
-
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        return 0;

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_sample_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }
        ret = ACT_P_CREATED;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 52400d4..658efae 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -88,6 +88,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
    struct tcf_defact *d;
    bool exists = false;
    int ret = 0, err;
+   u32 index;

    if (nla == NULL)
        return -EINVAL;
@@ -100,7 +101,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        return -EINVAL;

    parm = nla_data(tb[TCA_DEF_PARMS]);
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -111,15 +113,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        if (exists)
            tcf_idr_release(*a, bind);
        else
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
        return -EINVAL;
    }

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_simp_ops, bind, false);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 86d90fc..7709710 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -107,6 +107,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
    u16 *queue_mapping = NULL, *ptype = NULL;
    bool exists = false;
    int ret = 0, err;
+   u32 index;

    if (nla == NULL)
        return -EINVAL;
@@ -153,8 +154,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
    }

    parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
-
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -165,15 +166,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        if (exists)
            tcf_idr_release(*a, bind);
        else
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
        return -EINVAL;
    }

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_skbedit_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index 588077f..3038493 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -88,12 +88,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
    struct nlattr *tb[TCA_SKBMOD_MAX + 1];
    struct tcf_skbmod_params *p, *p_old;
    struct tc_skbmod *parm;
+   u32 lflags = 0, index;
    struct tcf_skbmod *d;
    bool exists = false;
    u8 *daddr = NULL;
    u8 *saddr = NULL;
    u16 eth_type = 0;
-   u32 lflags = 0;
    int ret = 0, err;

    if (!nla)
@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
    }

    parm = nla_data(tb[TCA_SKBMOD_PARMS]);
+   index = parm->index;
    if (parm->flags & SKBMOD_F_SWAPMAC)
        lflags = SKBMOD_F_SWAPMAC;

-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        if (exists)
            tcf_idr_release(*a, bind);
        else
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
        return -EINVAL;
    }

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_skbmod_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 72d9c43..66bfe57 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -224,6 +224,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
    __be16 flags;
    u8 tos, ttl;
    int ret = 0;
+   u32 index;
    int err;

    if (!nla) {
@@ -244,7 +245,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
    }

    parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -338,7 +340,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
    }

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_tunnel_key_ops, bind, true);
        if (ret) {
            NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
@@ -384,7 +386,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
    if (exists)
        tcf_idr_release(*a, bind);
    else
-       tcf_idr_cleanup(tn, parm->index);
+       tcf_idr_cleanup(tn, index);
    return ret;
 }

diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 20a7d4d..da993edd 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -118,6 +118,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
    u8 push_prio = 0;
    bool exists = false;
    int ret = 0, err;
+   u32 index;

    if (!nla)
        return -EINVAL;
@@ -129,7 +130,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
    if (!tb[TCA_VLAN_PARMS])
        return -EINVAL;
    parm = nla_data(tb[TCA_VLAN_PARMS]);
-   err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+   index = parm->index;
+   err = tcf_idr_check_alloc(tn, &index, a, bind);
    if (err < 0)
        return err;
    exists = err;
@@ -145,7 +147,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
            if (exists)
                tcf_idr_release(*a, bind);
            else
-               tcf_idr_cleanup(tn, parm->index);
+               tcf_idr_cleanup(tn, index);
            return -EINVAL;
        }
        push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
@@ -153,7 +155,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
            if (exists)
                tcf_idr_release(*a, bind);
            else
-               tcf_idr_cleanup(tn, parm->index);
+               tcf_idr_cleanup(tn, index);
            return -ERANGE;
        }

@@ -167,7 +169,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                if (exists)
                    tcf_idr_release(*a, bind);
                else
-                   tcf_idr_cleanup(tn, parm->index);
+                   tcf_idr_cleanup(tn, index);
                return -EPROTONOSUPPORT;
            }
        } else {
@@ -181,16 +183,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        if (exists)
            tcf_idr_release(*a, bind);
        else
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
        return -EINVAL;
    }
    action = parm->v_action;

    if (!exists) {
-       ret = tcf_idr_create(tn, parm->index, est, a,
+       ret = tcf_idr_create(tn, index, est, a,
                     &act_vlan_ops, bind, true);
        if (ret) {
-           tcf_idr_cleanup(tn, parm->index);
+           tcf_idr_cleanup(tn, index);
            return ret;
        }

Leave a Reply

Your email address will not be published. Required fields are marked *