Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e8ddd7f authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller
Browse files

net: sched: don't release reference on action overwrite



Return from action init function with reference to action taken,
even when overwriting existing action.

Action init API initializes its fourth argument (pointer to pointer to tc
action) to either existing action with same index or newly created action.
In case of existing index(and bind argument is zero), init function returns
without incrementing action reference counter. Caller of action init then
proceeds working with action, without actually holding reference to it.
This means that action could be deleted concurrently.

Change action init behavior to always take reference to action before
returning successfully, in order to protect from concurrent deletion.

Reviewed-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16af6067
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -870,8 +870,6 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		}
		act->order = i;
		sz += tcf_action_fill_size(act);
		if (ovr)
			refcount_inc(&act->tcfa_refcnt);
		list_add_tail(&act->list, actions);
	}

+4 −4
Original line number Diff line number Diff line
@@ -311,10 +311,11 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
		if (bind)
			return 0;

		if (!replace) {
			tcf_idr_release(*act, bind);
		if (!replace)
			return -EEXIST;
		}
	}

	is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS];
	is_ebpf = tb[TCA_ACT_BPF_FD];
@@ -356,7 +357,6 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,

	return res;
out:
	if (res == ACT_P_CREATED)
	tcf_idr_release(*act, bind);

	return ret;
+3 −2
Original line number Diff line number Diff line
@@ -135,9 +135,10 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
		ci = to_connmark(*a);
		if (bind)
			return 0;
		if (!ovr) {
			tcf_idr_release(*a, bind);
		if (!ovr)
			return -EEXIST;
		}
		/* replacing action and zone */
		ci->tcf_action = parm->action;
		ci->zone = parm->zone;
+4 −4
Original line number Diff line number Diff line
@@ -76,17 +76,17 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
	} else {
		if (bind)/* dont override defaults */
			return 0;
		if (!ovr) {
			tcf_idr_release(*a, bind);
		if (!ovr)
			return -EEXIST;
		}
	}

	p = to_tcf_csum(*a);
	ASSERT_RTNL();

	params_new = kzalloc(sizeof(*params_new), GFP_KERNEL);
	if (unlikely(!params_new)) {
		if (ret == ACT_P_CREATED)
		tcf_idr_release(*a, bind);
		return -ENOMEM;
	}
+3 −2
Original line number Diff line number Diff line
@@ -100,10 +100,11 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
	} else {
		if (bind)/* dont override defaults */
			return 0;
		if (!ovr) {
			tcf_idr_release(*a, bind);
		if (!ovr)
			return -EEXIST;
		}
	}

	gact = to_gact(*a);

Loading