diff options
Diffstat (limited to 'net/sched/act_api.c')
| -rw-r--r-- | net/sched/act_api.c | 55 | 
1 files changed, 32 insertions, 23 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index b70aa57319ea..e05b924618a0 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -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);  }  | 
