Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Disable BH while holding list spinlock in nf_conncount, from
   Taehee Yoo.

2) List corruption in nf_conncount, also from Taehee.

3) Fix race that results in leaving around an empty list node in
   nf_conncount, from Taehee Yoo.

4) Proper chain handling for inactive chains from the commit path,
   from Florian Westphal. This includes a selftest for this.

5) Do duplicate rule handles when replacing rules, also from Florian.

6) Remove net_exit path in xt_RATEEST that results in splat, from Taehee.

7) Possible use-after-free in nft_compat when releasing extensions.
   From Florian.

8) Memory leak in xt_hashlimit, from Taehee.

9) Call ip_vs_dst_notifier after ipv6_dev_notf, from Xin Long.

10) Fix cttimeout with udplite and gre, from Florian.

11) Preserve oif for IPv6 link-local generated traffic from mangle
    table, from Alin Nastac.

12) Missing error handling in masquerade notifiers, from Taehee Yoo.

13) Use mutex to protect registration/unregistration of masquerade
    extensions in order to prevent a race, from Taehee.

14) Incorrect condition check in tree_nodes_free(), also from Taehee.

15) Fix chain counter leak in rule replacement path, from Taehee.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2018-11-28 11:02:45 -08:00
23 changed files with 260 additions and 108 deletions

View File

@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
.flowi6_oif = sk ? sk->sk_bound_dev_if : 0,
.flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, sk),
.daddr = iph->daddr,

View File

@@ -58,8 +58,12 @@ static int __init masquerade_tg6_init(void)
int err;
err = xt_register_target(&masquerade_tg6_reg);
if (err == 0)
nf_nat_masquerade_ipv6_register_notifier();
if (err)
return err;
err = nf_nat_masquerade_ipv6_register_notifier();
if (err)
xt_unregister_target(&masquerade_tg6_reg);
return err;
}

View File

@@ -132,8 +132,8 @@ static void iterate_cleanup_work(struct work_struct *work)
* of ipv6 addresses being deleted), we also need to add an upper
* limit to the number of queued work items.
*/
static int masq_inet_event(struct notifier_block *this,
unsigned long event, void *ptr)
static int masq_inet6_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct inet6_ifaddr *ifa = ptr;
const struct net_device *dev;
@@ -171,30 +171,53 @@ static int masq_inet_event(struct notifier_block *this,
return NOTIFY_DONE;
}
static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event,
static struct notifier_block masq_inet6_notifier = {
.notifier_call = masq_inet6_event,
};
static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0);
static int masq_refcnt;
static DEFINE_MUTEX(masq_mutex);
void nf_nat_masquerade_ipv6_register_notifier(void)
int nf_nat_masquerade_ipv6_register_notifier(void)
{
/* check if the notifier is already set */
if (atomic_inc_return(&masquerade_notifier_refcount) > 1)
return;
int ret = 0;
register_netdevice_notifier(&masq_dev_notifier);
register_inet6addr_notifier(&masq_inet_notifier);
mutex_lock(&masq_mutex);
/* check if the notifier is already set */
if (++masq_refcnt > 1)
goto out_unlock;
ret = register_netdevice_notifier(&masq_dev_notifier);
if (ret)
goto err_dec;
ret = register_inet6addr_notifier(&masq_inet6_notifier);
if (ret)
goto err_unregister;
mutex_unlock(&masq_mutex);
return ret;
err_unregister:
unregister_netdevice_notifier(&masq_dev_notifier);
err_dec:
masq_refcnt--;
out_unlock:
mutex_unlock(&masq_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier);
void nf_nat_masquerade_ipv6_unregister_notifier(void)
{
mutex_lock(&masq_mutex);
/* check if the notifier still has clients */
if (atomic_dec_return(&masquerade_notifier_refcount) > 0)
return;
if (--masq_refcnt > 0)
goto out_unlock;
unregister_inet6addr_notifier(&masq_inet_notifier);
unregister_inet6addr_notifier(&masq_inet6_notifier);
unregister_netdevice_notifier(&masq_dev_notifier);
out_unlock:
mutex_unlock(&masq_mutex);
}
EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);

View File

@@ -70,7 +70,9 @@ static int __init nft_masq_ipv6_module_init(void)
if (ret < 0)
return ret;
nf_nat_masquerade_ipv6_register_notifier();
ret = nf_nat_masquerade_ipv6_register_notifier();
if (ret)
nft_unregister_expr(&nft_masq_ipv6_type);
return ret;
}