]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net_sched: fix a NULL pointer deref in ipt action
authorCong Wang <xiyou.wangcong@gmail.com>
Sun, 25 Aug 2019 17:01:32 +0000 (10:01 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Sep 2019 09:33:39 +0000 (10:33 +0100)
[ Upstream commit 981471bd3abf4d572097645d765391533aac327d ]

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: itugrok@yahoo.com
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
17 files changed:
include/net/act_api.h
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c

index 970303448c9029e2aaab37e3735bc83e0490de04..0c82d7ea6ee14cab4ec95c6c5b0bf04bb69f01bc 100644 (file)
@@ -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_net *tn,
        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;
index 20fae5ca87faa8d6515b6958f8ba66892ad61ae8..800846d77a56fdf4a023d38444f1ab90a0037238 100644 (file)
@@ -413,7 +413,7 @@ static __net_init int bpf_init_net(struct net *net)
 {
        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)
index 6054367479784adbe89431940db155a5c7816080..538dedd84e2101f1eecf0a58660bd19ab03c582d 100644 (file)
@@ -215,7 +215,7 @@ static __net_init int connmark_init_net(struct net *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)
index 40437197e053e61bb836fe2d1dd2fa65598511b7..1e269441065a6dd72966c48a2b5d84fb17832c8f 100644 (file)
@@ -678,7 +678,7 @@ static __net_init int csum_init_net(struct net *net)
 {
        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)
index 72d3347bdd41c0443bae0e78327e0b6d31742110..dfef9621375eb176a6c07aaff5149b83dc63e12a 100644 (file)
@@ -263,7 +263,7 @@ static __net_init int gact_init_net(struct net *net)
 {
        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)
index 24047e0e5db01b381b34554247e753449cd3f9cb..bac353bea02f54390ddf7653543e28b19d7bc82e 100644 (file)
@@ -887,7 +887,7 @@ static __net_init int ife_init_net(struct net *net)
 {
        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)
index 334f3a05767139cc9e77bbfe13ec6dab5ee2cceb..01d3669ef4989770d2d64c5f42608595e342e985 100644 (file)
@@ -65,12 +65,13 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
        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_action *a)
        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 *net, unsigned int id, struct nlattr *nla,
 
        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(struct net *net)
 {
        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 net *net)
 {
        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)
index 548614bd9366c37841fd17db96367a849f6e7646..399e3beae6cf45a96973b417b6b06a03091b6e8b 100644 (file)
@@ -419,7 +419,7 @@ static __net_init int mirred_init_net(struct net *net)
 {
        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)
index 619828920b97b8b5669fd54f283f57f211e9534f..d1b47a1b145c40f0acd98ca0ab30f9ecce4f364a 100644 (file)
@@ -317,7 +317,7 @@ static __net_init int nat_init_net(struct net *net)
 {
        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)
index 82d258b2a75ab89262adda2f0d7c57a523f0b07a..33c0cc5ef229f3bf71075c0706004cb73d2c2173 100644 (file)
@@ -488,7 +488,7 @@ static __net_init int pedit_init_net(struct net *net)
 {
        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)
index 997c34db1491995326256666f7ffda6d708842f9..4db25959e156285a85c1003e7955b67aa1f637bc 100644 (file)
@@ -342,7 +342,7 @@ static __net_init int police_init_net(struct net *net)
 {
        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)
index 34ff6c30d1e6d5b7b3e7c68720f2e039b0043854..98635311a5a0b73b31432fa91a6a5578b7fef0eb 100644 (file)
@@ -258,7 +258,7 @@ static __net_init int sample_init_net(struct net *net)
 {
        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)
index 658efae71a09de6f8194d9adb0d7e3c0e103044a..b418ef62e0a448a6f67b2ac46ffd88b8d4808b40 100644 (file)
@@ -215,7 +215,7 @@ static __net_init int simp_init_net(struct net *net)
 {
        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)
index 7709710a41f7270241dc0306525745691a9a9e33..a80179c1075f0d0ec6cbb249e68ce314960143a0 100644 (file)
@@ -316,7 +316,7 @@ static __net_init int skbedit_init_net(struct net *net)
 {
        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)
index 3038493d18ca197e871e890a807d0fd07687baa3..21d19529612174037fecaa5ab7cd39fba9847ffe 100644 (file)
@@ -277,7 +277,7 @@ static __net_init int skbmod_init_net(struct net *net)
 {
        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)
index 66bfe57e74ae0553e64dcd92a8da00e30bda26fa..43309ff2b5dc9639e34dec816522ce1824cdc739 100644 (file)
@@ -579,7 +579,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
 {
        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)
index da993edd2e40b6612ec9f97cb60ab08d57d8a730..41528b9664404f877e376f4fe9dfa283828dd8ae 100644 (file)
@@ -324,7 +324,7 @@ static __net_init int vlan_init_net(struct net *net)
 {
        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)