diff mbox series

[RFC,3/5] net/sched: act_bpf: validate the control action inside init()

Message ID 7673fdb060c9b44656d7ef356c318db4ad197080.1550271080.git.dcaratti@redhat.com
State RFC
Delegated to: David Miller
Headers show
Series net/sched: validate the control action with all the other parameters | expand

Commit Message

Davide Caratti Feb. 15, 2019, 11:06 p.m. UTC
Don't overwrite act_bpf data if the control control action is not valid,
to prevent loosing the previous configuration in case validation failed.
Not doing that caused NULL dereference in the data path if 'goto chain'
is used.

Tested with:
 # ./tdc.py -c bpf

Fixes: db50514f9a9c ("net: sched: add termination action to allow goto chain")
Fixes: 97763dc0f401 ("net_sched: reject unknown tcfa_action values")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
---
 net/sched/act_bpf.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 88a729bdab25..e2c2ba5faeb3 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -17,6 +17,7 @@ 
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
 
 #include <linux/tc_act/tc_bpf.h>
 #include <net/tc_act/tc_bpf.h>
@@ -282,6 +283,7 @@  static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 {
 	struct tc_action_net *tn = net_generic(net, bpf_net_id);
 	struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
+	struct tcf_chain *newchain = NULL;
 	struct tcf_bpf_cfg cfg, old;
 	struct tc_act_bpf *parm;
 	struct tcf_bpf *prog;
@@ -323,6 +325,10 @@  static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 		return ret;
 	}
 
+	ret = tcf_action_check_ctrlact(parm->action, tp, &newchain, extack);
+	if (ret < 0)
+		goto out;
+
 	is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS];
 	is_ebpf = tb[TCA_ACT_BPF_FD];
 
@@ -350,7 +356,7 @@  static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 	if (cfg.bpf_num_ops)
 		prog->bpf_num_ops = cfg.bpf_num_ops;
 
-	prog->tcf_action = parm->action;
+	tcf_action_set_ctrlact(*act, parm->action, newchain);
 	rcu_assign_pointer(prog->filter, cfg.filter);
 	spin_unlock_bh(&prog->tcf_lock);
 
@@ -364,6 +370,8 @@  static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 
 	return res;
 out:
+	if (newchain)
+		tcf_chain_put_by_act(newchain);
 	tcf_idr_release(*act, bind);
 
 	return ret;