From 27fc4207c6318c9f4666a00a8f858170df9ac28f Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Wed, 7 Dec 2016 10:30:04 +0100 Subject: [PATCH] tipc: check minimum bearer MTU (CVE-2016-8632) --- debian/changelog | 3 + .../all/tipc-check-minimum-bearer-MTU.patch | 122 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 126 insertions(+) create mode 100644 debian/patches/bugfix/all/tipc-check-minimum-bearer-MTU.patch diff --git a/debian/changelog b/debian/changelog index cfd07147e..9452a9a50 100644 --- a/debian/changelog +++ b/debian/changelog @@ -43,6 +43,9 @@ linux (4.8.12-1) UNRELEASED; urgency=medium * [armel] dts: marvell: fix number of sata port for linkstation ls-gl (Closes: #845611) + [ Salvatore Bonaccorso ] + * tipc: check minimum bearer MTU (CVE-2016-8632) + -- Uwe Kleine-König Sun, 04 Dec 2016 21:16:06 +0100 linux (4.8.11-1) unstable; urgency=medium diff --git a/debian/patches/bugfix/all/tipc-check-minimum-bearer-MTU.patch b/debian/patches/bugfix/all/tipc-check-minimum-bearer-MTU.patch new file mode 100644 index 000000000..f946eae8e --- /dev/null +++ b/debian/patches/bugfix/all/tipc-check-minimum-bearer-MTU.patch @@ -0,0 +1,122 @@ +From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= +Date: Fri, 2 Dec 2016 09:33:41 +0100 +Subject: tipc: check minimum bearer MTU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Origin: https://git.kernel.org/linus/3de81b758853f0b29c61e246679d20b513c4cfec + +Qian Zhang (张谦) reported a potential socket buffer overflow in +tipc_msg_build() which is also known as CVE-2016-8632: due to +insufficient checks, a buffer overflow can occur if MTU is too short for +even tipc headers. As anyone can set device MTU in a user/net namespace, +this issue can be abused by a regular user. + +As agreed in the discussion on Ben Hutchings' original patch, we should +check the MTU at the moment a bearer is attached rather than for each +processed packet. We also need to repeat the check when bearer MTU is +adjusted to new device MTU. UDP case also needs a check to avoid +overflow when calculating bearer MTU. + +Fixes: b97bf3fd8f6a ("[TIPC] Initial merge") +Signed-off-by: Michal Kubecek +Reported-by: Qian Zhang (张谦) +Acked-by: Ying Xue +Signed-off-by: David S. Miller +--- + net/tipc/bearer.c | 11 +++++++++-- + net/tipc/bearer.h | 13 +++++++++++++ + net/tipc/udp_media.c | 5 +++++ + 3 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c +index 975dbeb..52d7476 100644 +--- a/net/tipc/bearer.c ++++ b/net/tipc/bearer.c +@@ -421,6 +421,10 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, + dev = dev_get_by_name(net, driver_name); + if (!dev) + return -ENODEV; ++ if (tipc_mtu_bad(dev, 0)) { ++ dev_put(dev); ++ return -EINVAL; ++ } + + /* Associate TIPC bearer with L2 bearer */ + rcu_assign_pointer(b->media_ptr, dev); +@@ -610,8 +614,6 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, + if (!b) + return NOTIFY_DONE; + +- b->mtu = dev->mtu; +- + switch (evt) { + case NETDEV_CHANGE: + if (netif_carrier_ok(dev)) +@@ -624,6 +626,11 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, + tipc_reset_bearer(net, b); + break; + case NETDEV_CHANGEMTU: ++ if (tipc_mtu_bad(dev, 0)) { ++ bearer_disable(net, b); ++ break; ++ } ++ b->mtu = dev->mtu; + tipc_reset_bearer(net, b); + break; + case NETDEV_CHANGEADDR: +diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h +index 78892e2f..278ff7f 100644 +--- a/net/tipc/bearer.h ++++ b/net/tipc/bearer.h +@@ -39,6 +39,7 @@ + + #include "netlink.h" + #include "core.h" ++#include "msg.h" + #include + + #define MAX_MEDIA 3 +@@ -59,6 +60,9 @@ + #define TIPC_MEDIA_TYPE_IB 2 + #define TIPC_MEDIA_TYPE_UDP 3 + ++/* minimum bearer MTU */ ++#define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + INT_H_SIZE) ++ + /** + * struct tipc_media_addr - destination address used by TIPC bearers + * @value: address info (format defined by media) +@@ -215,4 +219,13 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, + void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, + struct sk_buff_head *xmitq); + ++/* check if device MTU is too low for tipc headers */ ++static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) ++{ ++ if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve) ++ return false; ++ netdev_warn(dev, "MTU too low for tipc bearer\n"); ++ return true; ++} ++ + #endif /* _TIPC_BEARER_H */ +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index 78cab9c..b58dc95 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -697,6 +697,11 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, + udp_conf.local_ip.s_addr = htonl(INADDR_ANY); + udp_conf.use_udp_checksums = false; + ub->ifindex = dev->ifindex; ++ if (tipc_mtu_bad(dev, sizeof(struct iphdr) + ++ sizeof(struct udphdr))) { ++ err = -EINVAL; ++ goto err; ++ } + b->mtu = dev->mtu - sizeof(struct iphdr) + - sizeof(struct udphdr); + #if IS_ENABLED(CONFIG_IPV6) +-- +2.1.4 + diff --git a/debian/patches/series b/debian/patches/series index 021bb64a7..a27b8e6f1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -102,6 +102,7 @@ bugfix/all/fs-Give-dentry-to-inode_change_ok-instead-of-inode.patch bugfix/all/fs-Avoid-premature-clearing-of-capabilities.patch bugfix/all/vfio-pci-Fix-integer-overflows-bitmask-check.patch bugfix/all/mnt-Add-a-per-mount-namespace-limit-on-the-number-of.patch +bugfix/all/tipc-check-minimum-bearer-MTU.patch # ABI maintenance