Skip to content

Commit 9e2f6c5

Browse files
Kirill Tkhaidavem330
authored andcommitted
netfilter: Rework xt_TEE netdevice notifier
Register netdevice notifier for every iptable entry is not good, since this breaks modularity, and the hidden synchronization is based on rtnl_lock(). This patch reworks the synchronization via new lock, while the rest of logic remains as it was before. This is required for the next patch. Tested via: while :; do unshare -n iptables -t mangle -A OUTPUT -j TEE --gateway 1.1.1.2 --oif lo; done Signed-off-by: Kirill Tkhai <[email protected]> Acked-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e9a441b commit 9e2f6c5

File tree

1 file changed

+46
-27
lines changed

1 file changed

+46
-27
lines changed

net/netfilter/xt_TEE.c

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <linux/netfilter/xt_TEE.h>
2121

2222
struct xt_tee_priv {
23-
struct notifier_block notifier;
23+
struct list_head list;
2424
struct xt_tee_tginfo *tginfo;
2525
int oif;
2626
};
@@ -51,29 +51,35 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
5151
}
5252
#endif
5353

54+
static DEFINE_MUTEX(priv_list_mutex);
55+
static LIST_HEAD(priv_list);
56+
5457
static int tee_netdev_event(struct notifier_block *this, unsigned long event,
5558
void *ptr)
5659
{
5760
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5861
struct xt_tee_priv *priv;
5962

60-
priv = container_of(this, struct xt_tee_priv, notifier);
61-
switch (event) {
62-
case NETDEV_REGISTER:
63-
if (!strcmp(dev->name, priv->tginfo->oif))
64-
priv->oif = dev->ifindex;
65-
break;
66-
case NETDEV_UNREGISTER:
67-
if (dev->ifindex == priv->oif)
68-
priv->oif = -1;
69-
break;
70-
case NETDEV_CHANGENAME:
71-
if (!strcmp(dev->name, priv->tginfo->oif))
72-
priv->oif = dev->ifindex;
73-
else if (dev->ifindex == priv->oif)
74-
priv->oif = -1;
75-
break;
63+
mutex_lock(&priv_list_mutex);
64+
list_for_each_entry(priv, &priv_list, list) {
65+
switch (event) {
66+
case NETDEV_REGISTER:
67+
if (!strcmp(dev->name, priv->tginfo->oif))
68+
priv->oif = dev->ifindex;
69+
break;
70+
case NETDEV_UNREGISTER:
71+
if (dev->ifindex == priv->oif)
72+
priv->oif = -1;
73+
break;
74+
case NETDEV_CHANGENAME:
75+
if (!strcmp(dev->name, priv->tginfo->oif))
76+
priv->oif = dev->ifindex;
77+
else if (dev->ifindex == priv->oif)
78+
priv->oif = -1;
79+
break;
80+
}
7681
}
82+
mutex_unlock(&priv_list_mutex);
7783

7884
return NOTIFY_DONE;
7985
}
@@ -89,8 +95,6 @@ static int tee_tg_check(const struct xt_tgchk_param *par)
8995
return -EINVAL;
9096

9197
if (info->oif[0]) {
92-
int ret;
93-
9498
if (info->oif[sizeof(info->oif)-1] != '\0')
9599
return -EINVAL;
96100

@@ -100,14 +104,11 @@ static int tee_tg_check(const struct xt_tgchk_param *par)
100104

101105
priv->tginfo = info;
102106
priv->oif = -1;
103-
priv->notifier.notifier_call = tee_netdev_event;
104107
info->priv = priv;
105108

106-
ret = register_netdevice_notifier(&priv->notifier);
107-
if (ret) {
108-
kfree(priv);
109-
return ret;
110-
}
109+
mutex_lock(&priv_list_mutex);
110+
list_add(&priv->list, &priv_list);
111+
mutex_unlock(&priv_list_mutex);
111112
} else
112113
info->priv = NULL;
113114

@@ -120,7 +121,9 @@ static void tee_tg_destroy(const struct xt_tgdtor_param *par)
120121
struct xt_tee_tginfo *info = par->targinfo;
121122

122123
if (info->priv) {
123-
unregister_netdevice_notifier(&info->priv->notifier);
124+
mutex_lock(&priv_list_mutex);
125+
list_del(&info->priv->list);
126+
mutex_unlock(&priv_list_mutex);
124127
kfree(info->priv);
125128
}
126129
static_key_slow_dec(&xt_tee_enabled);
@@ -153,13 +156,29 @@ static struct xt_target tee_tg_reg[] __read_mostly = {
153156
#endif
154157
};
155158

159+
static struct notifier_block tee_netdev_notifier = {
160+
.notifier_call = tee_netdev_event,
161+
};
162+
156163
static int __init tee_tg_init(void)
157164
{
158-
return xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
165+
int ret;
166+
167+
ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
168+
if (ret)
169+
return ret;
170+
ret = register_netdevice_notifier(&tee_netdev_notifier);
171+
if (ret) {
172+
xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
173+
return ret;
174+
}
175+
176+
return 0;
159177
}
160178

161179
static void __exit tee_tg_exit(void)
162180
{
181+
unregister_netdevice_notifier(&tee_netdev_notifier);
163182
xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
164183
}
165184

0 commit comments

Comments
 (0)