From: Greg Kroah-Hartman Date: Sat, 22 Jul 2017 13:02:04 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.63~47 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd9144040a2a3a6a26e8af3a1ef7363ba762e0b5;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: ath9k-fix-tx99-bus-error.patch ath9k-fix-tx99-use-after-free.patch include-stddef.h-move-offsetofend-from-vfio.h-to-a-generic-kernel-header.patch nfc-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-handlers.patch nfc-ensure-presence-of-required-attributes-in-the-activate_target-handler.patch nfc-fix-broken-device-allocation.patch nfc-fix-the-sockaddr-length-sanitization-in-llcp_sock_connect.patch stddef.h-move-offsetofend-inside-ifndef-endif-guard-neaten.patch --- diff --git a/queue-3.18/ath9k-fix-tx99-bus-error.patch b/queue-3.18/ath9k-fix-tx99-bus-error.patch new file mode 100644 index 00000000000..f183bd2de5c --- /dev/null +++ b/queue-3.18/ath9k-fix-tx99-bus-error.patch @@ -0,0 +1,31 @@ +From bde717ab473668377fc65872398a102d40cb2d58 Mon Sep 17 00:00:00 2001 +From: Miaoqing Pan +Date: Tue, 27 Jun 2017 17:31:51 +0300 +Subject: ath9k: fix tx99 bus error + +From: Miaoqing Pan + +commit bde717ab473668377fc65872398a102d40cb2d58 upstream. + +The hard coded register 0x9864 and 0x9924 are invalid +for ar9300 chips. + +Signed-off-by: Miaoqing Pan +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1707,8 +1707,6 @@ static void ar9003_hw_spectral_scan_wait + static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) + { + REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); +- REG_SET_BIT(ah, 0x9864, 0x7f000); +- REG_SET_BIT(ah, 0x9924, 0x7f00fe); + REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); + REG_WRITE(ah, AR_CR, AR_CR_RXD); + REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); diff --git a/queue-3.18/ath9k-fix-tx99-use-after-free.patch b/queue-3.18/ath9k-fix-tx99-use-after-free.patch new file mode 100644 index 00000000000..7fe29468347 --- /dev/null +++ b/queue-3.18/ath9k-fix-tx99-use-after-free.patch @@ -0,0 +1,62 @@ +From cf8ce1ea61b75712a154c93e40f2a5af2e4dd997 Mon Sep 17 00:00:00 2001 +From: Miaoqing Pan +Date: Tue, 27 Jun 2017 17:31:49 +0300 +Subject: ath9k: fix tx99 use after free + +From: Miaoqing Pan + +commit cf8ce1ea61b75712a154c93e40f2a5af2e4dd997 upstream. + +One scenario that could lead to UAF is two threads writing +simultaneously to the "tx99" debug file. One of them would +set the "start" value to true and follow to ath9k_tx99_init(). +Inside the function it would set the sc->tx99_state to true +after allocating sc->tx99skb. Then, the other thread would +execute write_file_tx99() and call ath9k_tx99_deinit(). +sc->tx99_state would be freed. After that, the first thread +would continue inside ath9k_tx99_init() and call +r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); +that would make use of the freed sc->tx99_skb memory. + +Signed-off-by: Miaoqing Pan +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/tx99.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/tx99.c ++++ b/drivers/net/wireless/ath/ath9k/tx99.c +@@ -190,22 +190,27 @@ static ssize_t write_file_tx99(struct fi + if (strtobool(buf, &start)) + return -EINVAL; + ++ mutex_lock(&sc->mutex); ++ + if (start == sc->tx99_state) { + if (!start) +- return count; ++ goto out; + ath_dbg(common, XMIT, "Resetting TX99\n"); + ath9k_tx99_deinit(sc); + } + + if (!start) { + ath9k_tx99_deinit(sc); +- return count; ++ goto out; + } + + r = ath9k_tx99_init(sc); +- if (r) ++ if (r) { ++ mutex_unlock(&sc->mutex); + return r; +- ++ } ++out: ++ mutex_unlock(&sc->mutex); + return count; + } + diff --git a/queue-3.18/include-stddef.h-move-offsetofend-from-vfio.h-to-a-generic-kernel-header.patch b/queue-3.18/include-stddef.h-move-offsetofend-from-vfio.h-to-a-generic-kernel-header.patch new file mode 100644 index 00000000000..574ca9119a3 --- /dev/null +++ b/queue-3.18/include-stddef.h-move-offsetofend-from-vfio.h-to-a-generic-kernel-header.patch @@ -0,0 +1,68 @@ +From 3876488444e71238e287459c39d7692b6f718c3e Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Mon, 9 Mar 2015 15:52:17 +0100 +Subject: include/stddef.h: Move offsetofend() from vfio.h to a generic kernel header + +From: Denys Vlasenko + +commit 3876488444e71238e287459c39d7692b6f718c3e upstream. + +Suggested by Andy. + +Suggested-by: Andy Lutomirski +Signed-off-by: Denys Vlasenko +Acked-by: Linus Torvalds +Cc: Alexei Starovoitov +Cc: Borislav Petkov +Cc: Frederic Weisbecker +Cc: H. Peter Anvin +Cc: Kees Cook +Cc: Oleg Nesterov +Cc: Steven Rostedt +Cc: Will Drewry +Link: http://lkml.kernel.org/r/1425912738-559-1-git-send-email-dvlasenk@redhat.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/stddef.h | 9 +++++++++ + include/linux/vfio.h | 13 ------------- + 2 files changed, 9 insertions(+), 13 deletions(-) + +--- a/include/linux/stddef.h ++++ b/include/linux/stddef.h +@@ -19,3 +19,12 @@ enum { + #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + #endif + #endif ++ ++/** ++ * offsetofend(TYPE, MEMBER) ++ * ++ * @TYPE: The type of the structure ++ * @MEMBER: The member within the structure to get the end offset of ++ */ ++#define offsetofend(TYPE, MEMBER) \ ++ (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) +--- a/include/linux/vfio.h ++++ b/include/linux/vfio.h +@@ -76,19 +76,6 @@ extern int vfio_register_iommu_driver(co + extern void vfio_unregister_iommu_driver( + const struct vfio_iommu_driver_ops *ops); + +-/** +- * offsetofend(TYPE, MEMBER) +- * +- * @TYPE: The type of the structure +- * @MEMBER: The member within the structure to get the end offset of +- * +- * Simple helper macro for dealing with variable sized structures passed +- * from user space. This allows us to easily determine if the provided +- * structure is sized to include various fields. +- */ +-#define offsetofend(TYPE, MEMBER) \ +- (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) +- + /* + * External user API + */ diff --git a/queue-3.18/nfc-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-handlers.patch b/queue-3.18/nfc-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-handlers.patch new file mode 100644 index 00000000000..77fd46822e5 --- /dev/null +++ b/queue-3.18/nfc-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-handlers.patch @@ -0,0 +1,45 @@ +From f6a5885fc4d68e7f25ffb42b9d8d80aebb3bacbb Mon Sep 17 00:00:00 2001 +From: Mateusz Jurczyk +Date: Tue, 13 Jun 2017 18:44:28 +0200 +Subject: NFC: Add sockaddr length checks before accessing sa_family in bind handlers + +From: Mateusz Jurczyk + +commit f6a5885fc4d68e7f25ffb42b9d8d80aebb3bacbb upstream. + +Verify that the caller-provided sockaddr structure is large enough to +contain the sa_family field, before accessing it in bind() handlers of the +AF_NFC socket. Since the syscall doesn't enforce a minimum size of the +corresponding memory region, very short sockaddrs (zero or one byte long) +result in operating on uninitialized memory while referencing .sa_family. + +Signed-off-by: Mateusz Jurczyk +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + net/nfc/llcp_sock.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -76,7 +76,8 @@ static int llcp_sock_bind(struct socket + struct sockaddr_nfc_llcp llcp_addr; + int len, ret = 0; + +- if (!addr || addr->sa_family != AF_NFC) ++ if (!addr || alen < offsetofend(struct sockaddr, sa_family) || ++ addr->sa_family != AF_NFC) + return -EINVAL; + + pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); +@@ -150,7 +151,8 @@ static int llcp_raw_sock_bind(struct soc + struct sockaddr_nfc_llcp llcp_addr; + int len, ret = 0; + +- if (!addr || addr->sa_family != AF_NFC) ++ if (!addr || alen < offsetofend(struct sockaddr, sa_family) || ++ addr->sa_family != AF_NFC) + return -EINVAL; + + pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); diff --git a/queue-3.18/nfc-ensure-presence-of-required-attributes-in-the-activate_target-handler.patch b/queue-3.18/nfc-ensure-presence-of-required-attributes-in-the-activate_target-handler.patch new file mode 100644 index 00000000000..7ecc607d928 --- /dev/null +++ b/queue-3.18/nfc-ensure-presence-of-required-attributes-in-the-activate_target-handler.patch @@ -0,0 +1,37 @@ +From a0323b979f81ad2deb2c8836eab506534891876a Mon Sep 17 00:00:00 2001 +From: Mateusz Jurczyk +Date: Wed, 24 May 2017 12:42:26 +0200 +Subject: nfc: Ensure presence of required attributes in the activate_target handler + +From: Mateusz Jurczyk + +commit a0323b979f81ad2deb2c8836eab506534891876a upstream. + +Check that the NFC_ATTR_TARGET_INDEX and NFC_ATTR_PROTOCOLS attributes (in +addition to NFC_ATTR_DEVICE_INDEX) are provided by the netlink client +prior to accessing them. This prevents potential unhandled NULL pointer +dereference exceptions which can be triggered by malicious user-mode +programs, if they omit one or both of these attributes. + +Signed-off-by: Mateusz Jurczyk +Acked-by: Kees Cook +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + net/nfc/netlink.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -899,7 +899,9 @@ static int nfc_genl_llc_get_params(struc + struct sk_buff *msg = NULL; + u32 idx; + +- if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) ++ if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || ++ !info->attrs[NFC_ATTR_TARGET_INDEX] || ++ !info->attrs[NFC_ATTR_PROTOCOLS]) + return -EINVAL; + + idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); diff --git a/queue-3.18/nfc-fix-broken-device-allocation.patch b/queue-3.18/nfc-fix-broken-device-allocation.patch new file mode 100644 index 00000000000..f9d105ff0a8 --- /dev/null +++ b/queue-3.18/nfc-fix-broken-device-allocation.patch @@ -0,0 +1,126 @@ +From 20777bc57c346b6994f465e0d8261a7fbf213a09 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 30 Mar 2017 12:15:35 +0200 +Subject: NFC: fix broken device allocation + +From: Johan Hovold + +commit 20777bc57c346b6994f465e0d8261a7fbf213a09 upstream. + +Commit 7eda8b8e9677 ("NFC: Use IDR library to assing NFC devices IDs") +moved device-id allocation and struct-device initialisation from +nfc_allocate_device() to nfc_register_device(). + +This broke just about every nfc-device-registration error path, which +continue to call nfc_free_device() that tries to put the device +reference of the now uninitialised (but zeroed) struct device: + +kobject: '(null)' (ce316420): is not initialized, yet kobject_put() is being called. + +The late struct-device initialisation also meant that various work +queues whose names are derived from the nfc device name were also +misnamed: + + 421 root 0 SW< [(null)_nci_cmd_] + 422 root 0 SW< [(null)_nci_rx_w] + 423 root 0 SW< [(null)_nci_tx_w] + +Move the id-allocation and struct-device initialisation back to +nfc_allocate_device() and fix up the single call site which did not use +nfc_free_device() in its error path. + +Fixes: 7eda8b8e9677 ("NFC: Use IDR library to assing NFC devices IDs") +Cc: Samuel Ortiz +Signed-off-by: Johan Hovold +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + net/nfc/core.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +--- a/net/nfc/core.c ++++ b/net/nfc/core.c +@@ -950,6 +950,8 @@ static void nfc_release(struct device *d + kfree(se); + } + ++ ida_simple_remove(&nfc_index_ida, dev->idx); ++ + kfree(dev); + } + +@@ -1024,6 +1026,7 @@ struct nfc_dev *nfc_allocate_device(stru + int tx_headroom, int tx_tailroom) + { + struct nfc_dev *dev; ++ int rc; + + if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || + !ops->deactivate_target || !ops->im_transceive) +@@ -1036,6 +1039,15 @@ struct nfc_dev *nfc_allocate_device(stru + if (!dev) + return NULL; + ++ rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); ++ if (rc < 0) ++ goto err_free_dev; ++ dev->idx = rc; ++ ++ dev->dev.class = &nfc_class; ++ dev_set_name(&dev->dev, "nfc%d", dev->idx); ++ device_initialize(&dev->dev); ++ + dev->ops = ops; + dev->supported_protocols = supported_protocols; + dev->tx_headroom = tx_headroom; +@@ -1058,6 +1070,11 @@ struct nfc_dev *nfc_allocate_device(stru + } + + return dev; ++ ++err_free_dev: ++ kfree(dev); ++ ++ return ERR_PTR(rc); + } + EXPORT_SYMBOL(nfc_allocate_device); + +@@ -1072,14 +1089,6 @@ int nfc_register_device(struct nfc_dev * + + pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + +- dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); +- if (dev->idx < 0) +- return dev->idx; +- +- dev->dev.class = &nfc_class; +- dev_set_name(&dev->dev, "nfc%d", dev->idx); +- device_initialize(&dev->dev); +- + mutex_lock(&nfc_devlist_mutex); + nfc_devlist_generation++; + rc = device_add(&dev->dev); +@@ -1117,12 +1126,10 @@ EXPORT_SYMBOL(nfc_register_device); + */ + void nfc_unregister_device(struct nfc_dev *dev) + { +- int rc, id; ++ int rc; + + pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + +- id = dev->idx; +- + if (dev->rfkill) { + rfkill_unregister(dev->rfkill); + rfkill_destroy(dev->rfkill); +@@ -1147,8 +1154,6 @@ void nfc_unregister_device(struct nfc_de + nfc_devlist_generation++; + device_del(&dev->dev); + mutex_unlock(&nfc_devlist_mutex); +- +- ida_simple_remove(&nfc_index_ida, id); + } + EXPORT_SYMBOL(nfc_unregister_device); + diff --git a/queue-3.18/nfc-fix-the-sockaddr-length-sanitization-in-llcp_sock_connect.patch b/queue-3.18/nfc-fix-the-sockaddr-length-sanitization-in-llcp_sock_connect.patch new file mode 100644 index 00000000000..7dda5534374 --- /dev/null +++ b/queue-3.18/nfc-fix-the-sockaddr-length-sanitization-in-llcp_sock_connect.patch @@ -0,0 +1,51 @@ +From 608c4adfcabab220142ee335a2a003ccd1c0b25b Mon Sep 17 00:00:00 2001 +From: Mateusz Jurczyk +Date: Wed, 24 May 2017 12:26:20 +0200 +Subject: nfc: Fix the sockaddr length sanitization in llcp_sock_connect + +From: Mateusz Jurczyk + +commit 608c4adfcabab220142ee335a2a003ccd1c0b25b upstream. + +Fix the sockaddr length verification in the connect() handler of NFC/LLCP +sockets, to compare against the size of the actual structure expected on +input (sockaddr_nfc_llcp) instead of its shorter version (sockaddr_nfc). + +Both structures are defined in include/uapi/linux/nfc.h. The fields +specific to the _llcp extended struct are as follows: + + 276 __u8 dsap; /* Destination SAP, if known */ + 277 __u8 ssap; /* Source SAP to be bound to */ + 278 char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */; + 279 size_t service_name_len; + +If the caller doesn't provide a sufficiently long sockaddr buffer, these +fields remain uninitialized (and they currently originate from the stack +frame of the top-level sys_connect handler). They are then copied by +llcp_sock_connect() into internal storage (nfc_llcp_sock structure), and +could be subsequently read back through the user-mode getsockname() +function (handled by llcp_sock_getname()). This would result in the +disclosure of up to ~70 uninitialized bytes from the kernel stack to +user-mode clients capable of creating AFC_NFC sockets. + +Signed-off-by: Mateusz Jurczyk +Acked-by: Kees Cook +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + net/nfc/llcp_sock.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -655,8 +655,7 @@ static int llcp_sock_connect(struct sock + + pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); + +- if (!addr || len < sizeof(struct sockaddr_nfc) || +- addr->sa_family != AF_NFC) ++ if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC) + return -EINVAL; + + if (addr->service_name_len == 0 && addr->dsap == 0) diff --git a/queue-3.18/series b/queue-3.18/series index 81002b14553..2b15884acd7 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -3,3 +3,11 @@ kvm-x86-memset-whole-irq_eoi.patch x86-rtc-remove-duplicate-const-specifier.patch ir-core-fix-gcc-7-warning-on-bool-arithmetic.patch cifs-fix-handle_cancelled_mid-callback-initialization.patch +ath9k-fix-tx99-use-after-free.patch +ath9k-fix-tx99-bus-error.patch +nfc-fix-broken-device-allocation.patch +nfc-ensure-presence-of-required-attributes-in-the-activate_target-handler.patch +nfc-fix-the-sockaddr-length-sanitization-in-llcp_sock_connect.patch +include-stddef.h-move-offsetofend-from-vfio.h-to-a-generic-kernel-header.patch +stddef.h-move-offsetofend-inside-ifndef-endif-guard-neaten.patch +nfc-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-handlers.patch diff --git a/queue-3.18/stddef.h-move-offsetofend-inside-ifndef-endif-guard-neaten.patch b/queue-3.18/stddef.h-move-offsetofend-inside-ifndef-endif-guard-neaten.patch new file mode 100644 index 00000000000..a600caa2d81 --- /dev/null +++ b/queue-3.18/stddef.h-move-offsetofend-inside-ifndef-endif-guard-neaten.patch @@ -0,0 +1,57 @@ +From 8c7fbe5795a016259445a61e072eb0118aaf6a61 Mon Sep 17 00:00:00 2001 +From: Joe Perches +Date: Thu, 25 Jun 2015 15:01:16 -0700 +Subject: stddef.h: move offsetofend inside #ifndef/#endif guard, neaten + +From: Joe Perches + +commit 8c7fbe5795a016259445a61e072eb0118aaf6a61 upstream. + +Commit 3876488444e7 ("include/stddef.h: Move offsetofend() from vfio.h +to a generic kernel header") added offsetofend outside the normal +include #ifndef/#endif guard. Move it inside. + +Miscellanea: + +o remove unnecessary blank line +o standardize offsetof macros whitespace style + +Signed-off-by: Joe Perches +Cc: Denys Vlasenko +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/stddef.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/include/linux/stddef.h ++++ b/include/linux/stddef.h +@@ -3,7 +3,6 @@ + + #include + +- + #undef NULL + #define NULL ((void *)0) + +@@ -14,10 +13,9 @@ enum { + + #undef offsetof + #ifdef __compiler_offsetof +-#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) ++#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER) + #else +-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +-#endif ++#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER) + #endif + + /** +@@ -28,3 +26,5 @@ enum { + */ + #define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) ++ ++#endif