|
@@ -529,20 +529,20 @@ errout:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
|
|
|
+static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
|
|
|
{
|
|
|
- a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL);
|
|
|
- if (!a->act_cookie)
|
|
|
- return -ENOMEM;
|
|
|
+ struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
|
|
|
+ if (!c)
|
|
|
+ return NULL;
|
|
|
|
|
|
- a->act_cookie->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
|
|
|
- if (!a->act_cookie->data) {
|
|
|
- kfree(a->act_cookie);
|
|
|
- return -ENOMEM;
|
|
|
+ c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
|
|
|
+ if (!c->data) {
|
|
|
+ kfree(c);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
- a->act_cookie->len = nla_len(tb[TCA_ACT_COOKIE]);
|
|
|
+ c->len = nla_len(tb[TCA_ACT_COOKIE]);
|
|
|
|
|
|
- return 0;
|
|
|
+ return c;
|
|
|
}
|
|
|
|
|
|
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
|
@@ -551,6 +551,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
|
|
{
|
|
|
struct tc_action *a;
|
|
|
struct tc_action_ops *a_o;
|
|
|
+ struct tc_cookie *cookie = NULL;
|
|
|
char act_name[IFNAMSIZ];
|
|
|
struct nlattr *tb[TCA_ACT_MAX + 1];
|
|
|
struct nlattr *kind;
|
|
@@ -566,6 +567,18 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
|
|
goto err_out;
|
|
|
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
|
|
|
goto err_out;
|
|
|
+ if (tb[TCA_ACT_COOKIE]) {
|
|
|
+ int cklen = nla_len(tb[TCA_ACT_COOKIE]);
|
|
|
+
|
|
|
+ if (cklen > TC_COOKIE_MAX_SIZE)
|
|
|
+ goto err_out;
|
|
|
+
|
|
|
+ cookie = nla_memdup_cookie(tb);
|
|
|
+ if (!cookie) {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto err_out;
|
|
|
+ }
|
|
|
+ }
|
|
|
} else {
|
|
|
err = -EINVAL;
|
|
|
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
|
|
@@ -604,20 +617,12 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
|
|
if (err < 0)
|
|
|
goto err_mod;
|
|
|
|
|
|
- if (tb[TCA_ACT_COOKIE]) {
|
|
|
- int cklen = nla_len(tb[TCA_ACT_COOKIE]);
|
|
|
-
|
|
|
- if (cklen > TC_COOKIE_MAX_SIZE) {
|
|
|
- err = -EINVAL;
|
|
|
- tcf_hash_release(a, bind);
|
|
|
- goto err_mod;
|
|
|
- }
|
|
|
-
|
|
|
- if (nla_memdup_cookie(a, tb) < 0) {
|
|
|
- err = -ENOMEM;
|
|
|
- tcf_hash_release(a, bind);
|
|
|
- goto err_mod;
|
|
|
+ if (name == NULL && tb[TCA_ACT_COOKIE]) {
|
|
|
+ if (a->act_cookie) {
|
|
|
+ kfree(a->act_cookie->data);
|
|
|
+ kfree(a->act_cookie);
|
|
|
}
|
|
|
+ a->act_cookie = cookie;
|
|
|
}
|
|
|
|
|
|
/* module count goes up only when brand new policy is created
|
|
@@ -632,6 +637,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
|
|
err_mod:
|
|
|
module_put(a_o->owner);
|
|
|
err_out:
|
|
|
+ if (cookie) {
|
|
|
+ kfree(cookie->data);
|
|
|
+ kfree(cookie);
|
|
|
+ }
|
|
|
return ERR_PTR(err);
|
|
|
}
|
|
|
|