@@ -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;
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(-)