From 1b7f083c0f10c48754c07c49e207746f54ac402e Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Thu, 14 Apr 2016 14:46:07 +0200 Subject: kernel-ipv4: CVE-2016-3156 Fixes denial of service when destroying a network interface (in the linux qoriq-3.12). Reference: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-3156 Reference to the upstream patch: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ patch/?id=5cc4ff312ac06ee4c49801f5b288c1118c3e5785 Signed-off-by: Sona Sarmadi Signed-off-by: Tudor Florea --- .../linux-qoriq-3.12/ipv4-CVE-2016-3156.patch | 135 +++++++++++++++++++++ recipes-kernel/linux/linux-qoriq-common.inc | 1 + 2 files changed, 136 insertions(+) create mode 100644 recipes-kernel/linux/linux-qoriq-3.12/ipv4-CVE-2016-3156.patch diff --git a/recipes-kernel/linux/linux-qoriq-3.12/ipv4-CVE-2016-3156.patch b/recipes-kernel/linux/linux-qoriq-3.12/ipv4-CVE-2016-3156.patch new file mode 100644 index 0000000..711d324 --- /dev/null +++ b/recipes-kernel/linux/linux-qoriq-3.12/ipv4-CVE-2016-3156.patch @@ -0,0 +1,135 @@ +From 5cc4ff312ac06ee4c49801f5b288c1118c3e5785 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Sun, 13 Mar 2016 23:28:00 -0400 +Subject: ipv4: Don't do expensive useless work during inetdev destroy. + +commit fbd40ea0180a2d328c5adc61414dc8bab9335ce2 upstream. + +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. + +[mk] 3.12.*: The change in masq_inet_event() needs to be duplicated in +both IPv4 and IPv6 version of the function, these two were merged in +3.18. + +CVE: CVE-2016-3156 +Upstream-Status: Backport + +Reported-by: Solar Designer +Signed-off-by: David S. Miller +Tested-by: Cyrill Gorcunov +Acked-by: Michal Kubecek +Signed-off-by: Jiri Slaby +Signed-off-by: Sona Sarmadi +--- + net/ipv4/devinet.c | 4 ++++ + net/ipv4/fib_frontend.c | 4 ++++ + net/ipv4/netfilter/ipt_MASQUERADE.c | 12 ++++++++++-- + net/ipv6/netfilter/ip6t_MASQUERADE.c | 12 ++++++++++-- + 4 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 6844710..6678beb 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -328,6 +328,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 + **/ +@@ -374,6 +377,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 f7f8cff..25a0946 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -812,6 +812,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 :-) + * +@@ -887,6 +890,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/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c +index 00352ce..3bc1c98 100644 +--- a/net/ipv4/netfilter/ipt_MASQUERADE.c ++++ b/net/ipv4/netfilter/ipt_MASQUERADE.c +@@ -128,10 +128,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); + } + +diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c +index 3e4e92d..bee09e9 100644 +--- a/net/ipv6/netfilter/ip6t_MASQUERADE.c ++++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c +@@ -88,10 +88,18 @@ static struct notifier_block masq_dev_notifier = { + static int masq_inet_event(struct notifier_block *this, + unsigned long event, void *ptr) + { +- struct inet6_ifaddr *ifa = ptr; ++ struct inet6_dev *idev = ((struct inet6_ifaddr *)ptr)->idev; + struct netdev_notifier_info info; + +- netdev_notifier_info_init(&info, ifa->idev->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 + diff --git a/recipes-kernel/linux/linux-qoriq-common.inc b/recipes-kernel/linux/linux-qoriq-common.inc index 44b4ff5..53b7bfc 100644 --- a/recipes-kernel/linux/linux-qoriq-common.inc +++ b/recipes-kernel/linux/linux-qoriq-common.inc @@ -28,6 +28,7 @@ SRC_URI += "file://b4860-hard_irq_disable-bug.patch \ file://net-unix-CVE-2013-7446.patch \ file://ALSA-CVE-2016-2546.patch \ file://ALSA-CVE-2016-2384.patch \ + file://ipv4-CVE-2016-3156.patch \ " SRC_URI += "file://cfg/00013-localversion.cfg \ -- cgit v1.2.3-54-g00ecf