CVE-2016-3135 ipv4: DoS when destroying a network interface (rhbz 1318172 1318270)
This commit is contained in:
parent
cb176ec4e7
commit
6f9c14ed9c
97
ipv4-Dont-do-expensive-useless-work-during-inetdev-des.patch
Normal file
97
ipv4-Dont-do-expensive-useless-work-during-inetdev-des.patch
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
From fbd40ea0180a2d328c5adc61414dc8bab9335ce2 Mon Sep 17 00:00:00 2001
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 65e76a4..e333bc8 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 4734475..21add55 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 c6eb421..ea91058 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
cgit v0.12
|
||||||
|
|
@ -619,6 +619,9 @@ Patch664: netfilter-x_tables-check-for-size-overflow.patch
|
|||||||
#CVE-2016-3134 rhbz 1317383 1317384
|
#CVE-2016-3134 rhbz 1317383 1317384
|
||||||
Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch
|
Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch
|
||||||
|
|
||||||
|
#CVE-2016-3135 rhbz 1318172 1318270
|
||||||
|
Patch666: ipv4-Dont-do-expensive-useless-work-during-inetdev-des.patch
|
||||||
|
|
||||||
# END OF PATCH DEFINITIONS
|
# END OF PATCH DEFINITIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -2140,6 +2143,9 @@ fi
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Mar 16 2016 Josh Boyer <jwboyer@fedoraproject.org>
|
||||||
|
- CVE-2016-3135 ipv4: DoS when destroying a network interface (rhbz 1318172 1318270)
|
||||||
|
|
||||||
* Wed Mar 16 2016 Josh Boyer <jwboyer@fedoraproject.org> - 4.6.0-0.rc0.git2.1
|
* Wed Mar 16 2016 Josh Boyer <jwboyer@fedoraproject.org> - 4.6.0-0.rc0.git2.1
|
||||||
- Linux v4.5-760-g710d60cbf1b3
|
- Linux v4.5-760-g710d60cbf1b3
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user