|
@@ -1,290 +0,0 @@
|
|
|
-From: Cong Wang <[email protected]>
|
|
|
-To: [email protected]
|
|
|
-Cc: Cong Wang <[email protected]>,
|
|
|
- Tony Ambardar <[email protected]>,
|
|
|
- Jamal Hadi Salim <[email protected]>,
|
|
|
- Jiri Pirko <[email protected]>
|
|
|
-Subject: [Patch net] net_sched: fix a NULL pointer deref in ipt action
|
|
|
-Date: Sun, 25 Aug 2019 10:01:32 -0700
|
|
|
-
|
|
|
-The net pointer in struct xt_tgdtor_param is not explicitly
|
|
|
-initialized therefore is still NULL when dereferencing it.
|
|
|
-So we have to find a way to pass the correct net pointer to
|
|
|
-ipt_destroy_target().
|
|
|
-
|
|
|
-The best way I find is just saving the net pointer inside the per
|
|
|
-netns struct tcf_idrinfo, which could make this patch smaller.
|
|
|
-
|
|
|
-Fixes: 0c66dc1ea3f0 ("netfilter: conntrack: register hooks in netns when needed by ruleset")
|
|
|
-Reported-and-tested-by: Tony Ambardar <[email protected]>
|
|
|
-Cc: Jamal Hadi Salim <[email protected]>
|
|
|
-Cc: Jiri Pirko <[email protected]>
|
|
|
-Signed-off-by: Cong Wang <[email protected]>
|
|
|
-
|
|
|
-[Backported for kernel v4.19]
|
|
|
-Signed-off-by: Tony Ambardar <[email protected]>
|
|
|
----
|
|
|
- include/net/act_api.h | 4 +++-
|
|
|
- net/sched/act_bpf.c | 2 +-
|
|
|
- net/sched/act_connmark.c | 2 +-
|
|
|
- net/sched/act_csum.c | 2 +-
|
|
|
- net/sched/act_gact.c | 2 +-
|
|
|
- net/sched/act_ife.c | 2 +-
|
|
|
- net/sched/act_ipt.c | 11 ++++++-----
|
|
|
- net/sched/act_mirred.c | 2 +-
|
|
|
- net/sched/act_nat.c | 2 +-
|
|
|
- net/sched/act_pedit.c | 2 +-
|
|
|
- net/sched/act_police.c | 2 +-
|
|
|
- net/sched/act_sample.c | 2 +-
|
|
|
- net/sched/act_simple.c | 2 +-
|
|
|
- net/sched/act_skbedit.c | 2 +-
|
|
|
- net/sched/act_skbmod.c | 2 +-
|
|
|
- net/sched/act_tunnel_key.c | 2 +-
|
|
|
- net/sched/act_vlan.c | 2 +-
|
|
|
- 17 files changed, 24 insertions(+), 21 deletions(-)
|
|
|
-
|
|
|
---- a/include/net/act_api.h
|
|
|
-+++ b/include/net/act_api.h
|
|
|
-@@ -15,6 +15,7 @@
|
|
|
- struct tcf_idrinfo {
|
|
|
- spinlock_t lock;
|
|
|
- struct idr action_idr;
|
|
|
-+ struct net *net;
|
|
|
- };
|
|
|
-
|
|
|
- struct tc_action_ops;
|
|
|
-@@ -107,7 +108,7 @@ struct tc_action_net {
|
|
|
- };
|
|
|
-
|
|
|
- static inline
|
|
|
--int tc_action_net_init(struct tc_action_net *tn,
|
|
|
-+int tc_action_net_init(struct net *net, struct tc_action_net *tn,
|
|
|
- const struct tc_action_ops *ops)
|
|
|
- {
|
|
|
- int err = 0;
|
|
|
-@@ -116,6 +117,7 @@ int tc_action_net_init(struct tc_action_
|
|
|
- if (!tn->idrinfo)
|
|
|
- return -ENOMEM;
|
|
|
- tn->ops = ops;
|
|
|
-+ tn->idrinfo->net = net;
|
|
|
- spin_lock_init(&tn->idrinfo->lock);
|
|
|
- idr_init(&tn->idrinfo->action_idr);
|
|
|
- return err;
|
|
|
---- a/net/sched/act_bpf.c
|
|
|
-+++ b/net/sched/act_bpf.c
|
|
|
-@@ -413,7 +413,7 @@ static __net_init int bpf_init_net(struc
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, bpf_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_bpf_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_bpf_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit bpf_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_connmark.c
|
|
|
-+++ b/net/sched/act_connmark.c
|
|
|
-@@ -215,7 +215,7 @@ static __net_init int connmark_init_net(
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, connmark_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_connmark_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_connmark_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit connmark_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_csum.c
|
|
|
-+++ b/net/sched/act_csum.c
|
|
|
-@@ -678,7 +678,7 @@ static __net_init int csum_init_net(stru
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, csum_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_csum_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_csum_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit csum_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_gact.c
|
|
|
-+++ b/net/sched/act_gact.c
|
|
|
-@@ -263,7 +263,7 @@ static __net_init int gact_init_net(stru
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, gact_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_gact_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_gact_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit gact_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_ife.c
|
|
|
-+++ b/net/sched/act_ife.c
|
|
|
-@@ -887,7 +887,7 @@ static __net_init int ife_init_net(struc
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, ife_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_ife_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_ife_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit ife_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_ipt.c
|
|
|
-+++ b/net/sched/act_ipt.c
|
|
|
-@@ -65,12 +65,13 @@ static int ipt_init_target(struct net *n
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
--static void ipt_destroy_target(struct xt_entry_target *t)
|
|
|
-+static void ipt_destroy_target(struct xt_entry_target *t, struct net *net)
|
|
|
- {
|
|
|
- struct xt_tgdtor_param par = {
|
|
|
- .target = t->u.kernel.target,
|
|
|
- .targinfo = t->data,
|
|
|
- .family = NFPROTO_IPV4,
|
|
|
-+ .net = net,
|
|
|
- };
|
|
|
- if (par.target->destroy != NULL)
|
|
|
- par.target->destroy(&par);
|
|
|
-@@ -82,7 +83,7 @@ static void tcf_ipt_release(struct tc_ac
|
|
|
- struct tcf_ipt *ipt = to_ipt(a);
|
|
|
-
|
|
|
- if (ipt->tcfi_t) {
|
|
|
-- ipt_destroy_target(ipt->tcfi_t);
|
|
|
-+ ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net);
|
|
|
- kfree(ipt->tcfi_t);
|
|
|
- }
|
|
|
- kfree(ipt->tcfi_tname);
|
|
|
-@@ -182,7 +183,7 @@ static int __tcf_ipt_init(struct net *ne
|
|
|
-
|
|
|
- spin_lock_bh(&ipt->tcf_lock);
|
|
|
- if (ret != ACT_P_CREATED) {
|
|
|
-- ipt_destroy_target(ipt->tcfi_t);
|
|
|
-+ ipt_destroy_target(ipt->tcfi_t, net);
|
|
|
- kfree(ipt->tcfi_tname);
|
|
|
- kfree(ipt->tcfi_t);
|
|
|
- }
|
|
|
-@@ -353,7 +354,7 @@ static __net_init int ipt_init_net(struc
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, ipt_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_ipt_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_ipt_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit ipt_exit_net(struct list_head *net_list)
|
|
|
-@@ -403,7 +404,7 @@ static __net_init int xt_init_net(struct
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, xt_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_xt_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_xt_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit xt_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_mirred.c
|
|
|
-+++ b/net/sched/act_mirred.c
|
|
|
-@@ -419,7 +419,7 @@ static __net_init int mirred_init_net(st
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, mirred_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_mirred_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_mirred_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit mirred_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_nat.c
|
|
|
-+++ b/net/sched/act_nat.c
|
|
|
-@@ -317,7 +317,7 @@ static __net_init int nat_init_net(struc
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, nat_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_nat_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_nat_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit nat_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_pedit.c
|
|
|
-+++ b/net/sched/act_pedit.c
|
|
|
-@@ -488,7 +488,7 @@ static __net_init int pedit_init_net(str
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, pedit_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_pedit_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_pedit_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit pedit_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_police.c
|
|
|
-+++ b/net/sched/act_police.c
|
|
|
-@@ -342,7 +342,7 @@ static __net_init int police_init_net(st
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, police_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_police_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_police_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit police_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_sample.c
|
|
|
-+++ b/net/sched/act_sample.c
|
|
|
-@@ -255,7 +255,7 @@ static __net_init int sample_init_net(st
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, sample_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_sample_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_sample_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit sample_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_simple.c
|
|
|
-+++ b/net/sched/act_simple.c
|
|
|
-@@ -215,7 +215,7 @@ static __net_init int simp_init_net(stru
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, simp_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_simp_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_simp_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit simp_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_skbedit.c
|
|
|
-+++ b/net/sched/act_skbedit.c
|
|
|
-@@ -316,7 +316,7 @@ static __net_init int skbedit_init_net(s
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, skbedit_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_skbedit_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_skbedit_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit skbedit_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_skbmod.c
|
|
|
-+++ b/net/sched/act_skbmod.c
|
|
|
-@@ -277,7 +277,7 @@ static __net_init int skbmod_init_net(st
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, skbmod_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_skbmod_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_skbmod_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit skbmod_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_tunnel_key.c
|
|
|
-+++ b/net/sched/act_tunnel_key.c
|
|
|
-@@ -579,7 +579,7 @@ static __net_init int tunnel_key_init_ne
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_tunnel_key_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_tunnel_key_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
|
|
|
---- a/net/sched/act_vlan.c
|
|
|
-+++ b/net/sched/act_vlan.c
|
|
|
-@@ -324,7 +324,7 @@ static __net_init int vlan_init_net(stru
|
|
|
- {
|
|
|
- struct tc_action_net *tn = net_generic(net, vlan_net_id);
|
|
|
-
|
|
|
-- return tc_action_net_init(tn, &act_vlan_ops);
|
|
|
-+ return tc_action_net_init(net, tn, &act_vlan_ops);
|
|
|
- }
|
|
|
-
|
|
|
- static void __net_exit vlan_exit_net(struct list_head *net_list)
|