aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaehee Yoo <ap420073@gmail.com>2018-10-06 11:09:18 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2018-10-11 05:29:14 -0400
commitf24d2d4f9586985509320f90308723d3d0c4e47f (patch)
tree68d348b457149c90c47d3bf3ed93c09f5d178abc
parent4a3e71b7b7dbaf3562be9d508260935aa13cb48b (diff)
netfilter: xt_TEE: fix wrong interface selection
TEE netdevice notifier handler checks only interface name. however each netns can have same interface name. hence other netns's interface could be selected. test commands: %ip netns add vm1 %iptables -I INPUT -p icmp -j TEE --gateway 192.168.1.1 --oif enp2s0 %ip link set enp2s0 netns vm1 Above rule is in the root netns. but that rule could get enp2s0 ifindex of vm1 by notifier handler. After this patch, TEE rule is added to the per-netns list. Fixes: 9e2f6c5d78db ("netfilter: Rework xt_TEE netdevice notifier") Signed-off-by: Taehee Yoo <ap420073@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/xt_TEE.c69
1 files changed, 52 insertions, 17 deletions
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 0d0d68c989df..673ad2099f97 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -14,6 +14,8 @@
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/route.h> 15#include <linux/route.h>
16#include <linux/netfilter/x_tables.h> 16#include <linux/netfilter/x_tables.h>
17#include <net/net_namespace.h>
18#include <net/netns/generic.h>
17#include <net/route.h> 19#include <net/route.h>
18#include <net/netfilter/ipv4/nf_dup_ipv4.h> 20#include <net/netfilter/ipv4/nf_dup_ipv4.h>
19#include <net/netfilter/ipv6/nf_dup_ipv6.h> 21#include <net/netfilter/ipv6/nf_dup_ipv6.h>
@@ -25,8 +27,15 @@ struct xt_tee_priv {
25 int oif; 27 int oif;
26}; 28};
27 29
30static unsigned int tee_net_id __read_mostly;
28static const union nf_inet_addr tee_zero_address; 31static const union nf_inet_addr tee_zero_address;
29 32
33struct tee_net {
34 struct list_head priv_list;
35 /* lock protects the priv_list */
36 struct mutex lock;
37};
38
30static unsigned int 39static unsigned int
31tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) 40tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
32{ 41{
@@ -51,17 +60,16 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
51} 60}
52#endif 61#endif
53 62
54static DEFINE_MUTEX(priv_list_mutex);
55static LIST_HEAD(priv_list);
56
57static int tee_netdev_event(struct notifier_block *this, unsigned long event, 63static int tee_netdev_event(struct notifier_block *this, unsigned long event,
58 void *ptr) 64 void *ptr)
59{ 65{
60 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 66 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
67 struct net *net = dev_net(dev);
68 struct tee_net *tn = net_generic(net, tee_net_id);
61 struct xt_tee_priv *priv; 69 struct xt_tee_priv *priv;
62 70
63 mutex_lock(&priv_list_mutex); 71 mutex_lock(&tn->lock);
64 list_for_each_entry(priv, &priv_list, list) { 72 list_for_each_entry(priv, &tn->priv_list, list) {
65 switch (event) { 73 switch (event) {
66 case NETDEV_REGISTER: 74 case NETDEV_REGISTER:
67 if (!strcmp(dev->name, priv->tginfo->oif)) 75 if (!strcmp(dev->name, priv->tginfo->oif))
@@ -79,13 +87,14 @@ static int tee_netdev_event(struct notifier_block *this, unsigned long event,
79 break; 87 break;
80 } 88 }
81 } 89 }
82 mutex_unlock(&priv_list_mutex); 90 mutex_unlock(&tn->lock);
83 91
84 return NOTIFY_DONE; 92 return NOTIFY_DONE;
85} 93}
86 94
87static int tee_tg_check(const struct xt_tgchk_param *par) 95static int tee_tg_check(const struct xt_tgchk_param *par)
88{ 96{
97 struct tee_net *tn = net_generic(par->net, tee_net_id);
89 struct xt_tee_tginfo *info = par->targinfo; 98 struct xt_tee_tginfo *info = par->targinfo;
90 struct xt_tee_priv *priv; 99 struct xt_tee_priv *priv;
91 100
@@ -106,9 +115,9 @@ static int tee_tg_check(const struct xt_tgchk_param *par)
106 priv->oif = -1; 115 priv->oif = -1;
107 info->priv = priv; 116 info->priv = priv;
108 117
109 mutex_lock(&priv_list_mutex); 118 mutex_lock(&tn->lock);
110 list_add(&priv->list, &priv_list); 119 list_add(&priv->list, &tn->priv_list);
111 mutex_unlock(&priv_list_mutex); 120 mutex_unlock(&tn->lock);
112 } else 121 } else
113 info->priv = NULL; 122 info->priv = NULL;
114 123
@@ -118,12 +127,13 @@ static int tee_tg_check(const struct xt_tgchk_param *par)
118 127
119static void tee_tg_destroy(const struct xt_tgdtor_param *par) 128static void tee_tg_destroy(const struct xt_tgdtor_param *par)
120{ 129{
130 struct tee_net *tn = net_generic(par->net, tee_net_id);
121 struct xt_tee_tginfo *info = par->targinfo; 131 struct xt_tee_tginfo *info = par->targinfo;
122 132
123 if (info->priv) { 133 if (info->priv) {
124 mutex_lock(&priv_list_mutex); 134 mutex_lock(&tn->lock);
125 list_del(&info->priv->list); 135 list_del(&info->priv->list);
126 mutex_unlock(&priv_list_mutex); 136 mutex_unlock(&tn->lock);
127 kfree(info->priv); 137 kfree(info->priv);
128 } 138 }
129 static_key_slow_dec(&xt_tee_enabled); 139 static_key_slow_dec(&xt_tee_enabled);
@@ -156,6 +166,21 @@ static struct xt_target tee_tg_reg[] __read_mostly = {
156#endif 166#endif
157}; 167};
158 168
169static int __net_init tee_net_init(struct net *net)
170{
171 struct tee_net *tn = net_generic(net, tee_net_id);
172
173 INIT_LIST_HEAD(&tn->priv_list);
174 mutex_init(&tn->lock);
175 return 0;
176}
177
178static struct pernet_operations tee_net_ops = {
179 .init = tee_net_init,
180 .id = &tee_net_id,
181 .size = sizeof(struct tee_net),
182};
183
159static struct notifier_block tee_netdev_notifier = { 184static struct notifier_block tee_netdev_notifier = {
160 .notifier_call = tee_netdev_event, 185 .notifier_call = tee_netdev_event,
161}; 186};
@@ -164,22 +189,32 @@ static int __init tee_tg_init(void)
164{ 189{
165 int ret; 190 int ret;
166 191
167 ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 192 ret = register_pernet_subsys(&tee_net_ops);
168 if (ret) 193 if (ret < 0)
169 return ret; 194 return ret;
195
196 ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
197 if (ret < 0)
198 goto cleanup_subsys;
199
170 ret = register_netdevice_notifier(&tee_netdev_notifier); 200 ret = register_netdevice_notifier(&tee_netdev_notifier);
171 if (ret) { 201 if (ret < 0)
172 xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 202 goto unregister_targets;
173 return ret;
174 }
175 203
176 return 0; 204 return 0;
205
206unregister_targets:
207 xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
208cleanup_subsys:
209 unregister_pernet_subsys(&tee_net_ops);
210 return ret;
177} 211}
178 212
179static void __exit tee_tg_exit(void) 213static void __exit tee_tg_exit(void)
180{ 214{
181 unregister_netdevice_notifier(&tee_netdev_notifier); 215 unregister_netdevice_notifier(&tee_netdev_notifier);
182 xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 216 xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
217 unregister_pernet_subsys(&tee_net_ops);
183} 218}
184 219
185module_init(tee_tg_init); 220module_init(tee_tg_init);