ipv4: Don't do expensive useless work during inetdev destroy (CVE-2016-3156)
This commit is contained in:
parent
3f1372dedd
commit
e01d7b854c
|
@ -237,6 +237,7 @@ linux (4.5.1-1) UNRELEASED; urgency=medium
|
|||
* netfilter: x_tables: Fix parsing of IPT_SO_SET_REPLACE blobs (CVE-2016-3134)
|
||||
- validate e->target_offset early
|
||||
- make sure e->next_offset covers remaining blob size
|
||||
* ipv4: Don't do expensive useless work during inetdev destroy (CVE-2016-3156)
|
||||
|
||||
[ Aurelien Jarno ]
|
||||
* [mipsel/mips/config.loongson-2f] Disable VIDEO_CX23885, VIDEO_IVTV,
|
||||
|
|
94
debian/patches/bugfix/all/ipv4-don-t-do-expensive-useless-work-during-inetdev-.patch
vendored
Normal file
94
debian/patches/bugfix/all/ipv4-don-t-do-expensive-useless-work-during-inetdev-.patch
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
From: "David S. Miller" <davem@davemloft.net>
|
||||
Date: Sun, 13 Mar 2016 23:28:00 -0400
|
||||
Subject: ipv4: Don't do expensive useless work during inetdev destroy.
|
||||
Origin: https://git.kernel.org/linus/fbd40ea0180a2d328c5adc61414dc8bab9335ce2
|
||||
|
||||
When an inetdev is destroyed, every address assigned to the interface
|
||||
is removed. And in this scenerio we do two pointless things which can
|
||||
be very expensive if the number of assigned interfaces is large:
|
||||
|
||||
1) Address promotion. We are deleting all addresses, so there is no
|
||||
point in doing this.
|
||||
|
||||
2) A full nf conntrack table purge for every address. We only need to
|
||||
do this once, as is already caught by the existing
|
||||
masq_dev_notifier so masq_inet_event() can skip this.
|
||||
|
||||
Reported-by: Solar Designer <solar@openwall.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Tested-by: Cyrill Gorcunov <gorcunov@openvz.org>
|
||||
---
|
||||
net/ipv4/devinet.c | 4 ++++
|
||||
net/ipv4/fib_frontend.c | 4 ++++
|
||||
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 12 ++++++++++--
|
||||
3 files changed, 18 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
|
||||
index 65e76a48382c..e333bc86bd39 100644
|
||||
--- a/net/ipv4/devinet.c
|
||||
+++ b/net/ipv4/devinet.c
|
||||
@@ -334,6 +334,9 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
+ if (in_dev->dead)
|
||||
+ goto no_promotions;
|
||||
+
|
||||
/* 1. Deleting primary ifaddr forces deletion all secondaries
|
||||
* unless alias promotion is set
|
||||
**/
|
||||
@@ -380,6 +383,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
||||
fib_del_ifaddr(ifa, ifa1);
|
||||
}
|
||||
|
||||
+no_promotions:
|
||||
/* 2. Unlink it */
|
||||
|
||||
*ifap = ifa1->ifa_next;
|
||||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
|
||||
index 473447593060..21add552e56a 100644
|
||||
--- a/net/ipv4/fib_frontend.c
|
||||
+++ b/net/ipv4/fib_frontend.c
|
||||
@@ -922,6 +922,9 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim)
|
||||
subnet = 1;
|
||||
}
|
||||
|
||||
+ if (in_dev->dead)
|
||||
+ goto no_promotions;
|
||||
+
|
||||
/* Deletion is more complicated than add.
|
||||
* We should take care of not to delete too much :-)
|
||||
*
|
||||
@@ -997,6 +1000,7 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim)
|
||||
}
|
||||
}
|
||||
|
||||
+no_promotions:
|
||||
if (!(ok & BRD_OK))
|
||||
fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
|
||||
if (subnet && ifa->ifa_prefixlen < 31) {
|
||||
diff --git a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
|
||||
index c6eb42100e9a..ea91058b5f6f 100644
|
||||
--- a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
|
||||
+++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
|
||||
@@ -108,10 +108,18 @@ static int masq_inet_event(struct notifier_block *this,
|
||||
unsigned long event,
|
||||
void *ptr)
|
||||
{
|
||||
- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
|
||||
+ struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev;
|
||||
struct netdev_notifier_info info;
|
||||
|
||||
- netdev_notifier_info_init(&info, dev);
|
||||
+ /* The masq_dev_notifier will catch the case of the device going
|
||||
+ * down. So if the inetdev is dead and being destroyed we have
|
||||
+ * no work to do. Otherwise this is an individual address removal
|
||||
+ * and we have to perform the flush.
|
||||
+ */
|
||||
+ if (idev->dead)
|
||||
+ return NOTIFY_DONE;
|
||||
+
|
||||
+ netdev_notifier_info_init(&info, idev->dev);
|
||||
return masq_device_event(this, event, &info);
|
||||
}
|
||||
|
|
@ -140,3 +140,4 @@ bugfix/all/tools-lib-traceevent-fix-use-of-uninitialized-variables.patch
|
|||
bugfix/all/scripts-fix-x.509-pem-support-in-sign-file.patch
|
||||
bugfix/all/netfilter-x_tables-validate-e-target_offset-early.patch
|
||||
bugfix/all/netfilter-x_tables-make-sure-e-next_offset-covers-re.patch
|
||||
bugfix/all/ipv4-don-t-do-expensive-useless-work-during-inetdev-.patch
|
||||
|
|
Loading…
Reference in New Issue