From 78fbe21d83e39e74f4b479a2978375ab7aaf3e37 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 12 Jul 2017 19:25:47 -0700 Subject: disable new gcc-7.1.1 warnings for now commit bd664f6b3e376a8ef4990f87d08271cc2d01ba9a upstream. I made the mistake of upgrading my desktop to the new Fedora 26 that comes with gcc-7.1.1. There's nothing wrong per se that I've noticed, but I now have 1500 lines of warnings, mostly from the new format-truncation warning triggering all over the tree. We use 'snprintf()' and friends in a lot of places, and often know that the numbers are fairly small (ie a controller index or similar), but gcc doesn't know that, and sees an 'int', and thinks that it could be some huge number. And then complains when our buffers are not able to fit the name for the ten millionth controller. These warnings aren't necessarily bad per se, and we probably want to look through them subsystem by subsystem, but at least during the merge window they just mean that I can't even see if somebody is introducing any *real* problems when I pull. So warnings disabled for now. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman diff --git a/Makefile b/Makefile index a872ece..0a2c352 100644 --- a/Makefile +++ b/Makefile @@ -629,6 +629,9 @@ include arch/$(SRCARCH)/Makefile KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) +KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) +KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) +KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,) -- cgit v0.10.2 From 70ec6b3635d95983e1fbcfb1c765cd7d2abd0ac8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 May 2017 08:46:44 -0300 Subject: ir-core: fix gcc-7 warning on bool arithmetic commit bd7e31bbade02bc1e92aa00d5cf2cee2da66838a upstream. gcc-7 suggests that an expression using a bitwise not and a bitmask on a 'bool' variable is better written using boolean logic: drivers/media/rc/imon.c: In function 'imon_incoming_scancode': drivers/media/rc/imon.c:1725:22: error: '~' on a boolean expression [-Werror=bool-operation] ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; ^ drivers/media/rc/imon.c:1725:22: note: did you mean to use logical not? I agree. Fixes: 21677cfc562a ("V4L/DVB: ir-core: add imon driver") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 86cc70fe25..2d4b836 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1629,7 +1629,7 @@ static void imon_incoming_packet(struct imon_context *ictx, if (kc == KEY_KEYBOARD && !ictx->release_code) { ictx->last_keycode = kc; if (!nomouse) { - ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; + ictx->pad_mouse = !ictx->pad_mouse; dev_dbg(dev, "toggling to %s mode\n", ictx->pad_mouse ? "mouse" : "keyboard"); spin_unlock_irqrestore(&ictx->kc_lock, flags); -- cgit v0.10.2 From 63d32e8af0dd6343cde33993eabc9c7562d92fe9 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 6 Jan 2017 15:33:14 -0500 Subject: dm mpath: cleanup -Wbool-operation warning in choose_pgpath() commit d19a55ccad15a486ffe03030570744e5d5bd9f8e upstream. Reported-by: David Binderman Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index ac8235b..0d437c9 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -431,7 +431,7 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes) unsigned long flags; struct priority_group *pg; struct pgpath *pgpath; - bool bypassed = true; + unsigned bypassed = 1; if (!atomic_read(&m->nr_valid_paths)) { clear_bit(MPATHF_QUEUE_IO, &m->flags); @@ -470,7 +470,7 @@ check_current_pg: */ do { list_for_each_entry(pg, &m->priority_groups, list) { - if (pg->bypassed == bypassed) + if (pg->bypassed == !!bypassed) continue; pgpath = choose_path_in_pg(m, pg, nr_bytes); if (!IS_ERR_OR_NULL(pgpath)) { -- cgit v0.10.2 From 60813b6a2ab40c8ad7f5e44819fe6e44fa4b459a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 May 2017 10:40:00 -0300 Subject: s5p-jpeg: don't return a random width/height commit a16e37726c444cbda91e73ed5f742e717bfe866f upstream. Gcc 7.1 complains about: drivers/media/platform/s5p-jpeg/jpeg-core.c: In function 's5p_jpeg_parse_hdr.isra.9': drivers/media/platform/s5p-jpeg/jpeg-core.c:1207:12: warning: 'width' may be used uninitialized in this function [-Wmaybe-uninitialized] result->w = width; ~~~~~~~~~~^~~~~~~ drivers/media/platform/s5p-jpeg/jpeg-core.c:1208:12: warning: 'height' may be used uninitialized in this function [-Wmaybe-uninitialized] result->h = height; ~~~~~~~~~~^~~~~~~~ Indeed the code would allow it to return a random value (although it shouldn't happen, in practice). So, explicitly set both to zero, just in case. Acked-by: Andrzej Pietrasiewicz Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc794..1da2c94 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1099,10 +1099,10 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, struct s5p_jpeg_ctx *ctx) { int c, components = 0, notfound, n_dht = 0, n_dqt = 0; - unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0, - sof_len = 0; - unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER], - dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; + unsigned int height = 0, width = 0, word, subsampling = 0; + unsigned int sos = 0, sof = 0, sof_len = 0; + unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER]; + unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; long length; struct s5p_jpeg_buffer jpeg_buffer; -- cgit v0.10.2 From 76572609e45895826f4bf49c376271dc62f125dc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:59:03 +0200 Subject: thermal: max77620: fix device-node reference imbalance commit c592fafbdbb6b1279b76a54722d1465ca77e5bde upstream. The thermal child device reuses the parent MFD-device device-tree node when registering a thermal zone, but did not take a reference to the node. This leads to a reference imbalance, and potential use-after-free, when the node reference is dropped by the platform-bus device destructor (once for the child and later again for the parent). Fix this by dropping any reference already held to a device-tree node and getting a reference to the parent's node which will be balanced on reprobe or on platform-device release, whichever comes first. Note that simply clearing the of_node pointer on probe errors and on driver unbind would not allow the use of device-managed resources as specifically thermal_zone_of_sensor_unregister() claims that a valid device-tree node pointer is needed during deregistration (even if it currently does not seem to use it). Fixes: ec4664b3fd6d ("thermal: max77620: Add thermal driver for reporting junction temp") Cc: Laxman Dewangan Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c index 83905ff..7e98927 100644 --- a/drivers/thermal/max77620_thermal.c +++ b/drivers/thermal/max77620_thermal.c @@ -104,8 +104,6 @@ static int max77620_thermal_probe(struct platform_device *pdev) return -EINVAL; } - pdev->dev.of_node = pdev->dev.parent->of_node; - mtherm->dev = &pdev->dev; mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL); if (!mtherm->rmap) { @@ -113,6 +111,14 @@ static int max77620_thermal_probe(struct platform_device *pdev) return -ENODEV; } + /* + * Drop any current reference to a device-tree node and get a + * reference to the parent's node which will be balanced on reprobe or + * on platform-device release. + */ + of_node_put(pdev->dev.of_node); + pdev->dev.of_node = of_node_get(pdev->dev.parent->of_node); + mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, mtherm, &max77620_thermal_ops); if (IS_ERR(mtherm->tz_device)) { -- cgit v0.10.2 From 7cd7b56037ae4cbdfe5e7fa9e41b67ba15199d7f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 25 Apr 2017 15:57:08 +0530 Subject: thermal: cpu_cooling: Avoid accessing potentially freed structures commit 289d72afddf83440117c35d864bf0c6309c1d011 upstream. After the lock is dropped, it is possible that the cpufreq_dev gets freed before we call get_level() and that can cause kernel to crash. Drop the lock after we are done using the structure. Fixes: 02373d7c69b4 ("thermal: cpu_cooling: fix lockdep problems in cpu_cooling") Signed-off-by: Viresh Kumar Reviewed-by: Lukasz Luba Tested-by: Lukasz Luba Signed-off-by: Eduardo Valentin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 9ce0e9e..f49d298 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -191,8 +191,10 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) mutex_lock(&cooling_list_lock); list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) { + unsigned long level = get_level(cpufreq_dev, freq); + mutex_unlock(&cooling_list_lock); - return get_level(cpufreq_dev, freq); + return level; } } mutex_unlock(&cooling_list_lock); -- cgit v0.10.2 From b729a1aea14d482e8a29186bd4a930282961a43c 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 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 diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 16aca9e..1fa7f84 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -189,22 +189,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, 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; } -- cgit v0.10.2 From 99f96831083bb23dff471ff1b4e16cc8370ecaec 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 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 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ae304355..fe5102c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1821,8 +1821,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) 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); -- cgit v0.10.2 From 48879676a8c3f481e1ae51ccde6d6e7515753476 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:53 +0300 Subject: ath9k: fix an invalid pointer dereference in ath9k_rng_stop() commit 07246c115801c27652700e3679bb58661ef7ed65 upstream. The bug was triggered when do suspend/resuming continuously on Dell XPS L322X/0PJHXN version 9333 (2013) with kernel 4.12.0-041200rc4-generic. But can't reproduce on DELL E5440 + AR9300 PCIE chips. The warning is caused by accessing invalid pointer sc->rng_task. sc->rng_task is not be cleared after kthread_stop(sc->rng_task) be called in ath9k_rng_stop(). Because the kthread is stopped before ath9k_rng_kthread() be scheduled. So set sc->rng_task to null after kthread_stop(sc->rng_task) to resolve this issue. WARNING: CPU: 0 PID: 984 at linux/kernel/kthread.c:71 kthread_stop+0xf1/0x100 CPU: 0 PID: 984 Comm: NetworkManager Not tainted 4.12.0-041200rc4-generic #201706042031 Hardware name: Dell Inc. Dell System XPS L322X/0PJHXN, BIOS A09 05/15/2013 task: ffff950170fdda00 task.stack: ffffa22c01538000 RIP: 0010:kthread_stop+0xf1/0x100 RSP: 0018:ffffa22c0153b5b0 EFLAGS: 00010246 RAX: ffffffffa6257800 RBX: ffff950171b79560 RCX: 0000000000000000 RDX: 0000000080000000 RSI: 000000007fffffff RDI: ffff9500ac9a9680 RBP: ffffa22c0153b5c8 R08: 0000000000000000 R09: 0000000000000000 R10: ffffa22c0153b648 R11: ffff9501768004b8 R12: ffff9500ac9a9680 R13: ffff950171b79f70 R14: ffff950171b78780 R15: ffff9501749dc018 FS: 00007f0d6bfd5540(0000) GS:ffff95017f200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fc190161a08 CR3: 0000000232906000 CR4: 00000000001406f0 Call Trace: ath9k_rng_stop+0x1a/0x20 [ath9k] ath9k_stop+0x3b/0x1d0 [ath9k] drv_stop+0x33/0xf0 [mac80211] ieee80211_stop_device+0x43/0x50 [mac80211] ieee80211_do_stop+0x4f2/0x810 [mac80211] Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196043 Reported-by: Giulio Genovese Tested-by: Giulio Genovese Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c index d38e50f..e0374eb 100644 --- a/drivers/net/wireless/ath/ath9k/rng.c +++ b/drivers/net/wireless/ath/ath9k/rng.c @@ -120,6 +120,8 @@ void ath9k_rng_start(struct ath_softc *sc) void ath9k_rng_stop(struct ath_softc *sc) { - if (sc->rng_task) + if (sc->rng_task) { kthread_stop(sc->rng_task); + sc->rng_task = NULL; + } } -- cgit v0.10.2 From f73de3f9915c997dd091cadcdbafbdb9835f2cf5 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 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 diff --git a/net/nfc/core.c b/net/nfc/core.c index 122bb81..5cf33df 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -982,6 +982,8 @@ static void nfc_release(struct device *d) kfree(se); } + ida_simple_remove(&nfc_index_ida, dev->idx); + kfree(dev); } @@ -1056,6 +1058,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, 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) @@ -1068,6 +1071,15 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, 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; @@ -1090,6 +1102,11 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, } return dev; + +err_free_dev: + kfree(dev); + + return ERR_PTR(rc); } EXPORT_SYMBOL(nfc_allocate_device); @@ -1104,14 +1121,6 @@ int nfc_register_device(struct nfc_dev *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); @@ -1149,12 +1158,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); @@ -1179,8 +1186,6 @@ void nfc_unregister_device(struct nfc_dev *dev) 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/net/nfc/nci/core.c b/net/nfc/nci/core.c index 61fff42..85a3d9e 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -1173,8 +1173,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, return ndev; free_nfc: - kfree(ndev->nfc_dev); - + nfc_free_device(ndev->nfc_dev); free_nci: kfree(ndev); return NULL; -- cgit v0.10.2 From 7de6ff402dd02cbfc6b963068efd6efecc0e4978 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Mar 2017 12:15:36 +0200 Subject: NFC: nfcmrvl_uart: add missing tty-device sanity check commit 15e0c59f1535926a939d1df66d6edcf997d7c1b9 upstream. Make sure to check the tty-device pointer before trying to access the parent device to avoid dereferencing a NULL-pointer when the tty is one end of a Unix98 pty. Fixes: e097dc624f78 ("NFC: nfcmrvl: add UART driver") Cc: Vincent Cuissard Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c index 83a99e3..6c0c301 100644 --- a/drivers/nfc/nfcmrvl/uart.c +++ b/drivers/nfc/nfcmrvl/uart.c @@ -109,6 +109,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) struct nfcmrvl_private *priv; struct nfcmrvl_platform_data *pdata = NULL; struct nfcmrvl_platform_data config; + struct device *dev = nu->tty->dev; /* * Platform data cannot be used here since usually it is already used @@ -116,9 +117,8 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) * and check if DT entries were added. */ - if (nu->tty->dev->parent && nu->tty->dev->parent->of_node) - if (nfcmrvl_uart_parse_dt(nu->tty->dev->parent->of_node, - &config) == 0) + if (dev && dev->parent && dev->parent->of_node) + if (nfcmrvl_uart_parse_dt(dev->parent->of_node, &config) == 0) pdata = &config; if (!pdata) { @@ -131,7 +131,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) } priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_UART, nu, &uart_ops, - nu->tty->dev, pdata); + dev, pdata); if (IS_ERR(priv)) return PTR_ERR(priv); -- cgit v0.10.2 From 4b4f74d6c4f801aee5add0cab1d68904e6141380 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Mar 2017 12:15:37 +0200 Subject: NFC: nfcmrvl: do not use device-managed resources commit 0cbe40112f42cf5e008f9127f6cd5952ba3946c7 upstream. This specifically fixes resource leaks in the registration error paths. Device-managed resources is a bad fit for this driver as devices can be registered from the n_nci line discipline. Firstly, a tty may not even have a corresponding device (should it be part of a Unix98 pty) something which would lead to a NULL-pointer dereference when registering resources. Secondly, if the tty has a class device, its lifetime exceeds that of the line discipline, which means that resources would leak every time the line discipline is closed (or if registration fails). Currently, the devres interface was only being used to request a reset gpio despite the fact that it was already explicitly freed in nfcmrvl_nci_unregister_dev() (along with the private data), something which also prevented the resource leak at close. Note that the driver treats gpio number 0 as invalid despite it being perfectly valid. This will be addressed in a follow-up patch. Fixes: b2fe288eac72 ("NFC: nfcmrvl: free reset gpio") Fixes: 4a2b947f56b3 ("NFC: nfcmrvl: add chip reset management") Cc: Vincent Cuissard Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c index 51c8240..3e3fc95 100644 --- a/drivers/nfc/nfcmrvl/main.c +++ b/drivers/nfc/nfcmrvl/main.c @@ -124,12 +124,13 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, memcpy(&priv->config, pdata, sizeof(*pdata)); if (priv->config.reset_n_io) { - rc = devm_gpio_request_one(dev, - priv->config.reset_n_io, - GPIOF_OUT_INIT_LOW, - "nfcmrvl_reset_n"); - if (rc < 0) + rc = gpio_request_one(priv->config.reset_n_io, + GPIOF_OUT_INIT_LOW, + "nfcmrvl_reset_n"); + if (rc < 0) { + priv->config.reset_n_io = 0; nfc_err(dev, "failed to request reset_n io\n"); + } } if (phy == NFCMRVL_PHY_SPI) { @@ -154,7 +155,7 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, if (!priv->ndev) { nfc_err(dev, "nci_allocate_device failed\n"); rc = -ENOMEM; - goto error; + goto error_free_gpio; } nci_set_drvdata(priv->ndev, priv); @@ -179,7 +180,9 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, error_free_dev: nci_free_device(priv->ndev); -error: +error_free_gpio: + if (priv->config.reset_n_io) + gpio_free(priv->config.reset_n_io); kfree(priv); return ERR_PTR(rc); } @@ -195,7 +198,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) nfcmrvl_fw_dnld_deinit(priv); if (priv->config.reset_n_io) - devm_gpio_free(priv->dev, priv->config.reset_n_io); + gpio_free(priv->config.reset_n_io); nci_unregister_device(ndev); nci_free_device(ndev); -- cgit v0.10.2 From 10f03f0f7ef0ee456369b2940e092e0225c754a6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Mar 2017 12:15:38 +0200 Subject: NFC: nfcmrvl: use nfc-device for firmware download commit e5834ac22948169bbd7c45996d8d4905edd20f5e upstream. Use the nfc- rather than phy-device in firmware-management code that needs a valid struct device. This specifically fixes a NULL-pointer dereference in nfcmrvl_fw_dnld_init() during registration when the underlying tty is one end of a Unix98 pty. Note that the driver still uses the phy device for any debugging, which is fine for now. Fixes: 3194c6870158 ("NFC: nfcmrvl: add firmware download support") Cc: Vincent Cuissard Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c index f8dcdf4..af62c4c 100644 --- a/drivers/nfc/nfcmrvl/fw_dnld.c +++ b/drivers/nfc/nfcmrvl/fw_dnld.c @@ -459,7 +459,7 @@ int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv) INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work); snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq", - dev_name(priv->dev)); + dev_name(&priv->ndev->nfc_dev->dev)); priv->fw_dnld.rx_wq = create_singlethread_workqueue(name); if (!priv->fw_dnld.rx_wq) return -ENOMEM; @@ -496,6 +496,7 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name) { struct nfcmrvl_private *priv = nci_get_drvdata(ndev); struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld; + int res; if (!priv->support_fw_dnld) return -ENOTSUPP; @@ -511,7 +512,9 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name) */ /* Retrieve FW binary */ - if (request_firmware(&fw_dnld->fw, firmware_name, priv->dev) < 0) { + res = request_firmware(&fw_dnld->fw, firmware_name, + &ndev->nfc_dev->dev); + if (res < 0) { nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name); return -ENOENT; } -- cgit v0.10.2 From 06be8e2767da8d2ffeaf490e05cda274935f7f89 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Mar 2017 12:15:39 +0200 Subject: NFC: nfcmrvl: fix firmware-management initialisation commit 45dd39b974f6632222dd5cdcbea7358a077ab0b0 upstream. The nci-device was never deregistered in the event that fw-initialisation failed. Fix this by moving the firmware initialisation before device registration since the firmware work queue should be available before registering. Note that this depends on a recent fix that moved device-name initialisation back to to nci_allocate_device() as the firmware-workqueue name is now derived from the nfc-device name. Fixes: 3194c6870158 ("NFC: nfcmrvl: add firmware download support") Cc: Vincent Cuissard Signed-off-by: Johan Hovold Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c index 3e3fc95..a446590 100644 --- a/drivers/nfc/nfcmrvl/main.c +++ b/drivers/nfc/nfcmrvl/main.c @@ -158,26 +158,28 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, goto error_free_gpio; } + rc = nfcmrvl_fw_dnld_init(priv); + if (rc) { + nfc_err(dev, "failed to initialize FW download %d\n", rc); + goto error_free_dev; + } + nci_set_drvdata(priv->ndev, priv); rc = nci_register_device(priv->ndev); if (rc) { nfc_err(dev, "nci_register_device failed %d\n", rc); - goto error_free_dev; + goto error_fw_dnld_deinit; } /* Ensure that controller is powered off */ nfcmrvl_chip_halt(priv); - rc = nfcmrvl_fw_dnld_init(priv); - if (rc) { - nfc_err(dev, "failed to initialize FW download %d\n", rc); - goto error_free_dev; - } - nfc_info(dev, "registered with nci successfully\n"); return priv; +error_fw_dnld_deinit: + nfcmrvl_fw_dnld_deinit(priv); error_free_dev: nci_free_device(priv->ndev); error_free_gpio: -- cgit v0.10.2 From d1ac8a98f312da20784723b53c62ad67766d5cb7 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 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 diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ea023b3..102c681 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -910,7 +910,9 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info) u32 device_idx, target_idx, protocol; int rc; - 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; device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); -- cgit v0.10.2 From 4a142251a315e4df6f12a7c99a2a6dfe4ac273ec 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 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 diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index b9edf5f..19c2ca1 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -661,8 +661,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, 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) -- cgit v0.10.2 From 244a7db0e9d584af63e1cfe4911d3200d1b180ee 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 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 diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 19c2ca1..e31dea1 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -76,7 +76,8 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) 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 socket *sock, struct sockaddr *addr, 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); -- cgit v0.10.2 From d3503ef1a6147be68f6208af01a9f81b11cc4877 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:02 +0300 Subject: perf intel-pt: Move decoder error setting into one condition commit 22c06892332d8916115525145b78e606e9cc6492 upstream. Move decoder error setting into one condition. Cc'ed to stable because later fixes depend on it. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 04387ab..9612870 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2128,15 +2128,18 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) } } while (err == -ENOLINK); - decoder->state.err = err ? intel_pt_ext_err(err) : 0; + if (err) { + decoder->state.err = intel_pt_ext_err(err); + decoder->state.from_ip = decoder->ip; + } else { + decoder->state.err = 0; + } + decoder->state.timestamp = decoder->timestamp; decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); decoder->state.cr3 = decoder->cr3; decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; - if (err) - decoder->state.from_ip = decoder->ip; - return &decoder->state; } -- cgit v0.10.2 From 3e6837f1f414ea98f574abc31f04a1a5acb68203 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:03 +0300 Subject: perf intel-pt: Improve sample timestamp commit 3f04d98e972b59706bd43d6cc75efac91f8fba50 upstream. The decoder uses its current timestamp in samples. Usually that is a timestamp that has already passed, but in some cases it is a timestamp for a branch that the decoder is walking towards, and consequently hasn't reached. Improve that situation by using the pkt_state to determine when to use the current or previous timestamp. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 9612870..5539b06 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -64,6 +64,25 @@ enum intel_pt_pkt_state { INTEL_PT_STATE_FUP_NO_TIP, }; +static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state) +{ + switch (pkt_state) { + case INTEL_PT_STATE_NO_PSB: + case INTEL_PT_STATE_NO_IP: + case INTEL_PT_STATE_ERR_RESYNC: + case INTEL_PT_STATE_IN_SYNC: + case INTEL_PT_STATE_TNT: + return true; + case INTEL_PT_STATE_TIP: + case INTEL_PT_STATE_TIP_PGD: + case INTEL_PT_STATE_FUP: + case INTEL_PT_STATE_FUP_NO_TIP: + return false; + default: + return true; + }; +} + #ifdef INTEL_PT_STRICT #define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB #define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB @@ -99,6 +118,7 @@ struct intel_pt_decoder { uint64_t timestamp; uint64_t tsc_timestamp; uint64_t ref_timestamp; + uint64_t sample_timestamp; uint64_t ret_addr; uint64_t ctc_timestamp; uint64_t ctc_delta; @@ -139,6 +159,7 @@ struct intel_pt_decoder { unsigned int fup_tx_flags; unsigned int tx_flags; uint64_t timestamp_insn_cnt; + uint64_t sample_insn_cnt; uint64_t stuck_ip; int no_progress; int stuck_ip_prd; @@ -898,6 +919,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, decoder->tot_insn_cnt += insn_cnt; decoder->timestamp_insn_cnt += insn_cnt; + decoder->sample_insn_cnt += insn_cnt; decoder->period_insn_cnt += insn_cnt; if (err) { @@ -2067,7 +2089,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder) { - uint64_t est = decoder->timestamp_insn_cnt << 1; + uint64_t est = decoder->sample_insn_cnt << 1; if (!decoder->cbr || !decoder->max_non_turbo_ratio) goto out; @@ -2075,7 +2097,7 @@ static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder) est *= decoder->max_non_turbo_ratio; est /= decoder->cbr; out: - return decoder->timestamp + est; + return decoder->sample_timestamp + est; } const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) @@ -2131,11 +2153,17 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) if (err) { decoder->state.err = intel_pt_ext_err(err); decoder->state.from_ip = decoder->ip; + decoder->sample_timestamp = decoder->timestamp; + decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; } else { decoder->state.err = 0; + if (intel_pt_sample_time(decoder->pkt_state)) { + decoder->sample_timestamp = decoder->timestamp; + decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; + } } - decoder->state.timestamp = decoder->timestamp; + decoder->state.timestamp = decoder->sample_timestamp; decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); decoder->state.cr3 = decoder->cr3; decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; -- cgit v0.10.2 From b338b87f2277e9c1a71749ec6985afe64be9efe8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:04 +0300 Subject: perf intel-pt: Fix missing stack clear commit 12b7080609097753fd8198cc1daf589be3ec1cca upstream. The return compression stack must be cleared whenever there is a PSB. Fix one case where that was not happening. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 5539b06..378347b 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1930,6 +1930,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) break; case INTEL_PT_PSB: + intel_pt_clear_stack(&decoder->stack); err = intel_pt_walk_psb(decoder); if (err) return err; -- cgit v0.10.2 From dc0401375f7a7a27ad56e1b0fc19dc470cf0f8d9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:05 +0300 Subject: perf intel-pt: Ensure IP is zero when state is INTEL_PT_STATE_NO_IP commit ad7167a8cd174ba7d8c0d0ed8d8410521206d104 upstream. A value of zero is used to indicate that there is no IP. Ensure the value is zero when the state is INTEL_PT_STATE_NO_IP. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-5-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 378347b..f080ed8 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2115,6 +2115,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) break; case INTEL_PT_STATE_NO_IP: decoder->last_ip = 0; + decoder->ip = 0; /* Fall through */ case INTEL_PT_STATE_ERR_RESYNC: err = intel_pt_sync_ip(decoder); -- cgit v0.10.2 From daa637832dd2c64751369a39d8ad69e993a42a42 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:06 +0300 Subject: perf intel-pt: Fix last_ip usage commit ee14ac0ef6827cd6f9a572cc83dd0191ea17812c upstream. Intel PT uses IP compression based on the last IP. For decoding purposes, 'last IP' is considered to be reset to zero whenever there is a synchronization packet (PSB). The decoder wasn't doing that, and was treating the zero value to mean that there was no last IP, whereas compression can be done against the zero value. Fix by setting last_ip to zero when a PSB is received and keep track of have_last_ip. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-6-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index f080ed8..958db8d 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -111,6 +111,7 @@ struct intel_pt_decoder { bool have_tma; bool have_cyc; bool fixup_last_mtc; + bool have_last_ip; uint64_t pos; uint64_t last_ip; uint64_t ip; @@ -419,6 +420,7 @@ static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet, static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) { decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip); + decoder->have_last_ip = true; } static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) @@ -1670,6 +1672,8 @@ next: break; case INTEL_PT_PSB: + decoder->last_ip = 0; + decoder->have_last_ip = true; intel_pt_clear_stack(&decoder->stack); err = intel_pt_walk_psbend(decoder); if (err == -EAGAIN) @@ -1750,7 +1754,7 @@ next: static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder) { - return decoder->last_ip || decoder->packet.count == 0 || + return decoder->have_last_ip || decoder->packet.count == 0 || decoder->packet.count == 3 || decoder->packet.count == 6; } @@ -1880,7 +1884,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) if (decoder->ip) return 0; } - if (decoder->packet.count) + if (decoder->packet.count && decoder->have_last_ip) intel_pt_set_last_ip(decoder); break; @@ -1930,6 +1934,8 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) break; case INTEL_PT_PSB: + decoder->last_ip = 0; + decoder->have_last_ip = true; intel_pt_clear_stack(&decoder->stack); err = intel_pt_walk_psb(decoder); if (err) @@ -2064,6 +2070,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) decoder->pge = false; decoder->continuous_period = false; + decoder->have_last_ip = false; decoder->last_ip = 0; decoder->ip = 0; intel_pt_clear_stack(&decoder->stack); @@ -2072,6 +2079,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) if (err) return err; + decoder->have_last_ip = true; decoder->pkt_state = INTEL_PT_STATE_NO_IP; err = intel_pt_walk_psb(decoder); @@ -2114,6 +2122,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) err = intel_pt_sync(decoder); break; case INTEL_PT_STATE_NO_IP: + decoder->have_last_ip = false; decoder->last_ip = 0; decoder->ip = 0; /* Fall through */ -- cgit v0.10.2 From 5a16bd39c5012940955afa708e98ffbb32be31ce Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:07 +0300 Subject: perf intel-pt: Ensure never to set 'last_ip' when packet 'count' is zero commit f952eaceb089b691eba7c4e13686e742a8f26bf5 upstream. Intel PT uses IP compression based on the last IP. For decoding purposes, 'last IP' is not updated when a branch target has been suppressed, which is indicated by IPBytes == 0. IPBytes is stored in the packet 'count', so ensure never to set 'last_ip' when packet 'count' is zero. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 958db8d..81c03c5 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1468,7 +1468,8 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) case INTEL_PT_FUP: decoder->pge = true; - intel_pt_set_last_ip(decoder); + if (decoder->packet.count) + intel_pt_set_last_ip(decoder); break; case INTEL_PT_MODE_TSX: @@ -1754,8 +1755,9 @@ next: static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder) { - return decoder->have_last_ip || decoder->packet.count == 0 || - decoder->packet.count == 3 || decoder->packet.count == 6; + return decoder->packet.count && + (decoder->have_last_ip || decoder->packet.count == 3 || + decoder->packet.count == 6); } /* Walk PSB+ packets to get in sync. */ -- cgit v0.10.2 From 94c38cd0aff23b38a7e78f82141081e986f560b5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:08 +0300 Subject: perf intel-pt: Use FUP always when scanning for an IP commit 622b7a47b843c78626f40c1d1aeef8483383fba2 upstream. The decoder will try to use branch packets to find an IP to start decoding or to recover from errors. Currently the FUP packet is used only in the case of an overflow, however there is no reason for that to be a special case. So just use FUP always when scanning for an IP. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 81c03c5..499e5af8 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1880,14 +1880,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) break; case INTEL_PT_FUP: - if (decoder->overflow) { - if (intel_pt_have_ip(decoder)) - intel_pt_set_ip(decoder); - if (decoder->ip) - return 0; - } - if (decoder->packet.count && decoder->have_last_ip) - intel_pt_set_last_ip(decoder); + if (intel_pt_have_ip(decoder)) + intel_pt_set_ip(decoder); + if (decoder->ip) + return 0; break; case INTEL_PT_MTC: -- cgit v0.10.2 From fe5cdbcdafaae75418307485b5d0ff5c66e250c4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 May 2017 11:17:09 +0300 Subject: perf intel-pt: Clear FUP flag on error commit 6a558f12dbe85437acbdec5e149ea07b5554eced upstream. Sometimes a FUP packet is associated with a TSX transaction and a flag is set to indicate that. Ensure that flag is cleared on any error condition because at that point the decoder can no longer assume it is correct. Signed-off-by: Adrian Hunter Cc: Andi Kleen Link: http://lkml.kernel.org/r/1495786658-18063-9-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 499e5af8..7e27207 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1960,6 +1960,8 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) { int err; + decoder->set_fup_tx_flags = false; + intel_pt_log("Scanning for full IP\n"); err = intel_pt_walk_to_ip(decoder); if (err) -- cgit v0.10.2 From 3da27a9d982798ece7f09dd3b259be8fe0bc3a11 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 10 Jun 2017 04:59:11 +0200 Subject: Bluetooth: use constant time memory comparison for secret values commit 329d82309824ff1082dc4a91a5bbed8c3bec1580 upstream. This file is filled with complex cryptography. Thus, the comparisons of MACs and secret keys and curve points and so forth should not add timing attacks, which could either result in a direct forgery, or, given the complexity, some other type of attack. Signed-off-by: Jason A. Donenfeld Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 43faf2a..658c900 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -506,7 +507,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], if (err) return false; - return !memcmp(bdaddr->b, hash, 3); + return !crypto_memneq(bdaddr->b, hash, 3); } int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) @@ -559,7 +560,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } smp->debug_key = false; @@ -973,7 +974,7 @@ static u8 smp_random(struct smp_chan *smp) if (ret) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { + if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { BT_ERR("Pairing failed (confirmation values mismatch)"); return SMP_CONFIRM_FAILED; } @@ -1473,7 +1474,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) smp->rrnd, r, cfm)) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; smp->passkey_round++; @@ -1857,7 +1858,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } } @@ -2122,7 +2123,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; } else { smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), @@ -2603,7 +2604,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(cfm.confirm_val, smp->pcnf, 16)) + if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) return SMP_CONFIRM_FAILED; } @@ -2636,7 +2637,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) else hcon->pending_sec_level = BT_SECURITY_FIPS; - if (!memcmp(debug_pk, smp->remote_pk, 64)) + if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); if (smp->method == DSP_PASSKEY) { @@ -2735,7 +2736,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(check->e, e, 16)) + if (crypto_memneq(check->e, e, 16)) return SMP_DHKEY_CHECK_FAILED; if (!hcon->out) { @@ -3446,7 +3447,7 @@ static int __init test_ah(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 3)) + if (crypto_memneq(res, exp, 3)) return -EINVAL; return 0; @@ -3476,7 +3477,7 @@ static int __init test_c1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3501,7 +3502,7 @@ static int __init test_s1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3533,7 +3534,7 @@ static int __init test_f4(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3567,10 +3568,10 @@ static int __init test_f5(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(mackey, exp_mackey, 16)) + if (crypto_memneq(mackey, exp_mackey, 16)) return -EINVAL; - if (memcmp(ltk, exp_ltk, 16)) + if (crypto_memneq(ltk, exp_ltk, 16)) return -EINVAL; return 0; @@ -3603,7 +3604,7 @@ static int __init test_f6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3657,7 +3658,7 @@ static int __init test_h6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; -- cgit v0.10.2 From 754f4e05e9994e734bf620bfd77a9d04ac55e7b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 May 2017 13:52:09 +0200 Subject: wlcore: fix 64K page support commit 4a4274bf2dbbd1c7a45be0c89a1687c9d2eef4a0 upstream. In the stable linux-3.16 branch, I ran into a warning in the wlcore driver: drivers/net/wireless/ti/wlcore/spi.c: In function 'wl12xx_spi_raw_write': drivers/net/wireless/ti/wlcore/spi.c:315:1: error: the frame size of 12848 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] Newer kernels no longer show the warning, but the bug is still there, as the allocation is based on the CPU page size rather than the actual capabilities of the hardware. This replaces the PAGE_SIZE macro with the SZ_4K macro, i.e. 4096 bytes per buffer. Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index f949ad2b..fa3547e 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -70,10 +70,10 @@ #define WSPI_MAX_CHUNK_SIZE 4092 /* - * wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to - * (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx + * wl18xx driver aggregation buffer size is (13 * 4K) compared to + * (4 * 4K) for wl12xx, so use the larger buffer needed for wl18xx */ -#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE) +#define SPI_AGGR_BUFFER_SIZE (13 * SZ_4K) /* Maximum number of SPI write chunks */ #define WSPI_MAX_NUM_OF_CHUNKS \ -- cgit v0.10.2 From 157302f97aaa6f79854622a9aab7749fe8661d20 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 22 Jun 2017 15:31:07 +0200 Subject: btrfs: Don't clear SGID when inheriting ACLs commit b7f8a09f8097db776b8d160862540e4fc1f51296 upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by moving posix_acl_update_mode() out of __btrfs_set_acl() into btrfs_set_acl(). That way the function will not be called when inheriting ACLs which is what we want as it prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: linux-btrfs@vger.kernel.org CC: David Sterba Signed-off-by: Jan Kara Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 247b8df..8d8370d 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -78,12 +78,6 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; - if (acl) { - ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (ret) - return ret; - } - ret = 0; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) @@ -119,6 +113,13 @@ out: int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { + int ret; + + if (type == ACL_TYPE_ACCESS && acl) { + ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (ret) + return ret; + } return __btrfs_set_acl(NULL, inode, acl, type); } -- cgit v0.10.2 From 9a81c136f486803b211c0e8d68a1fa9b0d8e8444 Mon Sep 17 00:00:00 2001 From: Matwey V Kornilov Date: Thu, 24 Nov 2016 13:32:48 +0300 Subject: igb: Explicitly select page 0 at initialization commit 440aeca4b9858248d8f16d724d9fa87a4f65fa33 upstream. The functions igb_read_phy_reg_gs40g/igb_write_phy_reg_gs40g (which were removed in 2a3cdea) explicitly selected the required page at every phy_reg access. Currently, igb_get_phy_id_82575 relays on the fact that page 0 is already selected. The assumption is not fulfilled for my Lex 3I380CW motherboard with integrated dual i211 based gigabit ethernet. This leads to igb initialization failure and network interfaces are not working: igb: Intel(R) Gigabit Ethernet Network Driver - version 5.4.0-k igb: Copyright (c) 2007-2014 Intel Corporation. igb: probe of 0000:01:00.0 failed with error -2 igb: probe of 0000:02:00.0 failed with error -2 In order to fix it, we explicitly select page 0 before first access to phy registers. See also: https://bugzilla.suse.com/show_bug.cgi?id=1009911 See also: http://www.lex.com.tw/products/pdf/3I380A&3I380CW.pdf Fixes: 2a3cdea ("igb: Remove GS40G specific defines/functions") Signed-off-by: Matwey V Kornilov Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index a61447f..1264a36 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -246,6 +246,7 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) E1000_STATUS_FUNC_SHIFT; /* Set phy->phy_addr and phy->id. */ + igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, 0); ret_val = igb_get_phy_id_82575(hw); if (ret_val) return ret_val; -- cgit v0.10.2 From 4d94276155f8bbd63b4ff1b3dc3ae9e14c9964e1 Mon Sep 17 00:00:00 2001 From: Satish Babu Patakokila Date: Fri, 16 Jun 2017 17:33:40 -0700 Subject: ASoC: compress: Derive substream from stream based on direction commit 01b8cedfd0422326caae308641dcadaa85e0ca72 upstream. Currently compress driver hardcodes direction as playback to get substream from the stream. This results in getting the incorrect substream for compressed capture usecase. To fix this, remove the hardcoding and derive substream based on the stream direction. Signed-off-by: Satish Babu Patakokila Signed-off-by: Banajit Goswami Acked-By: Vinod Koul Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index bf7b52f..ff093ed 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -68,7 +68,8 @@ out: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; @@ -414,7 +415,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; int ret = 0, stream; -- cgit v0.10.2 From b87a32175a22fae2b15750477c1397970deafd68 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 28 Jun 2017 16:56:18 +0200 Subject: PM / Domains: Fix unsafe iteration over modified list of device links commit c6e83cac3eda5f7dd32ee1453df2f7abb5c6cd46 upstream. pm_genpd_remove_subdomain() iterates over domain's master_links list and removes matching element thus it has to use safe version of list iteration. Fixes: f721889ff65a ("PM / Domains: Support for generic I/O PM domains (v8)") Signed-off-by: Krzysztof Kozlowski Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e023066..7704ae7 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1244,7 +1244,7 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain); int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *subdomain) { - struct gpd_link *link; + struct gpd_link *l, *link; int ret = -EINVAL; if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) @@ -1260,7 +1260,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, goto out; } - list_for_each_entry(link, &genpd->master_links, master_node) { + list_for_each_entry_safe(link, l, &genpd->master_links, master_node) { if (link->slave != subdomain) continue; -- cgit v0.10.2 From 178aa241fc070e5b34c5bbe3f9ae0a6b0b335840 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 28 Jun 2017 16:56:19 +0200 Subject: PM / Domains: Fix unsafe iteration over modified list of domain providers commit b556b15dc04e9b9b98790f04c21acf5e24f994b2 upstream. of_genpd_del_provider() iterates over list of domain provides and removes matching element thus it has to use safe version of list iteration. Fixes: aa42240ab254 (PM / Domains: Add generic OF-based PM domain look-up) Signed-off-by: Krzysztof Kozlowski Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7704ae7..4554654 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1607,12 +1607,12 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell); */ void of_genpd_del_provider(struct device_node *np) { - struct of_genpd_provider *cp; + struct of_genpd_provider *cp, *tmp; struct generic_pm_domain *gpd; mutex_lock(&gpd_list_lock); mutex_lock(&of_genpd_mutex); - list_for_each_entry(cp, &of_genpd_providers, link) { + list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) { if (cp->node == np) { /* * For each PM domain associated with the -- cgit v0.10.2 From d2bb0af4463d0fd094385d8e15f8f18c9adaafa4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 28 Jun 2017 16:56:20 +0200 Subject: PM / Domains: Fix unsafe iteration over modified list of domains commit a7e2d1bce4c1db471f1cbc0c4666a3112bbf0994 upstream. of_genpd_remove_last() iterates over list of domains and removes matching element thus it has to use safe version of list iteration. Fixes: 17926551c98a (PM / Domains: Add support for removing nested PM domains by provider) Signed-off-by: Krzysztof Kozlowski Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4554654..951c214 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1752,14 +1752,14 @@ EXPORT_SYMBOL_GPL(of_genpd_add_subdomain); */ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np) { - struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT); + struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT); int ret; if (IS_ERR_OR_NULL(np)) return ERR_PTR(-EINVAL); mutex_lock(&gpd_list_lock); - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { + list_for_each_entry_safe(gpd, tmp, &gpd_list, gpd_list_node) { if (gpd->provider == &np->fwnode) { ret = genpd_remove(gpd); genpd = ret ? ERR_PTR(ret) : gpd; -- cgit v0.10.2 From 542c097f1cb61f57ad42ffd8431371d69e76aa03 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Tue, 27 Jun 2017 11:53:27 +0200 Subject: scsi: ses: do not add a device to an enclosure if enclosure_add_links() fails. commit 62e62ffd95539b9220894a7900a619e0f3ef4756 upstream. The enclosure_add_device() function should fail if it can't create the relevant sysfs links. Signed-off-by: Maurizio Lombardi Tested-by: Douglas Miller Acked-by: James Bottomley Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 65fed71..cc91f7b 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -375,6 +375,7 @@ int enclosure_add_device(struct enclosure_device *edev, int component, struct device *dev) { struct enclosure_component *cdev; + int err; if (!edev || component >= edev->components) return -EINVAL; @@ -384,12 +385,17 @@ int enclosure_add_device(struct enclosure_device *edev, int component, if (cdev->dev == dev) return -EEXIST; - if (cdev->dev) + if (cdev->dev) { enclosure_remove_links(cdev); - - put_device(cdev->dev); + put_device(cdev->dev); + } cdev->dev = get_device(dev); - return enclosure_add_links(cdev); + err = enclosure_add_links(cdev); + if (err) { + put_device(cdev->dev); + cdev->dev = NULL; + } + return err; } EXPORT_SYMBOL_GPL(enclosure_add_device); -- cgit v0.10.2 From fc866b296a463661f90ea734c40b1049c4834eaa Mon Sep 17 00:00:00 2001 From: "Ewan D. Milne" Date: Tue, 27 Jun 2017 14:55:58 -0400 Subject: scsi: Add STARGET_CREATED_REMOVE state to scsi_target_state commit f9279c968c257ee39b0d7bd2571a4d231a67bcc1 upstream. The addition of the STARGET_REMOVE state had the side effect of introducing a race condition that can cause a crash. scsi_target_reap_ref_release() checks the starget->state to see if it still in STARGET_CREATED, and if so, skips calling transport_remove_device() and device_del(), because the starget->state is only set to STARGET_RUNNING after scsi_target_add() has called device_add() and transport_add_device(). However, if an rport loss occurs while a target is being scanned, it can happen that scsi_remove_target() will be called while the starget is still in the STARGET_CREATED state. In this case, the starget->state will be set to STARGET_REMOVE, and as a result, scsi_target_reap_ref_release() will take the wrong path. The end result is a panic: [ 1255.356653] Oops: 0000 [#1] SMP [ 1255.360154] Modules linked in: x86_pkg_temp_thermal kvm_intel kvm irqbypass crc32c_intel ghash_clmulni_i [ 1255.393234] CPU: 5 PID: 149 Comm: kworker/u96:4 Tainted: G W 4.11.0+ #8 [ 1255.401879] Hardware name: Dell Inc. PowerEdge R320/08VT7V, BIOS 2.0.22 11/19/2013 [ 1255.410327] Workqueue: scsi_wq_6 fc_scsi_scan_rport [scsi_transport_fc] [ 1255.417720] task: ffff88060ca8c8c0 task.stack: ffffc900048a8000 [ 1255.424331] RIP: 0010:kernfs_find_ns+0x13/0xc0 [ 1255.429287] RSP: 0018:ffffc900048abbf0 EFLAGS: 00010246 [ 1255.435123] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 1255.443083] RDX: 0000000000000000 RSI: ffffffff8188d659 RDI: 0000000000000000 [ 1255.451043] RBP: ffffc900048abc10 R08: 0000000000000000 R09: 0000012433fe0025 [ 1255.459005] R10: 0000000025e5a4b5 R11: 0000000025e5a4b5 R12: ffffffff8188d659 [ 1255.466972] R13: 0000000000000000 R14: ffff8805f55e5088 R15: 0000000000000000 [ 1255.474931] FS: 0000000000000000(0000) GS:ffff880616b40000(0000) knlGS:0000000000000000 [ 1255.483959] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1255.490370] CR2: 0000000000000068 CR3: 0000000001c09000 CR4: 00000000000406e0 [ 1255.498332] Call Trace: [ 1255.501058] kernfs_find_and_get_ns+0x31/0x60 [ 1255.505916] sysfs_unmerge_group+0x1d/0x60 [ 1255.510498] dpm_sysfs_remove+0x22/0x60 [ 1255.514783] device_del+0xf4/0x2e0 [ 1255.518577] ? device_remove_file+0x19/0x20 [ 1255.523241] attribute_container_class_device_del+0x1a/0x20 [ 1255.529457] transport_remove_classdev+0x4e/0x60 [ 1255.534607] ? transport_add_class_device+0x40/0x40 [ 1255.540046] attribute_container_device_trigger+0xb0/0xc0 [ 1255.546069] transport_remove_device+0x15/0x20 [ 1255.551025] scsi_target_reap_ref_release+0x25/0x40 [ 1255.556467] scsi_target_reap+0x2e/0x40 [ 1255.560744] __scsi_scan_target+0xaa/0x5b0 [ 1255.565312] scsi_scan_target+0xec/0x100 [ 1255.569689] fc_scsi_scan_rport+0xb1/0xc0 [scsi_transport_fc] [ 1255.576099] process_one_work+0x14b/0x390 [ 1255.580569] worker_thread+0x4b/0x390 [ 1255.584651] kthread+0x109/0x140 [ 1255.588251] ? rescuer_thread+0x330/0x330 [ 1255.592730] ? kthread_park+0x60/0x60 [ 1255.596815] ret_from_fork+0x29/0x40 [ 1255.600801] Code: 24 08 48 83 42 40 01 5b 41 5c 5d c3 66 66 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 [ 1255.621876] RIP: kernfs_find_ns+0x13/0xc0 RSP: ffffc900048abbf0 [ 1255.628479] CR2: 0000000000000068 [ 1255.632756] ---[ end trace 34a69ba0477d036f ]--- Fix this by adding another scsi_target state STARGET_CREATED_REMOVE to distinguish this case. Fixes: f05795d3d771 ("scsi: Add intermediate STARGET_REMOVE state to scsi_target_state") Reported-by: David Jeffery Signed-off-by: Ewan D. Milne Reviewed-by: Laurence Oberman Tested-by: Laurence Oberman Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 6f7128f..27a6d3c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -384,11 +384,12 @@ static void scsi_target_reap_ref_release(struct kref *kref) = container_of(kref, struct scsi_target, reap_ref); /* - * if we get here and the target is still in the CREATED state that + * if we get here and the target is still in a CREATED state that * means it was allocated but never made visible (because a scan * turned up no LUNs), so don't call device_del() on it. */ - if (starget->state != STARGET_CREATED) { + if ((starget->state != STARGET_CREATED) && + (starget->state != STARGET_CREATED_REMOVE)) { transport_remove_device(&starget->dev); device_del(&starget->dev); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 82dfe07..3a6f557 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1370,11 +1370,15 @@ restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || - starget->state == STARGET_REMOVE) + starget->state == STARGET_REMOVE || + starget->state == STARGET_CREATED_REMOVE) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); - starget->state = STARGET_REMOVE; + if (starget->state == STARGET_CREATED) + starget->state = STARGET_CREATED_REMOVE; + else + starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index b9ec493..f2b9a2f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -248,6 +248,7 @@ enum scsi_target_state { STARGET_CREATED = 1, STARGET_RUNNING, STARGET_REMOVE, + STARGET_CREATED_REMOVE, STARGET_DEL, }; -- cgit v0.10.2 From 732e3c76cf97451e8b58f666c1f54cd8b3f9d26f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 7 Jul 2017 14:45:49 -0700 Subject: iscsi-target: Add login_keys_workaround attribute for non RFC initiators commit 138d351eefb727ab9e41a3dc5f112ceb4f6e59f2 upstream. This patch re-introduces part of a long standing login workaround that was recently dropped by: commit 1c99de981f30b3e7868b8d20ce5479fa1c0fea46 Author: Nicholas Bellinger Date: Sun Apr 2 13:36:44 2017 -0700 iscsi-target: Drop work-around for legacy GlobalSAN initiator Namely, the workaround for FirstBurstLength ended up being required by Mellanox Flexboot PXE boot ROMs as reported by Robert. So this patch re-adds the work-around for FirstBurstLength within iscsi_check_proposer_for_optional_reply(), and makes the key optional to respond when the initiator does not propose, nor respond to it. Also as requested by Arun, this patch introduces a new TPG attribute named 'login_keys_workaround' that controls the use of both the FirstBurstLength workaround, as well as the two other existing workarounds for gPXE iSCSI boot client. By default, the workaround is enabled with login_keys_workaround=1, since Mellanox FlexBoot requires it, and Arun has verified the Qlogic MSFT initiator already proposes FirstBurstLength, so it's uneffected by this re-adding this part of the original work-around. Reported-by: Robert LeBlanc Cc: Robert LeBlanc Reviewed-by: Arun Easi Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 7e70fe8..9cbbc9c 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -802,6 +802,7 @@ DEF_TPG_ATTRIB(default_erl); DEF_TPG_ATTRIB(t10_pi); DEF_TPG_ATTRIB(fabric_prot_type); DEF_TPG_ATTRIB(tpg_enabled_sendtargets); +DEF_TPG_ATTRIB(login_keys_workaround); static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_attr_authentication, @@ -817,6 +818,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_attr_t10_pi, &iscsi_tpg_attrib_attr_fabric_prot_type, &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets, + &iscsi_tpg_attrib_attr_login_keys_workaround, NULL, }; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 89d34bd..6693d7c 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -819,7 +819,8 @@ static int iscsi_target_handle_csg_zero( SENDER_TARGET, login->rsp_buf, &login->rsp_length, - conn->param_list); + conn->param_list, + conn->tpg->tpg_attrib.login_keys_workaround); if (ret < 0) return -1; @@ -889,7 +890,8 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log SENDER_TARGET, login->rsp_buf, &login->rsp_length, - conn->param_list); + conn->param_list, + conn->tpg->tpg_attrib.login_keys_workaround); if (ret < 0) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ISCSI_LOGIN_STATUS_INIT_ERR); diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 4a073339a..0151776 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -765,7 +765,8 @@ static int iscsi_check_for_auth_key(char *key) return 0; } -static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) +static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param, + bool keys_workaround) { if (IS_TYPE_BOOL_AND(param)) { if (!strcmp(param->value, NO)) @@ -773,19 +774,31 @@ static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) } else if (IS_TYPE_BOOL_OR(param)) { if (!strcmp(param->value, YES)) SET_PSTATE_REPLY_OPTIONAL(param); - /* - * Required for gPXE iSCSI boot client - */ - if (!strcmp(param->name, IMMEDIATEDATA)) - SET_PSTATE_REPLY_OPTIONAL(param); + + if (keys_workaround) { + /* + * Required for gPXE iSCSI boot client + */ + if (!strcmp(param->name, IMMEDIATEDATA)) + SET_PSTATE_REPLY_OPTIONAL(param); + } } else if (IS_TYPE_NUMBER(param)) { if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) SET_PSTATE_REPLY_OPTIONAL(param); - /* - * Required for gPXE iSCSI boot client - */ - if (!strcmp(param->name, MAXCONNECTIONS)) - SET_PSTATE_REPLY_OPTIONAL(param); + + if (keys_workaround) { + /* + * Required for Mellanox Flexboot PXE boot ROM + */ + if (!strcmp(param->name, FIRSTBURSTLENGTH)) + SET_PSTATE_REPLY_OPTIONAL(param); + + /* + * Required for gPXE iSCSI boot client + */ + if (!strcmp(param->name, MAXCONNECTIONS)) + SET_PSTATE_REPLY_OPTIONAL(param); + } } else if (IS_PHASE_DECLARATIVE(param)) SET_PSTATE_REPLY_OPTIONAL(param); } @@ -1422,7 +1435,8 @@ int iscsi_encode_text_output( u8 sender, char *textbuf, u32 *length, - struct iscsi_param_list *param_list) + struct iscsi_param_list *param_list, + bool keys_workaround) { char *output_buf = NULL; struct iscsi_extra_response *er; @@ -1458,7 +1472,8 @@ int iscsi_encode_text_output( *length += 1; output_buf = textbuf + *length; SET_PSTATE_PROPOSER(param); - iscsi_check_proposer_for_optional_reply(param); + iscsi_check_proposer_for_optional_reply(param, + keys_workaround); pr_debug("Sending key: %s=%s\n", param->name, param->value); } diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h index a0751e3..17a58c2 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.h +++ b/drivers/target/iscsi/iscsi_target_parameters.h @@ -40,7 +40,7 @@ extern int iscsi_extract_key_value(char *, char **, char **); extern int iscsi_update_param_value(struct iscsi_param *, char *); extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *); extern int iscsi_encode_text_output(u8, u8, char *, u32 *, - struct iscsi_param_list *); + struct iscsi_param_list *, bool); extern int iscsi_check_negotiated_keys(struct iscsi_param_list *); extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *, struct iscsi_param_list *); diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 205a509..63e1dcc 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -227,6 +227,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg) a->t10_pi = TA_DEFAULT_T10_PI; a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE; a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS; + a->login_keys_workaround = TA_DEFAULT_LOGIN_KEYS_WORKAROUND; } int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg) @@ -899,3 +900,21 @@ int iscsit_ta_tpg_enabled_sendtargets( return 0; } + +int iscsit_ta_login_keys_workaround( + struct iscsi_portal_group *tpg, + u32 flag) +{ + struct iscsi_tpg_attrib *a = &tpg->tpg_attrib; + + if ((flag != 0) && (flag != 1)) { + pr_err("Illegal value %d\n", flag); + return -EINVAL; + } + + a->login_keys_workaround = flag; + pr_debug("iSCSI_TPG[%hu] - TPG enabled bit for login keys workaround: %s ", + tpg->tpgt, (a->login_keys_workaround) ? "ON" : "OFF"); + + return 0; +} diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h index 2da2119..901a712 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.h +++ b/drivers/target/iscsi/iscsi_target_tpg.h @@ -39,5 +39,6 @@ extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32); extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32); extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32); extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32); +extern int iscsit_ta_login_keys_workaround(struct iscsi_portal_group *, u32); #endif /* ISCSI_TARGET_TPG_H */ diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 4ac24f5..33b2e75 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -64,6 +64,14 @@ #define TA_DEFAULT_FABRIC_PROT_TYPE 0 /* TPG status needs to be enabled to return sendtargets discovery endpoint info */ #define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1 +/* + * Used to control the sending of keys with optional to respond state bit, + * as a workaround for non RFC compliant initiators,that do not propose, + * nor respond to specific keys required for login to complete. + * + * See iscsi_check_proposer_for_optional_reply() for more details. + */ +#define TA_DEFAULT_LOGIN_KEYS_WORKAROUND 1 #define ISCSI_IOV_DATA_BUFFER 5 @@ -766,6 +774,7 @@ struct iscsi_tpg_attrib { u8 t10_pi; u32 fabric_prot_type; u32 tpg_enabled_sendtargets; + u32 login_keys_workaround; struct iscsi_portal_group *tpg; }; -- cgit v0.10.2 From 71b1caea95a8ab5b2e5f868a68a454283ed51109 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 May 2017 16:48:36 -0700 Subject: xen/scsiback: Fix a TMR related use-after-free commit 9f4ab18ac51dc87345a9cbd2527e6acf7a0a9335 upstream. scsiback_release_cmd() must not dereference se_cmd->se_tmr_req because that memory is freed by target_free_cmd_mem() before scsiback_release_cmd() is called. Fix this use-after-free by inlining struct scsiback_tmr into struct vscsibk_pend. Signed-off-by: Bart Van Assche Reviewed-by: Juergen Gross Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: David Disseldorp Cc: xen-devel@lists.xenproject.org Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index d6950e0..980f328 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -134,9 +134,7 @@ struct vscsibk_pend { struct page *pages[VSCSI_MAX_GRANTS]; struct se_cmd se_cmd; -}; -struct scsiback_tmr { atomic_t tmr_complete; wait_queue_head_t tmr_wait; }; @@ -599,26 +597,20 @@ static void scsiback_device_action(struct vscsibk_pend *pending_req, struct scsiback_tpg *tpg = pending_req->v2p->tpg; struct scsiback_nexus *nexus = tpg->tpg_nexus; struct se_cmd *se_cmd = &pending_req->se_cmd; - struct scsiback_tmr *tmr; u64 unpacked_lun = pending_req->v2p->lun; int rc, err = FAILED; - tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL); - if (!tmr) { - target_put_sess_cmd(se_cmd); - goto err; - } - - init_waitqueue_head(&tmr->tmr_wait); + init_waitqueue_head(&pending_req->tmr_wait); rc = target_submit_tmr(&pending_req->se_cmd, nexus->tvn_se_sess, &pending_req->sense_buffer[0], - unpacked_lun, tmr, act, GFP_KERNEL, + unpacked_lun, NULL, act, GFP_KERNEL, tag, TARGET_SCF_ACK_KREF); if (rc) goto err; - wait_event(tmr->tmr_wait, atomic_read(&tmr->tmr_complete)); + wait_event(pending_req->tmr_wait, + atomic_read(&pending_req->tmr_complete)); err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; @@ -626,9 +618,8 @@ static void scsiback_device_action(struct vscsibk_pend *pending_req, scsiback_do_resp_with_sense(NULL, err, 0, pending_req); transport_generic_free_cmd(&pending_req->se_cmd, 1); return; + err: - if (tmr) - kfree(tmr); scsiback_do_resp_with_sense(NULL, err, 0, pending_req); } @@ -1389,12 +1380,6 @@ static int scsiback_check_stop_free(struct se_cmd *se_cmd) static void scsiback_release_cmd(struct se_cmd *se_cmd) { struct se_session *se_sess = se_cmd->se_sess; - struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; - - if (se_tmr && se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { - struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr; - kfree(tmr); - } percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag); } @@ -1455,11 +1440,11 @@ static int scsiback_queue_status(struct se_cmd *se_cmd) static void scsiback_queue_tm_rsp(struct se_cmd *se_cmd) { - struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; - struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr; + struct vscsibk_pend *pending_req = container_of(se_cmd, + struct vscsibk_pend, se_cmd); - atomic_set(&tmr->tmr_complete, 1); - wake_up(&tmr->tmr_wait); + atomic_set(&pending_req->tmr_complete, 1); + wake_up(&pending_req->tmr_wait); } static void scsiback_aborted_task(struct se_cmd *se_cmd) -- cgit v0.10.2 From d638c8584462609237b4d12563f871f2323ac819 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Thu, 29 Jun 2017 03:04:07 +1000 Subject: powerpc/pseries: Fix passing of pp0 in updatepp() and updateboltedpp() commit e71ff982ae4c17d176e9f0132157d54973788377 upstream. Once upon a time there were only two PP (page protection) bits. In ISA 2.03 an additional PP bit was added, but because of the layout of the HPTE it could not be made contiguous with the existing PP bits. The result is that we now have three PP bits, named pp0, pp1, pp2, where pp0 occupies bit 63 of dword 1 of the HPTE and pp1 and pp2 occupy bits 1 and 0 respectively. Until recently Linux hasn't used pp0, however with the addition of _PAGE_KERNEL_RO we started using it. The problem arises in the LPAR code, where we need to translate the PP bits into the argument for the H_PROTECT hypercall. Currently the code only passes bits 0-2 of newpp, which covers pp1, pp2 and N (no execute), meaning pp0 is not passed to the hypervisor at all. We can't simply pass it through in bit 63, as that would collide with a different field in the flags argument, as defined in PAPR. Instead we have to shift it down to bit 8 (IBM bit 55). Fixes: e58e87adc8bf ("powerpc/mm: Update _PAGE_KERNEL_RO") Signed-off-by: Balbir Singh [mpe: Simplify the test, rework change log] Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index f2c98f6..a7bb872 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -279,7 +279,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, int ssize, unsigned long inv_flags) { unsigned long lpar_rc; - unsigned long flags = (newpp & 7) | H_AVPN; + unsigned long flags; unsigned long want_v; want_v = hpte_encode_avpn(vpn, psize, ssize); @@ -287,6 +287,11 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", want_v, slot, flags, psize); + flags = (newpp & 7) | H_AVPN; + if (mmu_has_feature(MMU_FTR_KERNEL_RO)) + /* Move pp0 into bit 8 (IBM 55) */ + flags |= (newpp & HPTE_R_PP0) >> 55; + lpar_rc = plpar_pte_protect(flags, slot, want_v); if (lpar_rc == H_NOT_FOUND) { @@ -358,6 +363,10 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, BUG_ON(slot == -1); flags = newpp & 7; + if (mmu_has_feature(MMU_FTR_KERNEL_RO)) + /* Move pp0 into bit 8 (IBM 55) */ + flags |= (newpp & HPTE_R_PP0) >> 55; + lpar_rc = plpar_pte_protect(flags, slot, 0); BUG_ON(lpar_rc != H_SUCCESS); -- cgit v0.10.2 From 99fc5a2254ef6409947e21b7b829cd59eb8234c5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 11 Jul 2017 22:10:54 +1000 Subject: powerpc/64: Fix atomic64_inc_not_zero() to return an int commit 01e6a61aceb82e13bec29502a8eb70d9574f97ad upstream. Although it's not documented anywhere, there is an expectation that atomic64_inc_not_zero() returns a result which fits in an int. This is the behaviour implemented on all arches except powerpc. This has caused at least one bug in practice, in the percpu-refcount code, where the long result from our atomic64_inc_not_zero() was truncated to an int leading to lost references and stuck systems. That was worked around in that code in commit 966d2b04e070 ("percpu-refcount: fix reference leak during percpu-atomic transition"). To the best of my grepping abilities there are no other callers in-tree which truncate the value, but we should fix it anyway. Because the breakage is subtle and potentially very harmful I'm also tagging it for stable. Code generation is largely unaffected because in most cases the callers are just using the result for a test anyway. In particular the case of fget() that was mentioned in commit a6cf7ed5119f ("powerpc/atomic: Implement atomic*_inc_not_zero") generates exactly the same code. Fixes: a6cf7ed5119f ("powerpc/atomic: Implement atomic*_inc_not_zero") Noticed-by: Linus Torvalds Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index 2b90335..a2cc801 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -560,7 +560,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) * Atomically increments @v by 1, so long as @v is non-zero. * Returns non-zero if @v was non-zero, and zero otherwise. */ -static __inline__ long atomic64_inc_not_zero(atomic64_t *v) +static __inline__ int atomic64_inc_not_zero(atomic64_t *v) { long t1, t2; @@ -579,7 +579,7 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v) : "r" (&v->counter) : "cc", "xer", "memory"); - return t1; + return t1 != 0; } #endif /* __powerpc64__ */ -- cgit v0.10.2 From 53a28216131762700d10eb4755562b10c8d2685b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 15 Jun 2017 09:46:38 +1000 Subject: powerpc: Fix emulation of mcrf in emulate_step() commit 87c4b83e0fe234a1f0eed131ab6fa232036860d5 upstream. The mcrf emulation code was using the CR field number directly as the shift value, without taking into account that CR fields are numbered from 0-7 starting at the high bits. That meant it was looking at the CR fields in the reverse order. Fixes: cf87c3f6b647 ("powerpc: Emulate icbi, mcrf and conditional-trap instructions") Signed-off-by: Anton Blanchard Acked-by: Naveen N. Rao Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 6ca3b90..b6e4eca 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -687,8 +687,10 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, case 19: switch ((instr >> 1) & 0x3ff) { case 0: /* mcrf */ - rd = (instr >> 21) & 0x1c; - ra = (instr >> 16) & 0x1c; + rd = 7 - ((instr >> 23) & 0x7); + ra = 7 - ((instr >> 18) & 0x7); + rd *= 4; + ra *= 4; val = (regs->ccr >> ra) & 0xf; regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd); goto instr_done; -- cgit v0.10.2 From 5e35ee249e26e36cae641bee8d212fba0e1bb6e6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 15 Jun 2017 09:46:39 +1000 Subject: powerpc: Fix emulation of mfocrf in emulate_step() commit 64e756c55aa46fc18fd53e8f3598b73b528d8637 upstream. From POWER4 onwards, mfocrf() only places the specified CR field into the destination GPR, and the rest of it is set to 0. The PowerPC AS from version 3.0 now requires this behaviour. The emulation code currently puts the entire CR into the destination GPR. Fix it. Fixes: 6888199f7fe5 ("[POWERPC] Emulate more instructions in software") Signed-off-by: Anton Blanchard Acked-by: Naveen N. Rao Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index b6e4eca..776c1a1 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -970,6 +970,19 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, #endif case 19: /* mfcr */ + if ((instr >> 20) & 1) { + imm = 0xf0000000UL; + for (sh = 0; sh < 8; ++sh) { + if (instr & (0x80000 >> sh)) { + regs->gpr[rd] = regs->ccr & imm; + break; + } + imm >>= 4; + } + + goto instr_done; + } + regs->gpr[rd] = regs->ccr; regs->gpr[rd] &= 0xffffffffUL; goto instr_done; -- cgit v0.10.2 From 88481a2c40e49912d0671cc7e9a5bd3534662b49 Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Thu, 6 Jul 2017 18:46:43 +1000 Subject: powerpc/asm: Mark cr0 as clobbered in mftb() commit 2400fd822f467cb4c886c879d8ad99feac9cf319 upstream. The workaround for the CELL timebase bug does not correctly mark cr0 as being clobbered. This means GCC doesn't know that the asm block changes cr0 and might leave the result of an unrelated comparison in cr0 across the block, which we then trash, leading to basically random behaviour. Fixes: 859deea949c3 ("[POWERPC] Cell timebase bug workaround") Signed-off-by: Oliver O'Halloran [mpe: Tweak change log and flag for stable] Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index e7d9eca..ceb168c 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1283,7 +1283,7 @@ static inline void msr_check_and_clear(unsigned long bits) " .llong 0\n" \ ".previous" \ : "=r" (rval) \ - : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL)); \ + : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \ rval;}) #else #define mftb() ({unsigned long rval; \ -- cgit v0.10.2 From 3b7babc6be0aa56297b5d1dea0090339a2d5659d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 8 Jul 2017 07:45:32 -0500 Subject: powerpc/mm/radix: Properly clear process table entry commit c6bb0b8d426a8cf865ca9c8a532cc3a2927cfceb upstream. On radix, the process table entry we want to clear when destroying a context is entry 0, not entry 1. This has no *immediate* consequence on Power9, but it can cause other bugs to become worse. Fixes: 7e381c0ff618 ("powerpc/mm/radix: Add mmu context handling callback for radix") Signed-off-by: Benjamin Herrenschmidt Reviewed-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index 73bf6e1..a006f82 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c @@ -167,9 +167,15 @@ void destroy_context(struct mm_struct *mm) mm->context.cop_lockp = NULL; #endif /* CONFIG_PPC_ICSWX */ - if (radix_enabled()) - process_tb[mm->context.id].prtb1 = 0; - else + if (radix_enabled()) { + /* + * Radix doesn't have a valid bit in the process table + * entries. However we know that at least P9 implementation + * will avoid caching an entry with an invalid RTS field, + * and 0 is invalid. So this will do. + */ + process_tb[mm->context.id].prtb0 = 0; + } else subpage_prot_free(mm); destroy_pagetable_page(mm); __destroy_context(mm->context.id); -- cgit v0.10.2 From 3c17d418afb017792aa961e6eebb2ecc1ca5c775 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 13 Apr 2017 18:35:59 +0800 Subject: af_key: Fix sadb_x_ipsecrequest parsing commit 096f41d3a8fcbb8dde7f71379b1ca85fe213eded upstream. The parsing of sadb_x_ipsecrequest is broken in a number of ways. First of all we're not verifying sadb_x_ipsecrequest_len. This is needed when the structure carries addresses at the end. Worse we don't even look at the length when we parse those optional addresses. The migration code had similar parsing code that's better but it also has some deficiencies. The length is overcounted first of all as it includes the header itself. It also fails to check the length before dereferencing the sa_family field. This patch fixes those problems in parse_sockaddr_pair and then uses it in parse_ipsecrequest. Reported-by: Andrey Konovalov Signed-off-by: Herbert Xu Signed-off-by: Steffen Klassert Signed-off-by: Greg Kroah-Hartman diff --git a/net/key/af_key.c b/net/key/af_key.c index e67c28e..d8d95b6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -65,6 +65,10 @@ struct pfkey_sock { } dump; }; +static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, + xfrm_address_t *saddr, xfrm_address_t *daddr, + u16 *family); + static inline struct pfkey_sock *pfkey_sk(struct sock *sk) { return (struct pfkey_sock *)sk; @@ -1922,19 +1926,14 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) /* addresses present only in tunnel mode */ if (t->mode == XFRM_MODE_TUNNEL) { - u8 *sa = (u8 *) (rq + 1); - int family, socklen; + int err; - family = pfkey_sockaddr_extract((struct sockaddr *)sa, - &t->saddr); - if (!family) - return -EINVAL; - - socklen = pfkey_sockaddr_len(family); - if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), - &t->id.daddr) != family) - return -EINVAL; - t->encap_family = family; + err = parse_sockaddr_pair( + (struct sockaddr *)(rq + 1), + rq->sadb_x_ipsecrequest_len - sizeof(*rq), + &t->saddr, &t->id.daddr, &t->encap_family); + if (err) + return err; } else t->encap_family = xp->family; @@ -1954,7 +1953,11 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy)) return -EINVAL; - while (len >= sizeof(struct sadb_x_ipsecrequest)) { + while (len >= sizeof(*rq)) { + if (len < rq->sadb_x_ipsecrequest_len || + rq->sadb_x_ipsecrequest_len < sizeof(*rq)) + return -EINVAL; + if ((err = parse_ipsecrequest(xp, rq)) < 0) return err; len -= rq->sadb_x_ipsecrequest_len; @@ -2417,7 +2420,6 @@ out: return err; } -#ifdef CONFIG_NET_KEY_MIGRATE static int pfkey_sockaddr_pair_size(sa_family_t family) { return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); @@ -2429,7 +2431,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, { int af, socklen; - if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) + if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) return -EINVAL; af = pfkey_sockaddr_extract(sa, saddr); @@ -2445,6 +2447,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, return 0; } +#ifdef CONFIG_NET_KEY_MIGRATE static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, struct xfrm_migrate *m) { @@ -2452,13 +2455,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, struct sadb_x_ipsecrequest *rq2; int mode; - if (len <= sizeof(struct sadb_x_ipsecrequest) || - len < rq1->sadb_x_ipsecrequest_len) + if (len < sizeof(*rq1) || + len < rq1->sadb_x_ipsecrequest_len || + rq1->sadb_x_ipsecrequest_len < sizeof(*rq1)) return -EINVAL; /* old endoints */ err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), - rq1->sadb_x_ipsecrequest_len, + rq1->sadb_x_ipsecrequest_len - sizeof(*rq1), &m->old_saddr, &m->old_daddr, &m->old_family); if (err) @@ -2467,13 +2471,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len); len -= rq1->sadb_x_ipsecrequest_len; - if (len <= sizeof(struct sadb_x_ipsecrequest) || - len < rq2->sadb_x_ipsecrequest_len) + if (len <= sizeof(*rq2) || + len < rq2->sadb_x_ipsecrequest_len || + rq2->sadb_x_ipsecrequest_len < sizeof(*rq2)) return -EINVAL; /* new endpoints */ err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), - rq2->sadb_x_ipsecrequest_len, + rq2->sadb_x_ipsecrequest_len - sizeof(*rq2), &m->new_saddr, &m->new_daddr, &m->new_family); if (err) -- cgit v0.10.2 From 13b2f9f9b8aaa2085a2fcf946b8280f4e3d0f4f8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 19 Aug 2016 16:30:25 +0800 Subject: PCI: Work around poweroff & suspend-to-RAM issue on Macbook Pro 11 commit 13cfc732160f7bc7e596128ce34cda361c556966 upstream. Neither soft poweroff (transition to ACPI power state S5) nor suspend-to-RAM (transition to state S3) works on the Macbook Pro 11,4 and 11,5. The problem is related to the [mem 0x7fa00000-0x7fbfffff] space. When we use that space, e.g., by assigning it to the 00:1c.0 Root Port, the ACPI Power Management 1 Control Register (PM1_CNT) at [io 0x1804] doesn't work anymore. Linux does a soft poweroff (transition to S5) by writing to PM1_CNT. The theory about why this doesn't work is: - The write to PM1_CNT causes an SMI - The BIOS SMI handler depends on something in [mem 0x7fa00000-0x7fbfffff] - When Linux assigns [mem 0x7fa00000-0x7fbfffff] to the 00:1c.0 Port, it covers up whatever the SMI handler uses, so the SMI handler no longer works correctly Reserve the [mem 0x7fa00000-0x7fbfffff] space so we don't assign it to anything. This is voodoo programming, since we don't know what the real conflict is, but we've failed to find the root cause. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=103211 Tested-by: thejoe@gmail.com Signed-off-by: Bjorn Helgaas Cc: Rafael J. Wysocki Cc: Lukas Wunner Cc: Chen Yu Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 6d52b94..20fa7c8 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -571,3 +571,35 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, pci_invalid_bar); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar); + +/* + * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff] + * + * Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to + * the 00:1c.0 Root Port, causes a conflict with [io 0x1804], which is used + * for soft poweroff and suspend-to-RAM. + * + * As far as we know, this is related to the address space, not to the Root + * Port itself. Attaching the quirk to the Root Port is a convenience, but + * it could probably also be a standalone DMI quirk. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=103211 + */ +static void quirk_apple_mbp_poweroff(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + + if ((!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,4") && + !dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,5")) || + pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x1c, 0)) + return; + + res = request_mem_region(0x7fa00000, 0x200000, + "MacBook Pro poweroff workaround"); + if (res) + dev_info(dev, "claimed %s %pR\n", res->name, res); + else + dev_info(dev, "can't work around MacBook Pro poweroff issue\n"); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff); -- cgit v0.10.2 From f257f4bf6f0766725fd8bcb243ad9271aee7a106 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 3 Jul 2017 17:21:02 +0800 Subject: PCI: rockchip: Use normal register bank for config accessors commit dc8cca5ef25ac4cb0dfc37467521a759767ff361 upstream. Rockchip's RC has two banks of registers for the root port: a normal bank that is strictly compatible with the PCIe spec, and a privileged bank that can be used to change RO bits of root port registers. When probing the RC driver, we use the privileged bank to do some basic setup work as some RO bits are hw-inited to wrong value. But we didn't change to the normal bank after probing the driver. This leads to a serious problem when the PME code tries to clear the PME status by writing PCI_EXP_RTSTA_PME to the register of PCI_EXP_RTSTA. Per PCIe 3.0 spec, section 7.8.14, the PME status bit is RW1C. So the PME code is doing the right thing to clear the PME status but we find the RC doesn't clear it but actually setting it to one. So finally the system trap in pcie_pme_work_fn() as PCI_EXP_RTSTA_PME is true now forever. This issue can be reproduced by booting kernel with pci=nomsi. Use the normal register bank for the PCI config accessors. The privileged bank is used only internally by this driver. Fixes: e77f847d ("PCI: rockchip: Add Rockchip PCIe controller support") Signed-off-by: Shawn Lin Signed-off-by: Bjorn Helgaas Cc: Jeffy Chen Cc: Brian Norris Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 3452983..03ebfd5 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -131,6 +131,7 @@ PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \ PCIE_CORE_INT_MMVC) +#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 #define PCIE_RC_CONFIG_BASE 0xa00000 #define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) @@ -267,7 +268,9 @@ static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip, static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip, int where, int size, u32 *val) { - void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where; + void __iomem *addr; + + addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where; if (!IS_ALIGNED((uintptr_t)addr, size)) { *val = 0; @@ -291,11 +294,13 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip, int where, int size, u32 val) { u32 mask, tmp, offset; + void __iomem *addr; offset = where & ~0x3; + addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset; if (size == 4) { - writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset); + writel(val, addr); return PCIBIOS_SUCCESSFUL; } @@ -306,9 +311,9 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip, * corrupt RW1C bits in adjacent registers. But the hardware * doesn't support smaller writes. */ - tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask; + tmp = readl(addr) & mask; tmp |= val << ((where & 0x3) * 8); - writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset); + writel(tmp, addr); return PCIBIOS_SUCCESSFUL; } -- cgit v0.10.2 From 33780512d9fe64872b3c46596d2c6d812be98fc9 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Thu, 25 May 2017 16:49:07 +0800 Subject: PCI/PM: Restore the status of PCI devices across hibernation commit e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 upstream. Currently we saw a lot of "No irq handler" errors during hibernation, which caused the system hang finally: ata4.00: qc timeout (cmd 0xec) ata4.00: failed to IDENTIFY (I/O error, err_mask=0x4) ata4.00: revalidation failed (errno=-5) ata4: SATA link up 6.0 Gbps (SStatus 133 SControl 300) do_IRQ: 31.151 No irq handler for vector According to above logs, there is an interrupt triggered and it is dispatched to CPU31 with a vector number 151, but there is no handler for it, thus this IRQ will not get acked and will cause an IRQ flood which kills the system. To be more specific, the 31.151 is an interrupt from the AHCI host controller. After some investigation, the reason why this issue is triggered is because the thaw_noirq() function does not restore the MSI/MSI-X settings across hibernation. The scenario is illustrated below: 1. Before hibernation, IRQ 34 is the handler for the AHCI device, which is bound to CPU31. 2. Hibernation starts, the AHCI device is put into low power state. 3. All the nonboot CPUs are put offline, so IRQ 34 has to be migrated to the last alive one - CPU0. 4. After the snapshot has been created, all the nonboot CPUs are brought up again; IRQ 34 remains bound to CPU0. 5. AHCI devices are put into D0. 6. The snapshot is written to the disk. The issue is triggered in step 6. The AHCI interrupt should be delivered to CPU0, however it is delivered to the original CPU31 instead, which causes the "No irq handler" issue. Ying Huang has provided a clue that, in step 3 it is possible that writing to the register might not take effect as the PCI devices have been suspended. In step 3, the IRQ 34 affinity should be modified from CPU31 to CPU0, but in fact it is not. In __pci_write_msi_msg(), if the device is already in low power state, the low level MSI message entry will not be updated but cached. During the device restore process after a normal suspend/resume, pci_restore_msi_state() writes the cached MSI back to the hardware. But this is not the case for hibernation. pci_restore_msi_state() is not currently called in pci_pm_thaw_noirq(), although pci_save_state() has saved the necessary PCI cached information in pci_pm_freeze_noirq(). Restore the PCI status for the device during hibernation. Otherwise the status might be lost across hibernation (for example, settings for MSI, MSI-X, ATS, ACS, IOV, etc.), which might cause problems during hibernation. Suggested-by: Ying Huang Suggested-by: Rafael J. Wysocki Signed-off-by: Chen Yu [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki Cc: Len Brown Cc: Dan Williams Cc: Rui Zhang Cc: Ying Huang Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 1ccce1c..8a68e2b 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -954,6 +954,7 @@ static int pci_pm_thaw_noirq(struct device *dev) return pci_legacy_resume_early(dev); pci_update_current_state(pci_dev, PCI_D0); + pci_restore_state(pci_dev); if (drv && drv->pm && drv->pm->thaw_noirq) error = drv->pm->thaw_noirq(dev); -- cgit v0.10.2 From 445ea10969aade3f9711b262756099717a5fe6bb Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sat, 29 Apr 2017 20:33:09 +0300 Subject: ipvs: SNAT packet replies only for NATed connections commit 3c5ab3f395d66a9e4e937fcfdf6ebc63894f028b upstream. We do not check if packet from real server is for NAT connection before performing SNAT. This causes problems for setups that use DR/TUN and allow local clients to access the real server directly, for example: - local client in director creates IPVS-DR/TUN connection CIP->VIP and the request packets are routed to RIP. Talks are finished but IPVS connection is not expired yet. - second local client creates non-IPVS connection CIP->RIP with same reply tuple RIP->CIP and when replies are received on LOCAL_IN we wrongly assign them for the first client connection because RIP->CIP matches the reply direction. As result, IPVS SNATs replies for non-IPVS connections. The problem is more visible to local UDP clients but in rare cases it can happen also for TCP or remote clients when the real server sends the reply traffic via the director. So, better to be more precise for the reply traffic. As replies are not expected for DR/TUN connections, better to not touch them. Reported-by: Nick Moriarty Tested-by: Nick Moriarty Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Greg Kroah-Hartman diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 2c1b498..e34d3f6 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -849,10 +849,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, { unsigned int verdict = NF_DROP; - if (IP_VS_FWD_METHOD(cp) != 0) { - pr_err("shouldn't reach here, because the box is on the " - "half connection in the tun/dr module.\n"); - } + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + goto ignore_cp; /* Ensure the checksum is correct */ if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { @@ -886,6 +884,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ip_vs_notrack(skb); else ip_vs_update_conntrack(skb, cp, 0); + +ignore_cp: verdict = NF_ACCEPT; out: @@ -1385,8 +1385,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in */ cp = pp->conn_out_get(ipvs, af, skb, &iph); - if (likely(cp)) + if (likely(cp)) { + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + goto ignore_cp; return handle_response(af, skb, pd, cp, &iph, hooknum); + } /* Check for real-server-started requests */ if (atomic_read(&ipvs->conn_out_counter)) { @@ -1444,9 +1447,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in } } } + +out: IP_VS_DBG_PKT(12, af, pp, skb, iph.off, "ip_vs_out: packet continues traversal as normal"); return NF_ACCEPT; + +ignore_cp: + __ip_vs_conn_put(cp); + goto out; } /* -- cgit v0.10.2 From bf0440882ea94629b198b132ce89c11e25b4b91d Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 20 Jul 2017 14:48:29 +0300 Subject: xhci: fix 20000ms port resume timeout commit a54408d0a004757789863d74e29c2297edae0b4d upstream. A uncleared PLC (port link change) bit will prevent furuther port event interrupts for that port. Leaving it uncleared caused get_port_status() to timeout after 20000ms while waiting to get the final port event interrupt for resume -> U0 state change. This is a targeted fix for a specific case where we get a port resume event racing with xhci resume. The port event interrupt handler notices xHC is not yet running and bails out early, leaving PLC uncleared. The whole xhci port resuming needs more attention, but while working on it it anyways makes sense to always ensure PLC is cleared in get_port_status before setting a new link state and waiting for its completion. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index ff544f2..36b7789 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -783,6 +783,9 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, clear_bit(wIndex, &bus_state->resuming_ports); set_bit(wIndex, &bus_state->rexit_ports); + + xhci_test_and_clear_bit(xhci, port_array, wIndex, + PORT_PLC); xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); -- cgit v0.10.2 From 01845a8347b73ddc89c0e7a81a108a4786ff07ea Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 20 Jul 2017 14:48:26 +0300 Subject: xhci: Fix NULL pointer dereference when cleaning up streams for removed host commit 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 upstream. This off by one in stream_id indexing caused NULL pointer dereference and soft lockup on machines with USB attached SCSI devices connected to a hotpluggable xhci controller. The code that cleans up pending URBs for dead hosts tried to dereference a stream ring at the invalid stream_id 0. ep->stream_info->stream_rings[0] doesn't point to a ring. Start looping stream_id from 1 like in all the other places in the driver, and check that the ring exists before trying to kill URBs on it. Reported-by: rocko r Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 521c181..63735b5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -860,13 +860,16 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, (ep->ep_state & EP_GETTING_NO_STREAMS)) { int stream_id; - for (stream_id = 0; stream_id < ep->stream_info->num_streams; + for (stream_id = 1; stream_id < ep->stream_info->num_streams; stream_id++) { + ring = ep->stream_info->stream_rings[stream_id]; + if (!ring) + continue; + xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Killing URBs for slot ID %u, ep index %u, stream %u", - slot_id, ep_index, stream_id + 1); - xhci_kill_ring_urbs(xhci, - ep->stream_info->stream_rings[stream_id]); + slot_id, ep_index, stream_id); + xhci_kill_ring_urbs(xhci, ring); } } else { ring = ep->ring; -- cgit v0.10.2 From 24a950e16eb54d42f25e4074bc00ee4a746877ac Mon Sep 17 00:00:00 2001 From: Jiahau Chang Date: Thu, 20 Jul 2017 14:48:27 +0300 Subject: xhci: Bad Ethernet performance plugged in ASM1042A host commit 9da5a1092b13468839b1a864b126cacfb72ad016 upstream. When USB Ethernet is plugged in ASMEDIA ASM1042A xHCI host, bad performance was manifesting in Web browser use (like download large file such as ISO image). It is known limitation of ASM1042A that is not compatible with driver scheduling, As a workaround we can modify flow control handling of ASM1042A. The register we modify is changes the behavior [use quirk bit 28, usleep_range 40-60us, empty non-pci function -Mathias] Signed-off-by: Jiahau Chang Signed-off-by: Ian Pilcher Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index a9a1e4c..c8989c6 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -77,6 +77,16 @@ #define USB_INTEL_USB3_PSSEN 0xD8 #define USB_INTEL_USB3PRM 0xDC +/* ASMEDIA quirk use */ +#define ASMT_DATA_WRITE0_REG 0xF8 +#define ASMT_DATA_WRITE1_REG 0xFC +#define ASMT_CONTROL_REG 0xE0 +#define ASMT_CONTROL_WRITE_BIT 0x02 +#define ASMT_WRITEREG_CMD 0x10423 +#define ASMT_FLOWCTL_ADDR 0xFA30 +#define ASMT_FLOWCTL_DATA 0xBA +#define ASMT_PSEUDO_DATA 0 + /* * amd_chipset_gen values represent AMD different chipset generations */ @@ -412,6 +422,50 @@ void usb_amd_quirk_pll_disable(void) } EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable); +static int usb_asmedia_wait_write(struct pci_dev *pdev) +{ + unsigned long retry_count; + unsigned char value; + + for (retry_count = 1000; retry_count > 0; --retry_count) { + + pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value); + + if (value == 0xff) { + dev_err(&pdev->dev, "%s: check_ready ERROR", __func__); + return -EIO; + } + + if ((value & ASMT_CONTROL_WRITE_BIT) == 0) + return 0; + + usleep_range(40, 60); + } + + dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__); + return -ETIMEDOUT; +} + +void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) +{ + if (usb_asmedia_wait_write(pdev) != 0) + return; + + /* send command and address to device */ + pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD); + pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR); + pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT); + + if (usb_asmedia_wait_write(pdev) != 0) + return; + + /* send data to device */ + pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA); + pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA); + pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT); +} +EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol); + void usb_amd_quirk_pll_enable(void) { usb_amd_quirk_pll(0); diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index c622ddf..6463fdb 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -11,6 +11,7 @@ bool usb_amd_prefetch_quirk(void); void usb_amd_dev_put(void); void usb_amd_quirk_pll_disable(void); void usb_amd_quirk_pll_enable(void); +void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev); void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); void sb800_prefetch(struct device *dev, int on); @@ -18,6 +19,7 @@ void sb800_prefetch(struct device *dev, int on); struct pci_dev; static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} +static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} static inline void usb_amd_dev_put(void) {} static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} static inline void sb800_prefetch(struct device *dev, int on) {} diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 672751e..2383344 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -59,6 +59,8 @@ #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc +#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 + static const char hcd_name[] = "xhci_hcd"; static struct hc_driver __read_mostly xhci_pci_hc_driver; @@ -217,6 +219,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == 0x1142) xhci->quirks |= XHCI_TRUST_TX_LENGTH; + if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) + xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL; + if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 34e23c7..82308af 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -192,6 +192,9 @@ int xhci_reset(struct xhci_hcd *xhci) if (ret) return ret; + if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL) + usb_asmedia_modifyflowcontrol(to_pci_dev(xhci_to_hcd(xhci)->self.controller)); + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Wait for controller to be ready for doorbell rings"); /* @@ -1122,6 +1125,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running) compliance_mode_recovery_timer_init(xhci); + if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL) + usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller)); + /* Re-enable port polling. */ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8336e07..a0f4a9f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1661,6 +1661,7 @@ struct xhci_hcd { #define XHCI_BROKEN_PORT_PED (1 << 25) #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) #define XHCI_U2_DISABLE_WAKE (1 << 27) +#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) unsigned int num_active_eps; unsigned int limit_active_eps; -- cgit v0.10.2 From 8bc51b4f2a42187b4386974ef92add94acafe135 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 21 Apr 2017 13:28:37 -0300 Subject: mxl111sf: Fix driver to use heap allocate buffers for USB messages commit d90b336f3f652ff0441e631a06236f785581c8f7 upstream. The recent changes in 4.9 to mandate USB buffers be heap allocated broke this driver, which was allocating the buffers on the stack. This resulted in the device failing at initialization. Introduce dedicated send/receive buffers as part of the state structure, and add a mutex to protect access to them. Note: we also had to tweak the API to mxl111sf_ctrl_msg to pass the pointer to the state struct rather than the device, since we need it inside the function to access the buffers and the mutex. This patch adjusts the callers to match the API change. Signed-off-by: Devin Heitmueller Reported-by: Doug Lung Cc: Michael Ira Krufky Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index 283495c..aab8eee 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -320,7 +320,7 @@ fail: static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, u8 index, u8 *wdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, NULL, 0); mxl_fail(ret); @@ -330,7 +330,7 @@ static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, static int mxl111sf_i2c_get_data(struct mxl111sf_state *state, u8 index, u8 *wdata, u8 *rdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, rdata, 24); mxl_fail(ret); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 5d676b5..f1f4486 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -24,9 +24,6 @@ #include "lgdt3305.h" #include "lg2160.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 - int dvb_usb_mxl111sf_debug; module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level " @@ -56,27 +53,34 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { + struct dvb_usb_device *d = state->d; int wo = (rbuf == NULL || rlen == 0); /* write-only */ int ret; - u8 sndbuf[MAX_XFER_SIZE]; - if (1 + wlen > sizeof(sndbuf)) { + if (1 + wlen > MXL_MAX_XFER_SIZE) { pr_warn("%s: len=%d is too big!\n", __func__, wlen); return -EOPNOTSUPP; } pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); - memset(sndbuf, 0, 1+wlen); + mutex_lock(&state->msg_lock); + memset(state->sndbuf, 0, 1+wlen); + memset(state->rcvbuf, 0, rlen); + + state->sndbuf[0] = cmd; + memcpy(&state->sndbuf[1], wbuf, wlen); - sndbuf[0] = cmd; - memcpy(&sndbuf[1], wbuf, wlen); + ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) : + dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf, + rlen); + + memcpy(rbuf, state->rcvbuf, rlen); + mutex_unlock(&state->msg_lock); - ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) : - dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen); mxl_fail(ret); return ret; @@ -92,7 +96,7 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) u8 buf[2]; int ret; - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2); if (mxl_fail(ret)) { mxl_debug("error reading reg: 0x%02x", addr); goto fail; @@ -118,7 +122,7 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; @@ -922,6 +926,8 @@ static int mxl111sf_init(struct dvb_usb_device *d) static u8 eeprom[256]; struct i2c_client c; + mutex_init(&state->msg_lock); + ret = get_chip_info(state); if (mxl_fail(ret)) pr_err("failed to get chip info during probe"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 846260e..3e6f588 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -19,6 +19,9 @@ #include #include +/* Max transfer size done by I2C transfer functions */ +#define MXL_MAX_XFER_SIZE 64 + #define MXL_EP1_REG_READ 1 #define MXL_EP2_REG_WRITE 2 #define MXL_EP3_INTERRUPT 3 @@ -86,6 +89,9 @@ struct mxl111sf_state { struct mutex fe_lock; u8 num_frontends; struct mxl111sf_adap_state adap_state[3]; + u8 sndbuf[MXL_MAX_XFER_SIZE]; + u8 rcvbuf[MXL_MAX_XFER_SIZE]; + struct mutex msg_lock; #ifdef CONFIG_MEDIA_CONTROLLER_DVB struct media_entity tuner; struct media_pad tuner_pads[2]; @@ -108,7 +114,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, /* needed for hardware i2c functions in mxl111sf-i2c.c: * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */ -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen); #define mxl_printk(kern, fmt, arg...) \ -- cgit v0.10.2 From 8665f40a06a0794517f226cad694386faf9802c3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Jul 2017 16:06:32 +0100 Subject: usb: storage: return on error to avoid a null pointer dereference commit 446230f52a5bef593554510302465eabab45a372 upstream. When us->extra is null the driver is not initialized, however, a later call to osd200_scsi_to_ata is made that dereferences us->extra, causing a null pointer dereference. The code currently detects and reports that the driver is not initialized; add a return to avoid the subsequent dereference issue in this check. Thanks to Alan Stern for pointing out that srb->result needs setting to DID_ERROR << 16 Detected by CoverityScan, CID#100308 ("Dereference after null check") Signed-off-by: Colin Ian King Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index fba4005..6a7720e 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1529,8 +1529,11 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) /* Make sure driver was initialized */ - if (us->extra == NULL) + if (us->extra == NULL) { usb_stor_dbg(us, "ERROR Driver not initialized\n"); + srb->result = DID_ERROR << 16; + return; + } scsi_set_resid(srb, 0); /* scsi_bufflen might change in protocol translation to ata */ -- cgit v0.10.2 From a74779d8e1726da718e0a71066e5c4de5b07012c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 12 Jul 2017 15:08:39 +0200 Subject: USB: cdc-acm: add device-id for quirky printer commit fe855789d605590e57f9cd968d85ecce46f5c3fd upstream. Add device-id entry for DATECS FP-2000 fiscal printer needing the NO_UNION_NORMAL quirk. Reported-by: Anton Avramov Signed-off-by: Johan Hovold Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a876d47..f16491c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1770,6 +1770,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, + { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ + }, { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ .driver_info = CLEAR_HALT_CONDITIONS, -- cgit v0.10.2 From 5433bfcc85273a89c7c5a565a337697ff31ae499 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 19 Jul 2017 16:16:54 +0900 Subject: usb: renesas_usbhs: fix usbhsc_resume() for !USBHSF_RUNTIME_PWCTRL commit 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce upstream. This patch fixes an issue that some registers may be not initialized after resume if the USBHSF_RUNTIME_PWCTRL is not set. Otherwise, if a cable is not connected, the driver will not enable INTENB0.VBSE after resume. And then, the driver cannot detect the VBUS. Fixes: ca8a282a5373 ("usb: gadget: renesas_usbhs: add suspend/resume support") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 012a37a..7994208 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -752,8 +752,10 @@ static int usbhsc_resume(struct device *dev) struct usbhs_priv *priv = dev_get_drvdata(dev); struct platform_device *pdev = usbhs_priv_to_pdev(priv); - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { usbhsc_power_ctrl(priv, 1); + usbhs_mod_autonomy_mode(priv); + } usbhs_platform_call(priv, phy_reset, pdev); -- cgit v0.10.2 From dbc969ca944f1a3f61af083f4126bb5408d37b4c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 19 Jul 2017 16:16:55 +0900 Subject: usb: renesas_usbhs: gadget: disable all eps when the driver stops commit b8b9c974afee685789fcbb191b52d1790be3608c upstream. A gadget driver will not disable eps immediately when ->disconnect() is called. But, since this driver assumes all eps stop after the ->disconnect(), unexpected behavior happens (especially in system suspend). So, this patch disables all eps in usbhsg_try_stop(). After disabling eps by renesas_usbhs driver, since some functions will be called by both a gadget and renesas_usbhs driver, renesas_usbhs driver should protect uep->pipe. To protect uep->pipe easily, this patch adds a new lock in struct usbhsg_uep. Fixes: 2f98382dc ("usb: renesas_usbhs: Add Renesas USBHS Gadget") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 5bc7a61..93fba90 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -37,6 +37,7 @@ struct usbhsg_gpriv; struct usbhsg_uep { struct usb_ep ep; struct usbhs_pipe *pipe; + spinlock_t lock; /* protect the pipe */ char ep_name[EP_NAME_SIZE]; @@ -636,10 +637,16 @@ usbhsg_ep_enable_end: static int usbhsg_ep_disable(struct usb_ep *ep) { struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); - struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); + struct usbhs_pipe *pipe; + unsigned long flags; + int ret = 0; - if (!pipe) - return -EINVAL; + spin_lock_irqsave(&uep->lock, flags); + pipe = usbhsg_uep_to_pipe(uep); + if (!pipe) { + ret = -EINVAL; + goto out; + } usbhsg_pipe_disable(uep); usbhs_pipe_free(pipe); @@ -647,6 +654,9 @@ static int usbhsg_ep_disable(struct usb_ep *ep) uep->pipe->mod_private = NULL; uep->pipe = NULL; +out: + spin_unlock_irqrestore(&uep->lock, flags); + return 0; } @@ -696,8 +706,11 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) { struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); - struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); + struct usbhs_pipe *pipe; + unsigned long flags; + spin_lock_irqsave(&uep->lock, flags); + pipe = usbhsg_uep_to_pipe(uep); if (pipe) usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); @@ -706,6 +719,7 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) * even if the pipe is NULL. */ usbhsg_queue_pop(uep, ureq, -ECONNRESET); + spin_unlock_irqrestore(&uep->lock, flags); return 0; } @@ -852,10 +866,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); - struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); + struct usbhsg_uep *uep; struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; - int ret = 0; + int ret = 0, i; /******************** spin lock ********************/ usbhs_lock(priv, flags); @@ -887,7 +901,9 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) usbhs_sys_set_test_mode(priv, 0); usbhs_sys_function_ctrl(priv, 0); - usbhsg_ep_disable(&dcp->ep); + /* disable all eps */ + usbhsg_for_each_uep_with_dcp(uep, gpriv, i) + usbhsg_ep_disable(&uep->ep); dev_dbg(dev, "stop gadget\n"); @@ -1069,6 +1085,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) ret = -ENOMEM; goto usbhs_mod_gadget_probe_err_gpriv; } + spin_lock_init(&uep->lock); gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); dev_info(dev, "%stransceiver found\n", -- cgit v0.10.2 From 03c1d9d45582e8a0991747a6f7a3a235b39b3e2b Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 7 Jun 2017 19:05:31 -0400 Subject: md: don't use flush_signals in userspace processes commit f9c79bc05a2a91f4fba8bfd653579e066714b1ec upstream. The function flush_signals clears all pending signals for the process. It may be used by kernel threads when we need to prepare a kernel thread for responding to signals. However using this function for an userspaces processes is incorrect - clearing signals without the program expecting it can cause misbehavior. The raid1 and raid5 code uses flush_signals in its request routine because it wants to prepare for an interruptible wait. This patch drops flush_signals and uses sigprocmask instead to block all signals (including SIGKILL) around the schedule() call. The signals are not lost, but the schedule() call won't respond to them. Signed-off-by: Mikulas Patocka Acked-by: NeilBrown Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 29e2df5..81a7875 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1073,7 +1073,7 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio) */ DEFINE_WAIT(w); for (;;) { - flush_signals(current); + sigset_t full, old; prepare_to_wait(&conf->wait_barrier, &w, TASK_INTERRUPTIBLE); if (bio_end_sector(bio) <= mddev->suspend_lo || @@ -1082,7 +1082,10 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio) !md_cluster_ops->area_resyncing(mddev, WRITE, bio->bi_iter.bi_sector, bio_end_sector(bio)))) break; + sigfillset(&full); + sigprocmask(SIG_BLOCK, &full, &old); schedule(); + sigprocmask(SIG_SETMASK, &old, NULL); } finish_wait(&conf->wait_barrier, &w); } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f34ad2b..a613eea 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5300,12 +5300,15 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi) * userspace, we want an interruptible * wait. */ - flush_signals(current); prepare_to_wait(&conf->wait_for_overlap, &w, TASK_INTERRUPTIBLE); if (logical_sector >= mddev->suspend_lo && logical_sector < mddev->suspend_hi) { + sigset_t full, old; + sigfillset(&full); + sigprocmask(SIG_BLOCK, &full, &old); schedule(); + sigprocmask(SIG_SETMASK, &old, NULL); do_prepare = true; } goto retry; -- cgit v0.10.2 From 4d3d3a1690c25205b36f6ec015458466e1ea6dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 26 Jun 2017 14:49:46 +0200 Subject: x86/xen: allow userspace access during hypercalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c54590cac51db8ab5fd30156bdaba34af915e629 upstream. Userspace application can do a hypercall through /dev/xen/privcmd, and some for some hypercalls argument is a pointers to user-provided structure. When SMAP is supported and enabled, hypervisor can't access. So, lets allow it. The same applies to HYPERVISOR_dm_op, where additionally privcmd driver carefully verify buffer addresses. Cc: stable@vger.kernel.org Signed-off-by: Marek Marczykowski-Górecki Reviewed-by: Juergen Gross [HYPERVISOR_dm_op dropped - not present until 4.11] Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index a12a047..8b678af 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -214,10 +215,12 @@ privcmd_call(unsigned call, __HYPERCALL_DECLS; __HYPERCALL_5ARG(a1, a2, a3, a4, a5); + stac(); asm volatile("call *%[call]" : __HYPERCALL_5PARAM : [call] "a" (&hypercall_page[call]) : __HYPERCALL_CLOBBER5); + clac(); return (long)__res; } -- cgit v0.10.2 From e82672f45ea3dd7511fcbe0098df3f4fe65c20e8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 20 Sep 2014 09:23:44 -0300 Subject: cx88: Fix regression in initial video standard setting commit 4e0973a918b9a42e217093f078e04a61e5dd95a5 upstream. Setting initial standard at the top of cx8800_initdev would cause the first call to cx88_set_tvnorm() to return without programming any registers (leaving the driver saying it's set to NTSC but the hardware isn't programmed). Even worse, any subsequent attempt to explicitly set it to NTSC-M will return success but actually fail to program the underlying registers unless first changing the standard to something other than NTSC-M. Set the initial standard later in the process, and make sure the field is zero at the beginning to ensure that the call always goes through. This regression was introduced in the following commit: commit ccd6f1d488e7 ("[media] cx88: move width, height and field to core struct") Author: Hans Verkuil [media] cx88: move width, height and field to core struct Signed-off-by: Devin Heitmueller Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 8f2556e..61611d1 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3691,7 +3691,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->nr = nr; sprintf(core->name, "cx88[%d]", core->nr); - core->tvnorm = V4L2_STD_NTSC_M; + /* + * Note: Setting initial standard here would cause first call to + * cx88_set_tvnorm() to return without programming any registers. Leave + * it blank for at this point and it will get set later in + * cx8800_initdev() + */ + core->tvnorm = 0; + core->width = 320; core->height = 240; core->field = V4L2_FIELD_INTERLACED; diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index d83eb3b..3b140ad 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1422,7 +1422,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, /* initial device configuration */ mutex_lock(&core->lock); - cx88_set_tvnorm(core, core->tvnorm); + cx88_set_tvnorm(core, V4L2_STD_NTSC_M); v4l2_ctrl_handler_setup(&core->video_hdl); v4l2_ctrl_handler_setup(&core->audio_hdl); cx88_video_mux(core, 0); -- cgit v0.10.2 From 891c31e16cb7aab2356625444f3eedebb96cde00 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Thu, 29 Jun 2017 16:59:11 -0600 Subject: libnvdimm, btt: fix btt_rw_page not returning errors commit c13c43d54f2c6a3be1c675766778ac1ad8dfbfcc upstream. btt_rw_page was not propagating errors frm btt_do_bvec, resulting in any IO errors via the rw_page path going unnoticed. the pmem driver recently fixed this in e10624f pmem: fail io-requests to known bad blocks but same problem in BTT went neglected. Fixes: 5212e11fde4d ("nd_btt: atomic sector updates") Cc: Toshi Kani Cc: Dan Williams Cc: Jeff Moyer Signed-off-by: Vishal Verma Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index 368795a..94733f7 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1203,10 +1203,13 @@ static int btt_rw_page(struct block_device *bdev, sector_t sector, struct page *page, bool is_write) { struct btt *btt = bdev->bd_disk->private_data; + int rc; - btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector); - page_endio(page, is_write, 0); - return 0; + rc = btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector); + if (rc == 0) + page_endio(page, is_write, 0); + + return rc; } -- cgit v0.10.2 From 0fa705dc61ee12e09827ac19225be3731b1cb988 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Fri, 7 Jul 2017 17:44:26 -0600 Subject: libnvdimm: fix badblock range handling of ARS range commit 4e3f0701f25ab194c5362576b1146a1e6cc6c2e7 upstream. __add_badblock_range() does not account sector alignment when it sets 'num_sectors'. Therefore, an ARS error record range spanning across two sectors is set to a single sector length, which leaves the 2nd sector unprotected. Change __add_badblock_range() to set 'num_sectors' properly. Fixes: 0caeef63e6d2 ("libnvdimm: Add a poison list and export badblocks") Signed-off-by: Toshi Kani Reviewed-by: Vishal Verma Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 7ceba08..18a0bea 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -450,14 +450,15 @@ static void set_badblock(struct badblocks *bb, sector_t s, int num) static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len) { const unsigned int sector_size = 512; - sector_t start_sector; + sector_t start_sector, end_sector; u64 num_sectors; u32 rem; start_sector = div_u64(ns_offset, sector_size); - num_sectors = div_u64_rem(len, sector_size, &rem); + end_sector = div_u64_rem(ns_offset + len, sector_size, &rem); if (rem) - num_sectors++; + end_sector++; + num_sectors = end_sector - start_sector; if (unlikely(num_sectors > (u64)INT_MAX)) { u64 remaining = num_sectors; -- cgit v0.10.2 From 4d1f97eb59a472a11982d6fff9a722b681225e1a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 21 Jun 2017 14:34:15 +0200 Subject: ext2: Don't clear SGID when inheriting ACLs commit a992f2d38e4ce17b8c7d1f7f67b2de0eebdea069 upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by creating __ext2_set_acl() function that does not call posix_acl_update_mode() and use it when inheriting ACLs. That prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: linux-ext4@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 79dafa7..069c0dc 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -175,11 +175,8 @@ ext2_get_acl(struct inode *inode, int type) return acl; } -/* - * inode->i_mutex: down - */ -int -ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +static int +__ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int name_index; void *value = NULL; @@ -189,13 +186,6 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; - if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) - return error; - inode->i_ctime = current_time(inode); - mark_inode_dirty(inode); - } break; case ACL_TYPE_DEFAULT: @@ -222,6 +212,24 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) } /* + * inode->i_mutex: down + */ +int +ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + int error; + + if (type == ACL_TYPE_ACCESS && acl) { + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (error) + return error; + inode->i_ctime = current_time(inode); + mark_inode_dirty(inode); + } + return __ext2_set_acl(inode, acl, type); +} + +/* * Initialize the ACLs of a new inode. Called from ext2_new_inode. * * dir->i_mutex: down @@ -238,12 +246,12 @@ ext2_init_acl(struct inode *inode, struct inode *dir) return error; if (default_acl) { - error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + error = __ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } if (acl) { if (!error) - error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS); + error = __ext2_set_acl(inode, acl, ACL_TYPE_ACCESS); posix_acl_release(acl); } return error; -- cgit v0.10.2 From 1e95148551f3ea57aef1a97d1b2a825be5a7704a Mon Sep 17 00:00:00 2001 From: Xiao Ni Date: Wed, 5 Jul 2017 17:34:04 +0800 Subject: Raid5 should update rdev->sectors after reshape commit b5d27718f38843a74552e9a93d32e2391fd3999f upstream. The raid5 md device is created by the disks which we don't use the total size. For example, the size of the device is 5G and it just uses 3G of the devices to create one raid5 device. Then change the chunksize and wait reshape to finish. After reshape finishing stop the raid and assemble it again. It fails. mdadm -CR /dev/md0 -l5 -n3 /dev/loop[0-2] --size=3G --chunk=32 --assume-clean mdadm /dev/md0 --grow --chunk=64 wait reshape to finish mdadm -S /dev/md0 mdadm -As The error messages: [197519.814302] md: loop1 does not have a valid v1.2 superblock, not importing! [197519.821686] md: md_import_device returned -22 After reshape the data offset is changed. It selects backwards direction in this condition. In function super_1_load it compares the available space of the underlying device with sb->data_size. The new data offset gets bigger after reshape. So super_1_load returns -EINVAL. rdev->sectors is updated in md_finish_reshape. Then sb->data_size is set in super_1_sync based on rdev->sectors. So add md_finish_reshape in end_reshape. Signed-off-by: Xiao Ni Acked-by: Guoqing Jiang Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a613eea..8f117d6 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7560,12 +7560,10 @@ static void end_reshape(struct r5conf *conf) { if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { - struct md_rdev *rdev; spin_lock_irq(&conf->device_lock); conf->previous_raid_disks = conf->raid_disks; - rdev_for_each(rdev, conf->mddev) - rdev->data_offset = rdev->new_data_offset; + md_finish_reshape(conf->mddev); smp_wmb(); conf->reshape_progress = MaxSector; conf->mddev->reshape_position = MaxSector; -- cgit v0.10.2 From 8302e9d2f50b4358e4419deae2b09e0ccca766c6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 29 Jun 2017 11:38:11 +0200 Subject: s390/syscalls: Fix out of bounds arguments access commit c46fc0424ced3fb71208e72bd597d91b9169a781 upstream. Zorro reported following crash while having enabled syscall tracing (CONFIG_FTRACE_SYSCALLS): Unable to handle kernel pointer dereference at virtual ... Oops: 0011 [#1] SMP DEBUG_PAGEALLOC SNIP Call Trace: ([<000000000024d79c>] ftrace_syscall_enter+0xec/0x1d8) [<00000000001099c6>] do_syscall_trace_enter+0x236/0x2f8 [<0000000000730f1c>] sysc_tracesys+0x1a/0x32 [<000003fffcf946a2>] 0x3fffcf946a2 INFO: lockdep is turned off. Last Breaking-Event-Address: [<000000000022dd44>] rb_event_data+0x34/0x40 ---[ end trace 8c795f86b1b3f7b9 ]--- The crash happens in syscall_get_arguments function for syscalls with zero arguments, that will try to access first argument (args[0]) in event entry, but it's not allocated. Bail out of there are no arguments. Reported-by: Zorro Lang Signed-off-by: Jiri Olsa Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 6ba0bf9..6bc941b 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -64,6 +64,12 @@ static inline void syscall_get_arguments(struct task_struct *task, { unsigned long mask = -1UL; + /* + * No arguments for this syscall, there's nothing to do. + */ + if (!n) + return; + BUG_ON(i + n > 6); #ifdef CONFIG_COMPAT if (test_tsk_thread_flag(task, TIF_31BIT)) -- cgit v0.10.2 From b85007c9114a05c696c46c2aac6da68aeaed7bbc Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 23 May 2017 11:35:22 -0400 Subject: drm/amd/amdgpu: Return error if initiating read out of range on vram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9156e723301c0a7a7def4cde820e018ce791b842 upstream. If you initiate a read that is out of the VRAM address space return ENXIO instead of 0. Reads that begin below that point will read upto the VRAM limit as before. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dcaf691..264899d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1419,6 +1419,9 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; + if (*pos >= adev->mc.mc_vram_size) + return -ENXIO; + while (size) { unsigned long flags; uint32_t value; -- cgit v0.10.2 From a844f8d2a564d00d0043487d860a82d303b1a313 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 11 May 2017 13:14:14 -0400 Subject: drm/radeon/ci: disable mclk switching for high refresh rates (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ab03d9fe508f4e2914a8f4a9eef1b21051cacd0f upstream. Even if the vblank period would allow it, it still seems to be problematic on some cards. v2: fix logic inversion (Nils) bug: https://bugs.freedesktop.org/show_bug.cgi?id=96868 Acked-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index ea36dc4..2481049 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -782,6 +782,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev) if (r600_dpm_get_vrefresh(rdev) > 120) return true; + /* disable mclk switching if the refresh is >120Hz, even if the + * blanking period would allow it + */ + if (r600_dpm_get_vrefresh(rdev) > 120) + return true; + if (vblank_time < switch_limit) return true; else -- cgit v0.10.2 From 6e7b1eff91aa3bcc222e665328bea9988b453218 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Fri, 7 Jul 2017 04:57:04 +0200 Subject: drm/radeon: Fix eDP for single-display iMac10,1 (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 564d8a2cf3abf16575af48bdc3e86e92ee8a617d upstream. The late 2009, 27 inch Apple iMac10,1 has an internal eDP display and an external Mini- Displayport output, driven by a DCE-3.2, RV730 Radeon Mobility HD-4670. The machine worked fine in a dual-display setup with eDP panel + externally connected HDMI or DVI-D digital display sink, connected via MiniDP to DVI or HDMI adapter. However, booting the machine single-display with only eDP panel results in a completely black display - even backlight powering off, as soon as the radeon modesetting driver loads. This patch fixes the single dispay eDP case by assigning encoders based on dig->linkb, similar to DCE-4+. While this should not be generally necessary (Alex: "...atom on normal boards should be able to handle any mapping."), Apple seems to use some special routing here. One remaining problem not solved by this patch is that an external Minidisplayport->DP sink does still not work on iMac10,1, whereas external DVI and HDMI sinks continue to work. The problem affects at least all tested kernels since Linux 3.13 - didn't test earlier kernels, so backporting to stable probably makes sense. v2: With the original patch from 2016, Alex was worried it will break other DCE3.2 systems. Use dmi_match() to apply this special encoder assignment only for the Apple iMac 10,1 from late 2009. Signed-off-by: Mario Kleiner Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 56bb758..7bb1e53 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -30,6 +30,7 @@ #include "radeon_audio.h" #include "atom.h" #include +#include extern int atom_debug; @@ -2183,9 +2184,17 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx) goto assigned; } - /* on DCE32 and encoder can driver any block so just crtc id */ + /* + * On DCE32 any encoder can drive any block so usually just use crtc id, + * but Apple thinks different at least on iMac10,1, so there use linkb, + * otherwise the internal eDP panel will stay dark. + */ if (ASIC_IS_DCE32(rdev)) { - enc_idx = radeon_crtc->crtc_id; + if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1")) + enc_idx = (dig->linkb) ? 1 : 0; + else + enc_idx = radeon_crtc->crtc_id; + goto assigned; } -- cgit v0.10.2 From 685e124ebc7f11de248b68f883cd845523a63fc9 Mon Sep 17 00:00:00 2001 From: Tony Camuso Date: Mon, 19 Jun 2017 13:17:33 -0400 Subject: ipmi: use rcu lock around call to intf->handlers->sender() commit cdea46566bb21ce309725a024208322a409055cc upstream. A vendor with a system having more than 128 CPUs occasionally encounters the following crash during shutdown. This is not an easily reproduceable event, but the vendor was able to provide the following analysis of the crash, which exhibits the same footprint each time. crash> bt PID: 0 TASK: ffff88017c70ce70 CPU: 5 COMMAND: "swapper/5" #0 [ffff88085c143ac8] machine_kexec at ffffffff81059c8b #1 [ffff88085c143b28] __crash_kexec at ffffffff811052e2 #2 [ffff88085c143bf8] crash_kexec at ffffffff811053d0 #3 [ffff88085c143c10] oops_end at ffffffff8168ef88 #4 [ffff88085c143c38] no_context at ffffffff8167ebb3 #5 [ffff88085c143c88] __bad_area_nosemaphore at ffffffff8167ec49 #6 [ffff88085c143cd0] bad_area_nosemaphore at ffffffff8167edb3 #7 [ffff88085c143ce0] __do_page_fault at ffffffff81691d1e #8 [ffff88085c143d40] do_page_fault at ffffffff81691ec5 #9 [ffff88085c143d70] page_fault at ffffffff8168e188 [exception RIP: unknown or invalid address] RIP: ffffffffa053c800 RSP: ffff88085c143e28 RFLAGS: 00010206 RAX: ffff88017c72bfd8 RBX: ffff88017a8dc000 RCX: ffff8810588b5ac8 RDX: ffff8810588b5a00 RSI: ffffffffa053c800 RDI: ffff8810588b5a00 RBP: ffff88085c143e58 R8: ffff88017c70d408 R9: ffff88017a8dc000 R10: 0000000000000002 R11: ffff88085c143da0 R12: ffff8810588b5ac8 R13: 0000000000000100 R14: ffffffffa053c800 R15: ffff8810588b5a00 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 [exception RIP: cpuidle_enter_state+82] RIP: ffffffff81514192 RSP: ffff88017c72be50 RFLAGS: 00000202 RAX: 0000001e4c3c6f16 RBX: 000000000000f8a0 RCX: 0000000000000018 RDX: 0000000225c17d03 RSI: ffff88017c72bfd8 RDI: 0000001e4c3c6f16 RBP: ffff88017c72be78 R8: 000000000000237e R9: 0000000000000018 R10: 0000000000002494 R11: 0000000000000001 R12: ffff88017c72be20 R13: ffff88085c14f8e0 R14: 0000000000000082 R15: 0000001e4c3bb400 ORIG_RAX: ffffffffffffff10 CS: 0010 SS: 0018 This is the corresponding stack trace It has crashed because the area pointed with RIP extracted from timer element is already removed during a shutdown process. The function is smi_timeout(). And we think ffff8810588b5a00 in RDX is a parameter struct smi_info crash> rd ffff8810588b5a00 20 ffff8810588b5a00: ffff8810588b6000 0000000000000000 .`.X............ ffff8810588b5a10: ffff880853264400 ffffffffa05417e0 .D&S......T..... ffff8810588b5a20: 24a024a000000000 0000000000000000 .....$.$........ ffff8810588b5a30: 0000000000000000 0000000000000000 ................ ffff8810588b5a30: 0000000000000000 0000000000000000 ................ ffff8810588b5a40: ffffffffa053a040 ffffffffa053a060 @.S.....`.S..... ffff8810588b5a50: 0000000000000000 0000000100000001 ................ ffff8810588b5a60: 0000000000000000 0000000000000e00 ................ ffff8810588b5a70: ffffffffa053a580 ffffffffa053a6e0 ..S.......S..... ffff8810588b5a80: ffffffffa053a4a0 ffffffffa053a250 ..S.....P.S..... ffff8810588b5a90: 0000000500000002 0000000000000000 ................ Unfortunately the top of this area is already detroyed by someone. But because of two reasonns we think this is struct smi_info 1) The address included in between ffff8810588b5a70 and ffff8810588b5a80: are inside of ipmi_si_intf.c see crash> module ffff88085779d2c0 2) We've found the area which point this. It is offset 0x68 of ffff880859df4000 crash> rd ffff880859df4000 100 ffff880859df4000: 0000000000000000 0000000000000001 ................ ffff880859df4010: ffffffffa0535290 dead000000000200 .RS............. ffff880859df4020: ffff880859df4020 ffff880859df4020 @.Y.... @.Y.... ffff880859df4030: 0000000000000002 0000000000100010 ................ ffff880859df4040: ffff880859df4040 ffff880859df4040 @@.Y....@@.Y.... ffff880859df4050: 0000000000000000 0000000000000000 ................ ffff880859df4060: 0000000000000000 ffff8810588b5a00 .........Z.X.... ffff880859df4070: 0000000000000001 ffff880859df4078 ........x@.Y.... If we regards it as struct ipmi_smi in shutdown process it looks consistent. The remedy for this apparent race is affixed below. Signed-off-by: Tony Camuso Signed-off-by: Greg Kroah-Hartman This was first introduced in 7ea0ed2b5be817 ipmi: Make the message handler easier to use for SMI interfaces where some code was moved outside of the rcu_read_lock() and the lock was not added. Signed-off-by: Corey Minyard diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index fcdd886..172a9dc 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3877,6 +3877,9 @@ static void smi_recv_tasklet(unsigned long val) * because the lower layer is allowed to hold locks while calling * message delivery. */ + + rcu_read_lock(); + if (!run_to_completion) spin_lock_irqsave(&intf->xmit_msgs_lock, flags); if (intf->curr_msg == NULL && !intf->in_shutdown) { @@ -3899,6 +3902,8 @@ static void smi_recv_tasklet(unsigned long val) if (newmsg) intf->handlers->sender(intf->send_info, newmsg); + rcu_read_unlock(); + handle_new_recv_msgs(intf); } -- cgit v0.10.2 From 1b9008cdae94e6c4ae42bc90bf031b9fefcf7a93 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 30 Jun 2017 07:18:08 -0500 Subject: ipmi:ssif: Add missing unlock in error branch commit 4495ec6d770e1bca7a04e93ac453ab6720c56c5d upstream. When getting flags, a response to a different message would result in a deadlock because of a missing unlock. Add that unlock and a comment. Found by static analysis. Reported-by: Dan Carpenter Signed-off-by: Corey Minyard Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 6958b5c..510fc10 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -762,6 +762,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, result, len, data[2]); } else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || data[1] != IPMI_GET_MSG_FLAGS_CMD) { + /* + * Don't abort here, maybe it was a queued + * response to a previous command. + */ + ipmi_ssif_unlock_cond(ssif_info, flags); pr_warn(PFX "Invalid response getting flags: %x %x\n", data[0], data[1]); } else { -- cgit v0.10.2 From 58d2eacd3b0ef6eb7d7a786021f1bcd7f147082d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jun 2017 08:48:18 -0700 Subject: xfs: Don't clear SGID when inheriting ACLs commit 8ba358756aa08414fa9e65a1a41d28304ed6fd7f upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by calling __xfs_set_acl() instead of xfs_set_acl() when setting up inode in xfs_generic_create(). That prevents SGID bit clearing and mode is properly set by posix_acl_create() anyway. We also reorder arguments of __xfs_set_acl() to match the ordering of xfs_set_acl() to make things consistent. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: Darrick J. Wong CC: linux-xfs@vger.kernel.org Signed-off-by: Jan Kara Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Signed-off-by: Greg Kroah-Hartman diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index b468e04..7034e17 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -170,8 +170,8 @@ xfs_get_acl(struct inode *inode, int type) return acl; } -STATIC int -__xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) +int +__xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { struct xfs_inode *ip = XFS_I(inode); unsigned char *ea_name; @@ -268,5 +268,5 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) } set_acl: - return __xfs_set_acl(inode, type, acl); + return __xfs_set_acl(inode, acl, type); } diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 286fa89..0432731 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -24,6 +24,7 @@ struct posix_acl; #ifdef CONFIG_XFS_POSIX_ACL extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); +extern int __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); #else static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) { diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f5e0f60..a1247c3 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -190,12 +190,12 @@ xfs_generic_create( #ifdef CONFIG_XFS_POSIX_ACL if (default_acl) { - error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); if (error) goto out_cleanup_inode; } if (acl) { - error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS); + error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS); if (error) goto out_cleanup_inode; } -- cgit v0.10.2 From 19e117a50135efbb1d7c5ab1f24522162cc30bf0 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Thu, 1 Jun 2017 11:18:30 -0700 Subject: f2fs: sanity check size of nat and sit cache commit 21d3f8e1c3b7996ce239ab6fa82e9f7a8c47d84d upstream. Make sure number of entires doesn't exceed max journal size. Signed-off-by: Jin Qian Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Greg Kroah-Hartman diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a7943f8..74a2b44 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1805,6 +1805,8 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) static int restore_curseg_summaries(struct f2fs_sb_info *sbi) { + struct f2fs_journal *sit_j = CURSEG_I(sbi, CURSEG_COLD_DATA)->journal; + struct f2fs_journal *nat_j = CURSEG_I(sbi, CURSEG_HOT_DATA)->journal; int type = CURSEG_HOT_DATA; int err; @@ -1831,6 +1833,11 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi) return err; } + /* sanity check for summary blocks */ + if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES || + sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) + return -EINVAL; + return 0; } -- cgit v0.10.2 From f97f9e94f666213b3cc59a6cff70b318154f2b09 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 11 Jul 2017 14:56:49 -0700 Subject: f2fs: Don't clear SGID when inheriting ACLs commit c925dc162f770578ff4a65ec9b08270382dba9e6 upstream. This patch copies commit b7f8a09f80: "btrfs: Don't clear SGID when inheriting ACLs" written by Jan. Fixes: 073931017b49d9458aa351605b43a7e34598caef Signed-off-by: Jan Kara Reviewed-by: Chao Yu Reviewed-by: Jan Kara Signed-off-by: Jaegeuk Kim Signed-off-by: Greg Kroah-Hartman diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 6fe23af..55aa29c 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -211,7 +211,7 @@ static int __f2fs_set_acl(struct inode *inode, int type, switch (type) { case ACL_TYPE_ACCESS: name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; - if (acl) { + if (acl && !ipage) { error = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (error) return error; -- cgit v0.10.2 From 0fb615f9cad7966267cd1904766a1b3059336f76 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Mon, 3 Jul 2017 14:05:34 -0400 Subject: drm/ttm: Fix use-after-free in ttm_bo_clean_mm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8046e1955465e3f24e9154d0f2a2e0a8e3f8dccf upstream. We unref the man->move fence in ttm_bo_clean_mm() and then call ttm_bo_force_list_clean() which waits on it, except the refcount is now zero so a warning is generated (or worse): [149492.279301] refcount_t: increment on 0; use-after-free. [149492.279309] ------------[ cut here ]------------ [149492.279315] WARNING: CPU: 3 PID: 18726 at lib/refcount.c:150 refcount_inc+0x2b/0x30 [149492.279315] Modules linked in: vhost_net vhost tun x86_pkg_temp_thermal crc32_pclmul ghash_clmulni_intel efivarfs amdgpu( -) i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm [149492.279326] CPU: 3 PID: 18726 Comm: rmmod Not tainted 4.12.0-rc5-drm-next-4.13-ttmpatch+ #1 [149492.279326] Hardware name: Gigabyte Technology Co., Ltd. Z97X-UD3H-BK/Z97X-UD3H-BK-CF, BIOS F6 06/17/2014 [149492.279327] task: ffff8804ddfedcc0 task.stack: ffffc90008d20000 [149492.279329] RIP: 0010:refcount_inc+0x2b/0x30 [149492.279330] RSP: 0018:ffffc90008d23c30 EFLAGS: 00010286 [149492.279331] RAX: 000000000000002b RBX: 0000000000000170 RCX: 0000000000000000 [149492.279331] RDX: 0000000000000000 RSI: ffff88051ecccbe8 RDI: ffff88051ecccbe8 [149492.279332] RBP: ffffc90008d23c30 R08: 0000000000000001 R09: 00000000000003ee [149492.279333] R10: ffffc90008d23bb0 R11: 00000000000003ee R12: ffff88043aaac960 [149492.279333] R13: ffff8805005e28a8 R14: 0000000000000002 R15: ffff88050115e178 [149492.279334] FS: 00007fc540168700(0000) GS:ffff88051ecc0000(0000) knlGS:0000000000000000 [149492.279335] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [149492.279336] CR2: 00007fc3e8654140 CR3: 000000027ba77000 CR4: 00000000001426e0 [149492.279337] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [149492.279337] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [149492.279338] Call Trace: [149492.279345] ttm_bo_force_list_clean+0xb9/0x110 [ttm] [149492.279348] ttm_bo_clean_mm+0x7a/0xe0 [ttm] [149492.279375] amdgpu_ttm_fini+0xc9/0x1f0 [amdgpu] [149492.279392] amdgpu_bo_fini+0x12/0x40 [amdgpu] [149492.279415] gmc_v7_0_sw_fini+0x32/0x40 [amdgpu] [149492.279430] amdgpu_fini+0x2c9/0x490 [amdgpu] [149492.279445] amdgpu_device_fini+0x58/0x1b0 [amdgpu] [149492.279461] amdgpu_driver_unload_kms+0x4f/0xa0 [amdgpu] [149492.279470] drm_dev_unregister+0x3c/0xe0 [drm] [149492.279485] amdgpu_pci_remove+0x19/0x30 [amdgpu] [149492.279487] pci_device_remove+0x39/0xc0 [149492.279490] device_release_driver_internal+0x155/0x210 [149492.279491] driver_detach+0x38/0x70 [149492.279493] bus_remove_driver+0x4c/0xa0 [149492.279494] driver_unregister+0x2c/0x40 [149492.279496] pci_unregister_driver+0x21/0x90 [149492.279520] amdgpu_exit+0x15/0x406 [amdgpu] [149492.279523] SyS_delete_module+0x1a8/0x270 [149492.279525] ? exit_to_usermode_loop+0x92/0xa0 [149492.279528] entry_SYSCALL_64_fastpath+0x13/0x94 [149492.279529] RIP: 0033:0x7fc53fcb68e7 [149492.279529] RSP: 002b:00007ffcfbfaabb8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 [149492.279531] RAX: ffffffffffffffda RBX: 0000563117adb200 RCX: 00007fc53fcb68e7 [149492.279531] RDX: 000000000000000a RSI: 0000000000000800 RDI: 0000563117adb268 [149492.279532] RBP: 0000000000000003 R08: 0000000000000000 R09: 1999999999999999 [149492.279533] R10: 0000000000000883 R11: 0000000000000206 R12: 00007ffcfbfa9ba0 [149492.279533] R13: 0000000000000000 R14: 0000000000000000 R15: 0000563117adb200 [149492.279534] Code: 55 48 89 e5 e8 77 fe ff ff 84 c0 74 02 5d c3 80 3d 40 f2 a4 00 00 75 f5 48 c7 c7 20 3c ca 81 c6 05 30 f2 a4 00 01 e8 91 f0 d7 ff <0f> ff 5d c3 90 55 48 89 fe bf 01 00 00 00 48 89 e5 e8 9f fe ff [149492.279557] ---[ end trace 2d4e0ffcb66a1016 ]--- Unref the fence *after* waiting for it. v2: Set man->move to NULL after dropping the last ref (Christian König) Fixes: aff98ba1fdb8 (drm/ttm: wait for eviction in ttm_bo_force_list_clean) Signed-off-by: John Brooks Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 35cc16f..d09276e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1343,7 +1343,6 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) mem_type); return ret; } - fence_put(man->move); man->use_type = false; man->has_type = false; @@ -1355,6 +1354,9 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) ret = (*man->func->takedown)(man); } + fence_put(man->move); + man->move = NULL; + return ret; } EXPORT_SYMBOL(ttm_bo_clean_mm); -- cgit v0.10.2 From fee760fc6c79998efc48bd06afeec31824dfb2d4 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 10 Jan 2017 21:30:21 +0300 Subject: ovl: drop CAP_SYS_RESOURCE from saved mounter's credentials commit 51f8f3c4e22535933ef9aecc00e9a6069e051b57 upstream. If overlay was mounted by root then quota set for upper layer does not work because overlay now always use mounter's credentials for operations. Also overlay might deplete reserved space and inodes in ext4. This patch drops capability SYS_RESOURCE from saved credentials. This affects creation new files, whiteouts, and copy-up operations. Signed-off-by: Konstantin Khlebnikov Fixes: 1175b6b8d963 ("ovl: do operations on underlying file system in mounter's context") Cc: Vivek Goyal Signed-off-by: Miklos Szeredi Cc: Amir Goldstein Signed-off-by: Greg Kroah-Hartman diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 0e10085..2a01489 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1146,6 +1146,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) unsigned int stacklen = 0; unsigned int i; bool remote = false; + struct cred *cred; int err; err = -ENOMEM; @@ -1309,10 +1310,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) else sb->s_d_op = &ovl_dentry_operations; - ufs->creator_cred = prepare_creds(); - if (!ufs->creator_cred) + ufs->creator_cred = cred = prepare_creds(); + if (!cred) goto out_put_lower_mnt; + /* Never override disk quota limits or use reserved space */ + cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); + err = -ENOMEM; oe = ovl_alloc_entry(numlower); if (!oe) -- cgit v0.10.2 From e91a55790ddfbda7f9f72963e561d9c738f14a52 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 19 Jun 2017 09:10:32 -0600 Subject: vfio: Fix group release deadlock commit 811642d8d8a82c0cce8dc2debfdaf23c5a144839 upstream. If vfio_iommu_group_notifier() acquires a group reference and that reference becomes the last reference to the group, then vfio_group_put introduces a deadlock code path where we're trying to unregister from the iommu notifier chain from within a callout of that chain. Use a work_struct to release this reference asynchronously. Signed-off-by: Alex Williamson Reviewed-by: Eric Auger Tested-by: Eric Auger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index d1d70e0..8e8b73b 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -419,6 +419,34 @@ static void vfio_group_put(struct vfio_group *group) kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); } +struct vfio_group_put_work { + struct work_struct work; + struct vfio_group *group; +}; + +static void vfio_group_put_bg(struct work_struct *work) +{ + struct vfio_group_put_work *do_work; + + do_work = container_of(work, struct vfio_group_put_work, work); + + vfio_group_put(do_work->group); + kfree(do_work); +} + +static void vfio_group_schedule_put(struct vfio_group *group) +{ + struct vfio_group_put_work *do_work; + + do_work = kmalloc(sizeof(*do_work), GFP_KERNEL); + if (WARN_ON(!do_work)) + return; + + INIT_WORK(&do_work->work, vfio_group_put_bg); + do_work->group = group; + schedule_work(&do_work->work); +} + /* Assume group_lock or group reference is held */ static void vfio_group_get(struct vfio_group *group) { @@ -743,7 +771,14 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, break; } - vfio_group_put(group); + /* + * If we're the last reference to the group, the group will be + * released, which includes unregistering the iommu group notifier. + * We hold a read-lock on that notifier list, unregistering needs + * a write-lock... deadlock. Release our reference asynchronously + * to avoid that situation. + */ + vfio_group_schedule_put(group); return NOTIFY_OK; } -- cgit v0.10.2 From 8f9dec0c2dbb99aa36fa2d242828d853abde8eb0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 28 Jun 2017 13:50:05 -0600 Subject: vfio: New external user group/file match commit 5d6dee80a1e94cc284d03e06d930e60e8d3ecf7d upstream. At the point where the kvm-vfio pseudo device wants to release its vfio group reference, we can't always acquire a new reference to make that happen. The group can be in a state where we wouldn't allow a new reference to be added. This new helper function allows a caller to match a file to a group to facilitate this. Given a file and group, report if they match. Thus the caller needs to already have a group reference to match to the file. This allows the deletion of a group without acquiring a new reference. Signed-off-by: Alex Williamson Reviewed-by: Eric Auger Reviewed-by: Paolo Bonzini Tested-by: Eric Auger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 8e8b73b..881fc3a 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1751,6 +1751,15 @@ void vfio_group_put_external_user(struct vfio_group *group) } EXPORT_SYMBOL_GPL(vfio_group_put_external_user); +bool vfio_external_group_match_file(struct vfio_group *test_group, + struct file *filep) +{ + struct vfio_group *group = filep->private_data; + + return (filep->f_op == &vfio_group_fops) && (group == test_group); +} +EXPORT_SYMBOL_GPL(vfio_external_group_match_file); + int vfio_external_user_iommu_id(struct vfio_group *group) { return iommu_group_id(group->iommu_group); diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 0ecae0b..ed46675 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -88,6 +88,8 @@ extern void vfio_unregister_iommu_driver( */ extern struct vfio_group *vfio_group_get_external_user(struct file *filep); extern void vfio_group_put_external_user(struct vfio_group *group); +extern bool vfio_external_group_match_file(struct vfio_group *group, + struct file *filep); extern int vfio_external_user_iommu_id(struct vfio_group *group); extern long vfio_external_check_extension(struct vfio_group *group, unsigned long arg); diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 1dd087d..111e09c 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -47,6 +47,22 @@ static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep) return vfio_group; } +static bool kvm_vfio_external_group_match_file(struct vfio_group *group, + struct file *filep) +{ + bool ret, (*fn)(struct vfio_group *, struct file *); + + fn = symbol_get(vfio_external_group_match_file); + if (!fn) + return false; + + ret = fn(group, filep); + + symbol_put(vfio_external_group_match_file); + + return ret; +} + static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group) { void (*fn)(struct vfio_group *); @@ -171,18 +187,13 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) if (!f.file) return -EBADF; - vfio_group = kvm_vfio_group_get_external_user(f.file); - fdput(f); - - if (IS_ERR(vfio_group)) - return PTR_ERR(vfio_group); - ret = -ENOENT; mutex_lock(&kv->lock); list_for_each_entry(kvg, &kv->group_list, node) { - if (kvg->vfio_group != vfio_group) + if (!kvm_vfio_external_group_match_file(kvg->vfio_group, + f.file)) continue; list_del(&kvg->node); @@ -196,7 +207,7 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) mutex_unlock(&kv->lock); - kvm_vfio_group_put_external_user(vfio_group); + fdput(f); kvm_vfio_update_coherency(dev); -- cgit v0.10.2 From d17cc7b7a7522c908636b32beee7537f64e3c043 Mon Sep 17 00:00:00 2001 From: Marta Rybczynska Date: Tue, 6 Jun 2017 13:27:21 +0200 Subject: nvme-rdma: remove race conditions from IB signalling commit 5e599d73c1c1816af07f94ddba879499aa39b43c upstream. This patch improves the way the RDMA IB signalling is done by using atomic operations for the signalling variable. This avoids race conditions on sig_count. The signalling interval changes slightly and is now the largest power of two not larger than queue depth / 2. ilog() usage idea by Bart Van Assche. Signed-off-by: Marta Rybczynska Reviewed-by: Sagi Grimberg Signed-off-by: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 3222f3e..286fda4 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -88,7 +88,7 @@ enum nvme_rdma_queue_flags { struct nvme_rdma_queue { struct nvme_rdma_qe *rsp_ring; - u8 sig_count; + atomic_t sig_count; int queue_size; size_t cmnd_capsule_len; struct nvme_rdma_ctrl *ctrl; @@ -555,6 +555,7 @@ static int nvme_rdma_init_queue(struct nvme_rdma_ctrl *ctrl, queue->cmnd_capsule_len = sizeof(struct nvme_command); queue->queue_size = queue_size; + atomic_set(&queue->sig_count, 0); queue->cm_id = rdma_create_id(&init_net, nvme_rdma_cm_handler, queue, RDMA_PS_TCP, IB_QPT_RC); @@ -1011,17 +1012,16 @@ static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc) nvme_rdma_wr_error(cq, wc, "SEND"); } -static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue) +/* + * We want to signal completion at least every queue depth/2. This returns the + * largest power of two that is not above half of (queue size + 1) to optimize + * (avoid divisions). + */ +static inline bool nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue) { - int sig_limit; + int limit = 1 << ilog2((queue->queue_size + 1) / 2); - /* - * We signal completion every queue depth/2 and also handle the - * degenerated case of a device with queue_depth=1, where we - * would need to signal every message. - */ - sig_limit = max(queue->queue_size / 2, 1); - return (++queue->sig_count % sig_limit) == 0; + return (atomic_inc_return(&queue->sig_count) & (limit - 1)) == 0; } static int nvme_rdma_post_send(struct nvme_rdma_queue *queue, -- cgit v0.10.2 From 198bd494cebfad07c251d9fd26279393c81d8dec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Jul 2017 10:35:57 +0300 Subject: ftrace: Fix uninitialized variable in match_records() commit 2e028c4fe12907f226b8221815f16c2486ad3aa7 upstream. My static checker complains that if "func" is NULL then "clear_filter" is uninitialized. This seems like it could be true, although it's possible something subtle is happening that I haven't seen. kernel/trace/ftrace.c:3844 match_records() error: uninitialized symbol 'clear_filter'. Link: http://lkml.kernel.org/r/20170712073556.h6tkpjcdzjaozozs@mwanda Fixes: f0a3b154bd7 ("ftrace: Clarify code for mod command") Signed-off-by: Dan Carpenter Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 221eb59..4f7ea84 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3590,7 +3590,7 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod) int exclude_mod = 0; int found = 0; int ret; - int clear_filter; + int clear_filter = 0; if (func) { func_g.type = filter_parse_regex(func, len, &func_g.search, -- cgit v0.10.2 From dd2f83263dd8ecc4e325fe5f1aed5a930edbe643 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 31 May 2017 16:19:47 +0100 Subject: MIPS: Fix mips_atomic_set() retry condition commit 2ec420b26f7b6ff332393f0bb5a7d245f7ad87f0 upstream. The inline asm retry check in the MIPS_ATOMIC_SET operation of the sysmips system call has been backwards since commit f1e39a4a616c ("MIPS: Rewrite sysmips(MIPS_ATOMIC_SET, ...) in C with inline assembler") merged in v2.6.32, resulting in the non R10000_LLSC_WAR case retrying until the operation was inatomic, before returning the new value that was probably just written multiple times instead of the old value. Invert the branch condition to fix that particular issue. Fixes: f1e39a4a616c ("MIPS: Rewrite sysmips(MIPS_ATOMIC_SET, ...) in C with inline assembler") Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16148/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 53a7ef9..876c5a5 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -141,7 +141,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) "1: ll %[old], (%[addr]) \n" " move %[tmp], %[new] \n" "2: sc %[tmp], (%[addr]) \n" - " bnez %[tmp], 4f \n" + " beqz %[tmp], 4f \n" "3: \n" " .insn \n" " .subsection 2 \n" -- cgit v0.10.2 From f39f3b5d8260de549887f127ac5e99f0931b4990 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 31 May 2017 16:19:49 +0100 Subject: MIPS: Fix mips_atomic_set() with EVA commit 4915e1b043d6286928207b1f6968197b50407294 upstream. EVA linked loads (LLE) and conditional stores (SCE) should be used on EVA kernels for the MIPS_ATOMIC_SET operation of the sysmips system call, or else the atomic set will apply to the kernel view of the virtual address space (potentially unmapped on EVA kernels) rather than the user view (TLB mapped). Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16151/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 876c5a5..8c222d3 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -138,9 +139,11 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) __asm__ __volatile__ ( " .set "MIPS_ISA_ARCH_LEVEL" \n" " li %[err], 0 \n" - "1: ll %[old], (%[addr]) \n" + "1: \n" + user_ll("%[old]", "(%[addr])") " move %[tmp], %[new] \n" - "2: sc %[tmp], (%[addr]) \n" + "2: \n" + user_sc("%[tmp]", "(%[addr])") " beqz %[tmp], 4f \n" "3: \n" " .insn \n" -- cgit v0.10.2 From 02131aea6bd4d7a1414333160124b6a078b262fe Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 29 Jun 2017 10:12:34 +0100 Subject: MIPS: Negate error syscall return in trace commit 4f32a39d49b25eaa66d2420f1f03d371ea4cd906 upstream. The sys_exit trace event takes a single return value for the system call, which MIPS passes the value of the $v0 (result) register, however MIPS returns positive error codes in $v0 with $a3 specifying that $v0 contains an error code. As a result erroring system calls are traced returning positive error numbers that can't always be distinguished from success. Use regs_return_value() to negate the error code if $a3 is set. Fixes: 1d7bf993e073 ("MIPS: ftrace: Add support for syscall tracepoints.") Signed-off-by: James Hogan Cc: Steven Rostedt Cc: Ingo Molnar Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16651/ Acked-by: Steven Rostedt (VMware) Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index bf83dc1..3de0260 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -924,7 +924,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(regs); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_exit(regs, regs->regs[2]); + trace_sys_exit(regs, regs_return_value(regs)); if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); -- cgit v0.10.2 From ec469b5e2aafdcedbc80d9a7a8a4fa8632e584e3 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 16 Jun 2017 16:21:44 +0200 Subject: ubifs: Don't leak kernel memory to the MTD commit 4acadda74ff8b949c448c0282765ae747e088c87 upstream. When UBIFS prepares data structures which will be written to the MTD it ensues that their lengths are multiple of 8. Since it uses kmalloc() the padded bytes are left uninitialized and we leak a few bytes of kernel memory to the MTD. To make sure that all bytes are initialized, let's switch to kzalloc(). Kzalloc() is fine in this case because the buffers are not huge and in the IO path the performance bottleneck is anyway the MTD. Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") Signed-off-by: Richard Weinberger Reviewed-by: Boris Brezillon Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 91bc76dc..7d764e3 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -576,7 +576,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, /* Make sure to also account for extended attributes */ len += host_ui->data_len; - dent = kmalloc(len, GFP_NOFS); + dent = kzalloc(len, GFP_NOFS); if (!dent) return -ENOMEM; @@ -952,7 +952,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, if (twoparents) len += plen; - dent1 = kmalloc(len, GFP_NOFS); + dent1 = kzalloc(len, GFP_NOFS); if (!dent1) return -ENOMEM; @@ -1102,7 +1102,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8); if (move) len += plen; - dent = kmalloc(len, GFP_NOFS); + dent = kzalloc(len, GFP_NOFS); if (!dent) return -ENOMEM; @@ -1466,7 +1466,7 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, hlen = host_ui->data_len + UBIFS_INO_NODE_SZ; len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8); - xent = kmalloc(len, GFP_NOFS); + xent = kzalloc(len, GFP_NOFS); if (!xent) return -ENOMEM; @@ -1573,7 +1573,7 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, aligned_len1 = ALIGN(len1, 8); aligned_len = aligned_len1 + ALIGN(len2, 8); - ino = kmalloc(aligned_len, GFP_NOFS); + ino = kzalloc(aligned_len, GFP_NOFS); if (!ino) return -ENOMEM; -- cgit v0.10.2 From b2966b109b1a2c23e626ad35fc03d4a52efd1aa4 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Wed, 12 Jul 2017 11:09:09 +0800 Subject: ACPI / EC: Drop EC noirq hooks to fix a regression commit 662591461c4b9a1e3b9b159dbf37648a585ebaae upstream. According to bug reports, although the busy polling mode can make noirq stages execute faster, it causes abnormal fan blowing up after system resume (see the first link below for a video demonstration) on Lenovo ThinkPad X1 Carbon - the 5th Generation. The problem can be fixed by upgrading the EC firmware on that machine. However, many reporters confirm that the problem can be fixed by stopping busy polling during suspend/resume and for some of them upgrading the EC firmware is not an option. For this reason, drop the noirq stage hooks from the EC driver to fix the regression. Fixes: c3a696b6e8f8 (ACPI / EC: Use busy polling mode when GPE is not enabled) Link: https://youtu.be/9NQ9x-Jm99Q Link: https://bugzilla.kernel.org/show_bug.cgi?id=196129 Reported-by: Andreas Lindhe Tested-by: Gjorgji Jankovski Tested-by: Damjan Georgievski Tested-by: Fernando Chaves Tested-by: Tomislav Ivek Tested-by: Denis P. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 22ca892..3f01f65 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1865,24 +1865,6 @@ error: } #ifdef CONFIG_PM_SLEEP -static int acpi_ec_suspend_noirq(struct device *dev) -{ - struct acpi_ec *ec = - acpi_driver_data(to_acpi_device(dev)); - - acpi_ec_enter_noirq(ec); - return 0; -} - -static int acpi_ec_resume_noirq(struct device *dev) -{ - struct acpi_ec *ec = - acpi_driver_data(to_acpi_device(dev)); - - acpi_ec_leave_noirq(ec); - return 0; -} - static int acpi_ec_suspend(struct device *dev) { struct acpi_ec *ec = @@ -1904,7 +1886,6 @@ static int acpi_ec_resume(struct device *dev) #endif static const struct dev_pm_ops acpi_ec_pm = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) SET_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend, acpi_ec_resume) }; -- cgit v0.10.2 From 456a997498cb5217a61fba0f1929be7d182b5338 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Wed, 12 Jul 2017 11:09:17 +0800 Subject: Revert "ACPI / EC: Enable event freeze mode..." to fix a regression commit 9c40f956ce9b331493347d1b3cb7e384f7dc0581 upstream. On Lenovo ThinkPad X1 Carbon - the 5th Generation, enabling an earlier EC event freezing timing causes acpitz-virtual-0 to report a stuck 48C temparature. And with EC firmware revisioned as 1.14, without reverting back to old EC event freezing timing, the fan still blows up after a system resume. This reverts the culprit change so that the regression can be fixed without upgrading the EC firmware. Fixes: d30283057ecd (ACPI / EC: Enable event freeze mode to improve event handling) Link: https://bugzilla.kernel.org/show_bug.cgi?id=191181#c168 Tested-by: Damjan Georgievski Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3f01f65..79152db 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -147,7 +147,7 @@ static unsigned int ec_storm_threshold __read_mostly = 8; module_param(ec_storm_threshold, uint, 0644); MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); -static bool ec_freeze_events __read_mostly = true; +static bool ec_freeze_events __read_mostly = false; module_param(ec_freeze_events, bool, 0644); MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); -- cgit v0.10.2 From 036d59f40ac94964a1bbc8959f78f34efac71fd5 Mon Sep 17 00:00:00 2001 From: Seunghun Han Date: Tue, 18 Jul 2017 20:03:51 +0900 Subject: x86/acpi: Prevent out of bound access caused by broken ACPI tables commit dad5ab0db8deac535d03e3fe3d8f2892173fa6a4 upstream. The bus_irq argument of mp_override_legacy_irq() is used as the index into the isa_irq_to_gsi[] array. The bus_irq argument originates from ACPI_MADT_TYPE_IO_APIC and ACPI_MADT_TYPE_INTERRUPT items in the ACPI tables, but is nowhere sanity checked. That allows broken or malicious ACPI tables to overwrite memory, which might cause malfunction, panic or arbitrary code execution. Add a sanity check and emit a warning when that triggers. [ tglx: Added warning and rewrote changelog ] Signed-off-by: Seunghun Han Signed-off-by: Thomas Gleixner Cc: security@kernel.org Cc: "Rafael J. Wysocki" Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 931ced8..d3e0d04 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -338,6 +338,14 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, struct mpc_intsrc mp_irq; /* + * Check bus_irq boundary. + */ + if (bus_irq >= NR_IRQS_LEGACY) { + pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq); + return; + } + + /* * Convert 'gsi' to 'ioapic.pin'. */ ioapic = mp_find_ioapic(gsi); -- cgit v0.10.2 From c69280e9018eaea65ab18cc9a231d913479a5ee3 Mon Sep 17 00:00:00 2001 From: Seunghun Han Date: Tue, 18 Jul 2017 18:20:44 +0900 Subject: x86/ioapic: Pass the correct data to unmask_ioapic_irq() commit e708e35ba6d89ff785b225cd07dcccab04fa954a upstream. One of the rarely executed code pathes in check_timer() calls unmask_ioapic_irq() passing irq_get_chip_data(0) as argument. That's wrong as unmask_ioapic_irq() expects a pointer to the irq data of interrupt 0. irq_get_chip_data(0) returns NULL, so the following dereference in unmask_ioapic_irq() causes a kernel panic. The issue went unnoticed in the first place because irq_get_chip_data() returns a void pointer so the compiler cannot do a type check on the argument. The code path was added for machines with broken configuration, but it seems that those machines are either not running current kernels or simply do not longer exist. Hand in irq_get_irq_data(0) as argument which provides the correct data. [ tglx: Rewrote changelog ] Fixes: 4467715a44cc ("x86/irq: Move irq_cfg.irq_2_pin into io_apic.c") Signed-off-by: Seunghun Han Signed-off-by: Thomas Gleixner Link: http://lkml.kernel.org/r/1500369644-45767-1-git-send-email-kkamagui@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7249f15..cf89928 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2116,7 +2116,7 @@ static inline void __init check_timer(void) int idx; idx = find_irq_entry(apic1, pin1, mp_INT); if (idx != -1 && irq_trigger(idx)) - unmask_ioapic_irq(irq_get_chip_data(0)); + unmask_ioapic_irq(irq_get_irq_data(0)); } irq_domain_deactivate_irq(irq_data); irq_domain_activate_irq(irq_data); -- cgit v0.10.2 From a9db2f4f887c2cc9557fc2ae553ea24ecc65c6e0 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 8 Jul 2017 23:24:44 +0100 Subject: MIPS: Fix MIPS I ISA /proc/cpuinfo reporting commit e5f5a5b06e51a36f6ddf31a4a485358263953a3d upstream. Correct a commit 515a6393dbac ("MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo") regression that caused MIPS I systems to show no ISA levels supported in /proc/cpuinfo, e.g.: system type : Digital DECstation 2100/3100 machine : Unknown processor : 0 cpu model : R3000 V2.0 FPU V2.0 BogoMIPS : 10.69 wait instruction : no microsecond timers : no tlb_entries : 64 extra interrupt vector : no hardware watchpoint : no isa : ASEs implemented : shadow register sets : 1 kscratch registers : 0 package : 0 core : 0 VCED exceptions : not available VCEI exceptions : not available and similarly exclude `mips1' from the ISA list for any processors below MIPSr1. This is because the condition to show `mips1' on has been made `cpu_has_mips_r1' rather than newly-introduced `cpu_has_mips_1'. Use the correct condition then. Fixes: 515a6393dbac ("MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo") Signed-off-by: Maciej W. Rozycki Reviewed-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16758/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 4eff2ae..4c01ee5 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -83,7 +83,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) } seq_printf(m, "isa\t\t\t:"); - if (cpu_has_mips_r1) + if (cpu_has_mips_1) seq_printf(m, " mips1"); if (cpu_has_mips_2) seq_printf(m, "%s", " mips2"); -- cgit v0.10.2 From f8c331cbc937d849d93dc9f3f7cdc31d5fbac58e Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 31 May 2017 16:19:48 +0100 Subject: MIPS: Save static registers before sysmips commit 49955d84cd9ccdca5a16a495e448e1a06fad9e49 upstream. The MIPS sysmips system call handler may return directly from the MIPS_ATOMIC_SET case (mips_atomic_set()) to syscall_exit. This path restores the static (callee saved) registers, however they won't have been saved on entry to the system call. Use the save_static_function() macro to create a __sys_sysmips wrapper function which saves the static registers before calling sys_sysmips, so that the correct static register state is restored by syscall_exit. Fixes: f1e39a4a616c ("MIPS: Rewrite sysmips(MIPS_ATOMIC_SET, ...) in C with inline assembler") Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16149/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index c29d397..e6be1f6 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -371,7 +371,7 @@ EXPORT(sys_call_table) PTR sys_writev PTR sys_cacheflush PTR sys_cachectl - PTR sys_sysmips + PTR __sys_sysmips PTR sys_ni_syscall /* 4150 */ PTR sys_getsid PTR sys_fdatasync diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 0687f96..aa27daf 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -311,7 +311,7 @@ EXPORT(sys_call_table) PTR sys_sched_getaffinity PTR sys_cacheflush PTR sys_cachectl - PTR sys_sysmips + PTR __sys_sysmips PTR sys_io_setup /* 5200 */ PTR sys_io_destroy PTR sys_io_getevents diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 0331ba3..37f608f 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -302,7 +302,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_sched_getaffinity PTR sys_cacheflush PTR sys_cachectl - PTR sys_sysmips + PTR __sys_sysmips PTR compat_sys_io_setup /* 6200 */ PTR sys_io_destroy PTR compat_sys_io_getevents diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 5a47042..7913a5c 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -371,7 +371,7 @@ EXPORT(sys32_call_table) PTR compat_sys_writev PTR sys_cacheflush PTR sys_cachectl - PTR sys_sysmips + PTR __sys_sysmips PTR sys_ni_syscall /* 4150 */ PTR sys_getsid PTR sys_fdatasync diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 8c222d3..4234b2d 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -202,6 +202,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) unreachable(); } +/* + * mips_atomic_set() normally returns directly via syscall_exit potentially + * clobbering static registers, so be sure to preserve them. + */ +save_static_function(sys_sysmips); + SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2) { switch (cmd) { -- cgit v0.10.2 From 434c9f2e3b4667859a705b48d53f23f5f629ecf1 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:06:19 +0100 Subject: MIPS: Actually decode JALX in `__compute_return_epc_for_insn' commit a9db101b735a9d49295326ae41f610f6da62b08c upstream. Complement commit fb6883e5809c ("MIPS: microMIPS: Support handling of delay slots.") and actually decode the regular MIPS JALX major instruction opcode, the handling of which has been added with the said commit for EPC calculation in `__compute_return_epc_for_insn'. Fixes: fb6883e5809c ("MIPS: microMIPS: Support handling of delay slots.") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16394/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index c86b66b..62806db 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -556,6 +556,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* * These are unconditional and in j_format. */ + case jalx_op: case jal_op: regs->regs[31] = regs->cp0_epc + 8; case j_op: -- cgit v0.10.2 From 040078ad0fe82beff150dfd3b060a2ba7b47ea37 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:07:34 +0100 Subject: MIPS: Fix unaligned PC interpretation in `compute_return_epc' commit 11a3799dbeb620bf0400b1fda5cc2c6bea55f20a upstream. Fix a regression introduced with commit fb6883e5809c ("MIPS: microMIPS: Support handling of delay slots.") and defer to `__compute_return_epc' if the ISA bit is set in EPC with non-MIPS16, non-microMIPS hardware, which will then arrange for a SIGBUS due to an unaligned instruction reference. Returning EPC here is never correct as the API defines this function's result to be either a negative error code on failure or one of 0 and BRANCH_LIKELY_TAKEN on success. Fixes: fb6883e5809c ("MIPS: microMIPS: Support handling of delay slots.") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16395/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index de781cf..da80878 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -74,10 +74,7 @@ static inline int compute_return_epc(struct pt_regs *regs) return __microMIPS_compute_return_epc(regs); if (cpu_has_mips16) return __MIPS16e_compute_return_epc(regs); - return regs->cp0_epc; - } - - if (!delay_slot(regs)) { + } else if (!delay_slot(regs)) { regs->cp0_epc += 4; return 0; } -- cgit v0.10.2 From d79354cc1bc912d623765781d570ddc398d792db Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:05:08 +0100 Subject: MIPS: math-emu: Prevent wrong ISA mode instruction emulation commit 13769ebad0c42738831787e27c7c7f982e7da579 upstream. Terminate FPU emulation immediately whenever an ISA mode switch has been observed. This is so that we do not interpret machine code in the wrong mode, for example when a regular MIPS FPU instruction has been placed in a delay slot of a jump that switches into the MIPS16 mode, as with the following code (taken from a GCC test suite case): 00400650 : 400650: 3c020100 lui v0,0x100 400654: 03e00008 jr ra 400658: 44c2f800 ctc1 v0,c1_fcsr 40065c: 00000000 nop [...] 004012d0 <__libc_csu_init>: 4012d0: f000 6a02 li v0,2 4012d4: f150 0b1c la v1,3f9430 <_DYNAMIC-0x6df0> 4012d8: f400 3240 sll v0,16 4012dc: e269 addu v0,v1 4012de: 659a move gp,v0 4012e0: f00c 64f6 save a0-a2,48,ra,s0-s1 4012e4: 673c move s1,gp 4012e6: f010 9978 lw v1,-32744(s1) 4012ea: d204 sw v0,16(sp) 4012ec: eb40 jalr v1 4012ee: 653b move t9,v1 4012f0: f010 997c lw v1,-32740(s1) 4012f4: f030 9920 lw s1,-32736(s1) 4012f8: e32f subu v1,s1 4012fa: 326b sra v0,v1,2 4012fc: d206 sw v0,24(sp) 4012fe: 220c beqz v0,401318 <__libc_csu_init+0x48> 401300: 6800 li s0,0 401302: 99e0 lw a3,0(s1) 401304: 4801 addiu s0,1 401306: 960e lw a2,56(sp) 401308: 4904 addiu s1,4 40130a: 950d lw a1,52(sp) 40130c: 940c lw a0,48(sp) 40130e: ef40 jalr a3 401310: 653f move t9,a3 401312: 9206 lw v0,24(sp) 401314: ea0a cmp v0,s0 401316: 61f5 btnez 401302 <__libc_csu_init+0x32> 401318: 6476 restore 48,ra,s0-s1 40131a: e8a0 jrc ra Here `set_fast_math' is called from `40130e' (`40130f' with the ISA bit) and emulation triggers for the CTC1 instruction. As it is in a jump delay slot emulation continues from `401312' (`401313' with the ISA bit). However we have no path to handle MIPS16 FPU code emulation, because there are no MIPS16 FPU instructions. So the default emulation path is taken, interpreting a 32-bit word fetched by `get_user' from `401313' as a regular MIPS instruction, which is: 401313: f5ea0a92 sdc1 $f10,2706(t7) This makes the FPU emulator proceed with the supposed SDC1 instruction and consequently makes the program considered here terminate with SIGSEGV. A similar although less severe issue exists with pure-microMIPS processors in the case where similarly an FPU instruction is emulated in a delay slot of a register jump that (incorrectly) switches into the regular MIPS mode. A subsequent instruction fetch from the jump's target is supposed to cause an Address Error exception, however instead we proceed with regular MIPS FPU emulation. For simplicity then, always terminate the emulation loop whenever a mode change is detected, denoted by an ISA mode bit flip. As from commit 377cb1b6c16a ("MIPS: Disable MIPS16/microMIPS crap for platforms not supporting these ASEs.") the result of `get_isa16_mode' can be hardcoded to 0, so we need to examine the ISA mode bit by hand. This complements commit 102cedc32a6e ("MIPS: microMIPS: Floating point support.") which added JALX decoding to FPU emulation. Fixes: 102cedc32a6e ("MIPS: microMIPS: Floating point support.") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16393/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index f8b7bf8..e9385bc 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -2522,6 +2522,35 @@ dcopuop: return 0; } +/* + * Emulate FPU instructions. + * + * If we use FPU hardware, then we have been typically called to handle + * an unimplemented operation, such as where an operand is a NaN or + * denormalized. In that case exit the emulation loop after a single + * iteration so as to let hardware execute any subsequent instructions. + * + * If we have no FPU hardware or it has been disabled, then continue + * emulating floating-point instructions until one of these conditions + * has occurred: + * + * - a non-FPU instruction has been encountered, + * + * - an attempt to emulate has ended with a signal, + * + * - the ISA mode has been switched. + * + * We need to terminate the emulation loop if we got switched to the + * MIPS16 mode, whether supported or not, so that we do not attempt + * to emulate a MIPS16 instruction as a regular MIPS FPU instruction. + * Similarly if we got switched to the microMIPS mode and only the + * regular MIPS mode is supported, so that we do not attempt to emulate + * a microMIPS instruction as a regular MIPS FPU instruction. Or if + * we got switched to the regular MIPS mode and only the microMIPS mode + * is supported, so that we do not attempt to emulate a regular MIPS + * instruction that should cause an Address Error exception instead. + * For simplicity we always terminate upon an ISA mode switch. + */ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr) { @@ -2607,6 +2636,15 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; if (sig) break; + /* + * We have to check for the ISA bit explicitly here, + * because `get_isa16_mode' may return 0 if support + * for code compression has been globally disabled, + * or otherwise we may produce the wrong signal or + * even proceed successfully where we must not. + */ + if ((xcp->cp0_epc ^ prevepc) & 0x1) + break; cond_resched(); } while (xcp->cp0_epc > prevepc); -- cgit v0.10.2 From 86dd4aa3079058342b99289977cc06c681fb6a2d Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:08:29 +0100 Subject: MIPS: Send SIGILL for BPOSGE32 in `__compute_return_epc_for_insn' commit 7b82c1058ac1f8f8b9f2b8786b1f710a57a870a8 upstream. Fix commit e50c0a8fa60d ("Support the MIPS32 / MIPS64 DSP ASE.") and send SIGILL rather than SIGBUS whenever an unimplemented BPOSGE32 DSP ASE instruction has been encountered in `__compute_return_epc_for_insn' as our Reserved Instruction exception handler would in response to an attempt to actually execute the instruction. Sending SIGBUS only makes sense for the unaligned PC case, since moved to `__compute_return_epc'. Adjust function documentation accordingly, correct formatting and use `pr_info' rather than `printk' as the other exit path already does. Fixes: e50c0a8fa60d ("Support the MIPS32 / MIPS64 DSP ASE.") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16396/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 62806db..4e7e3b9 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -399,7 +399,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs) * * @regs: Pointer to pt_regs * @insn: branch instruction to decode - * @returns: -EFAULT on error and forces SIGBUS, and on success + * @returns: -EFAULT on error and forces SIGILL, and on success * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after * evaluating the branch. * @@ -832,8 +832,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, return ret; sigill_dsp: - printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm); - force_sig(SIGBUS, current); + pr_info("%s: DSP branch but not DSP ASE - sending SIGILL.\n", + current->comm); + force_sig(SIGILL, current); return -EFAULT; sigill_r6: pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n", -- cgit v0.10.2 From 99ce76144dee8dfbedeccfe7fed85f61d31c6379 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:09:23 +0100 Subject: MIPS: Rename `sigill_r6' to `sigill_r2r6' in `__compute_return_epc_for_insn' commit 1f4edde422961397cf4470b347958c13c6a740bb upstream. Use the more accurate `sigill_r2r6' name for the label used in the case of sending SIGILL in the absence of the instruction emulator for an earlier ISA level instruction that has been removed as from the R6 ISA, so that the `sigill_r6' name is freed for the situation where an R6 instruction is not supposed to be interpreted, because the executing processor does not support the R6 ISA. Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16397/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 4e7e3b9..a1cf462 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -431,7 +431,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* Fall through */ case jr_op: if (NO_R6EMU && insn.r_format.func == jr_op) - goto sigill_r6; + goto sigill_r2r6; regs->cp0_epc = regs->regs[insn.r_format.rs]; break; } @@ -446,7 +446,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, switch (insn.i_format.rt) { case bltzl_op: if (NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case bltz_op: if ((long)regs->regs[insn.i_format.rs] < 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); @@ -459,7 +459,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case bgezl_op: if (NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case bgez_op: if ((long)regs->regs[insn.i_format.rs] >= 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); @@ -574,7 +574,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, */ case beql_op: if (NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case beq_op: if (regs->regs[insn.i_format.rs] == regs->regs[insn.i_format.rt]) { @@ -588,7 +588,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case bnel_op: if (NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case bne_op: if (regs->regs[insn.i_format.rs] != regs->regs[insn.i_format.rt]) { @@ -602,7 +602,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case blezl_op: /* not really i_format */ if (!insn.i_format.rt && NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case blez_op: /* * Compact branches for R6 for the @@ -637,7 +637,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case bgtzl_op: if (!insn.i_format.rt && NO_R6EMU) - goto sigill_r6; + goto sigill_r2r6; case bgtz_op: /* * Compact branches for R6 for the @@ -836,7 +836,7 @@ sigill_dsp: current->comm); force_sig(SIGILL, current); return -EFAULT; -sigill_r6: +sigill_r2r6: pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n", current->comm); force_sig(SIGILL, current); -- cgit v0.10.2 From d4bd6a1df2c816b7027f9cf1a900ae52f528f300 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:12:53 +0100 Subject: MIPS: Send SIGILL for linked branches in `__compute_return_epc_for_insn' commit fef40be6da856afead4177aaa9d869a66fb3381f upstream. Fix commit 319824eabc3f ("MIPS: kernel: branch: Do not emulate the branch likelies on MIPS R6") and also send SIGILL rather than returning -SIGILL for BLTZAL, BLTZALL, BGEZAL and BGEZALL instruction encodings no longer supported in R6, except where emulated. Returning -SIGILL is never correct as the API defines this function's result upon error to be -EFAULT and a signal actually issued. Fixes: 319824eabc3f ("MIPS: kernel: branch: Do not emulate the branch likelies on MIPS R6") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16398/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index a1cf462..ddf0f02 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -473,10 +473,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case bltzal_op: case bltzall_op: if (NO_R6EMU && (insn.i_format.rs || - insn.i_format.rt == bltzall_op)) { - ret = -SIGILL; - break; - } + insn.i_format.rt == bltzall_op)) + goto sigill_r2r6; regs->regs[31] = epc + 8; /* * OK we are here either because we hit a NAL @@ -507,10 +505,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case bgezal_op: case bgezall_op: if (NO_R6EMU && (insn.i_format.rs || - insn.i_format.rt == bgezall_op)) { - ret = -SIGILL; - break; - } + insn.i_format.rt == bgezall_op)) + goto sigill_r2r6; regs->regs[31] = epc + 8; /* * OK we are here either because we hit a BAL -- cgit v0.10.2 From 3330a05c5c6ebb6134479bca4758d9766d1c9663 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:14:12 +0100 Subject: MIPS: Send SIGILL for R6 branches in `__compute_return_epc_for_insn' commit a60b1a5bf88a250f1a77977c0224e502c901c77b upstream. Fix: * commit 8467ca0122e2 ("MIPS: Emulate the new MIPS R6 branch compact (BC) instruction"), * commit 84fef630127a ("MIPS: Emulate the new MIPS R6 BALC instruction"), * commit 69b9a2fd05a3 ("MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions"), * commit 28d6f93d201d ("MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions"), * commit c893ce38b265 ("MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions") and send SIGILL rather than returning -SIGILL for R6 branch and jump instructions. Returning -SIGILL is never correct as the API defines this function's result upon error to be -EFAULT and a signal actually issued. Fixes: 8467ca0122e2 ("MIPS: Emulate the new MIPS R6 branch compact (BC) instruction") Fixes: 84fef630127a ("MIPS: Emulate the new MIPS R6 BALC instruction") Fixes: 69b9a2fd05a3 ("MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions") Fixes: 28d6f93d201d ("MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions") Fixes: c893ce38b265 ("MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16399/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index ddf0f02..be6d4ba 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -771,35 +771,27 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, #else case bc6_op: /* Only valid for MIPS R6 */ - if (!cpu_has_mips_r6) { - ret = -SIGILL; - break; - } + if (!cpu_has_mips_r6) + goto sigill_r6; regs->cp0_epc += 8; break; case balc6_op: - if (!cpu_has_mips_r6) { - ret = -SIGILL; - break; - } + if (!cpu_has_mips_r6) + goto sigill_r6; /* Compact branch: BALC */ regs->regs[31] = epc + 4; epc += 4 + (insn.i_format.simmediate << 2); regs->cp0_epc = epc; break; case pop66_op: - if (!cpu_has_mips_r6) { - ret = -SIGILL; - break; - } + if (!cpu_has_mips_r6) + goto sigill_r6; /* Compact branch: BEQZC || JIC */ regs->cp0_epc += 8; break; case pop76_op: - if (!cpu_has_mips_r6) { - ret = -SIGILL; - break; - } + if (!cpu_has_mips_r6) + goto sigill_r6; /* Compact branch: BNEZC || JIALC */ if (!insn.i_format.rs) { /* JIALC: set $31/ra */ @@ -811,10 +803,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case pop10_op: case pop30_op: /* Only valid for MIPS R6 */ - if (!cpu_has_mips_r6) { - ret = -SIGILL; - break; - } + if (!cpu_has_mips_r6) + goto sigill_r6; /* * Compact branches: * bovc, beqc, beqzalc, bnvc, bnec, bnezlac @@ -837,6 +827,11 @@ sigill_r2r6: current->comm); force_sig(SIGILL, current); return -EFAULT; +sigill_r6: + pr_info("%s: R6 branch but no MIPSr6 ISA support - sending SIGILL.\n", + current->comm); + force_sig(SIGILL, current); + return -EFAULT; } EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn); -- cgit v0.10.2 From 6d77ac4bc514568b98762f3a35b83a4de3e966b8 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 16 Jun 2017 00:15:22 +0100 Subject: MIPS: Fix a typo: s/preset/present/ in r2-to-r6 emulation error message commit 27fe2200dad2de8207a694024a7b9037dff1b280 upstream. This is a user-visible message, so we want it to be spelled correctly. Fixes: 5f9f41c474be ("MIPS: kernel: Prepare the JR instruction for emulation on MIPS R6") Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16400/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index be6d4ba..c3f2fb3 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -823,7 +823,7 @@ sigill_dsp: force_sig(SIGILL, current); return -EFAULT; sigill_r2r6: - pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n", + pr_info("%s: R2 branch but r2-to-r6 emulator is not present - sending SIGILL.\n", current->comm); force_sig(SIGILL, current); return -EFAULT; -- cgit v0.10.2 From 5b50e0e74e2e5f084d18a03f6dedc67cfdb8db49 Mon Sep 17 00:00:00 2001 From: Chen Hong Date: Sun, 2 Jul 2017 15:11:10 -0700 Subject: Input: i8042 - fix crash at boot time commit 340d394a789518018f834ff70f7534fc463d3226 upstream. The driver checks port->exists twice in i8042_interrupt(), first when trying to assign temporary "serio" variable, and second time when deciding whether it should call serio_interrupt(). The value of port->exists may change between the 2 checks, and we may end up calling serio_interrupt() with a NULL pointer: BUG: unable to handle kernel NULL pointer dereference at 0000000000000050 IP: [] _spin_lock_irqsave+0x1f/0x40 PGD 0 Oops: 0002 [#1] SMP last sysfs file: CPU 0 Modules linked in: Pid: 1, comm: swapper Not tainted 2.6.32-358.el6.x86_64 #1 QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:[] [] _spin_lock_irqsave+0x1f/0x40 RSP: 0018:ffff880028203cc0 EFLAGS: 00010082 RAX: 0000000000010000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000282 RSI: 0000000000000098 RDI: 0000000000000050 RBP: ffff880028203cc0 R08: ffff88013e79c000 R09: ffff880028203ee0 R10: 0000000000000298 R11: 0000000000000282 R12: 0000000000000050 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000098 FS: 0000000000000000(0000) GS:ffff880028200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000050 CR3: 0000000001a85000 CR4: 00000000001407f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 1, threadinfo ffff88013e79c000, task ffff88013e79b500) Stack: ffff880028203d00 ffffffff813de186 ffffffffffffff02 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000098 ffff880028203d70 ffffffff813e0162 ffff880028203d20 ffffffff8103b8ac Call Trace: [] serio_interrupt+0x36/0xa0 [] i8042_interrupt+0x132/0x3a0 [] ? kvm_clock_read+0x1c/0x20 [] ? kvm_clock_get_cycles+0x9/0x10 [] handle_IRQ_event+0x60/0x170 [] ? kvm_guest_apic_eoi_write+0x44/0x50 [] handle_edge_irq+0xde/0x180 [] handle_irq+0x49/0xa0 [] do_IRQ+0x6c/0xf0 [] ret_from_intr+0x0/0x11 [] ? __do_softirq+0x73/0x1e0 [] ? hrtimer_interrupt+0x14b/0x260 [] ? call_softirq+0x1c/0x30 [] ? do_softirq+0x65/0xa0 [] ? irq_exit+0x85/0x90 [] ? smp_apic_timer_interrupt+0x70/0x9b [] ? apic_timer_interrupt+0x13/0x20 To avoid the issue let's change the second check to test whether serio is NULL or not. Also, let's take i8042_lock in i8042_start() and i8042_stop() instead of trying to be overly smart and using memory barriers. Signed-off-by: Chen Hong [dtor: take lock in i8042_start()/i8042_stop()] Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 89abfdb..c84c685 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -434,8 +434,10 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; + spin_lock_irq(&i8042_lock); port->exists = true; - mb(); + spin_unlock_irq(&i8042_lock); + return 0; } @@ -448,16 +450,20 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; + spin_lock_irq(&i8042_lock); port->exists = false; + port->serio = NULL; + spin_unlock_irq(&i8042_lock); /* + * We need to make sure that interrupt handler finishes using + * our serio port before we return from this function. * We synchronize with both AUX and KBD IRQs because there is * a (very unlikely) chance that AUX IRQ is raised for KBD port * and vice versa. */ synchronize_irq(I8042_AUX_IRQ); synchronize_irq(I8042_KBD_IRQ); - port->serio = NULL; } /* @@ -574,7 +580,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&i8042_lock, flags); - if (likely(port->exists && !filtered)) + if (likely(serio && !filtered)) serio_interrupt(serio, data, dfl); out: -- cgit v0.10.2 From 5c2717f4154502779e696b303cf8dcfb94b2e5f5 Mon Sep 17 00:00:00 2001 From: Vladimir Neyelov Date: Sun, 21 May 2017 19:17:31 +0300 Subject: IB/iser: Fix connection teardown race condition commit c8c16d3bae967f1c7af541e8d016e5c51e4f010a upstream. Under heavy iser target(scst) start/stop stress during login/logout on iser intitiator side happened trace call provided below. The function iscsi_iser_slave_alloc iser_conn pointer could be NULL, due to the fact that function iscsi_iser_conn_stop can be called before and free iser connection. Let's protect that flow by introducing global mutex. BUG: unable to handle kernel paging request at 0000000000001018 IP: [] iscsi_iser_slave_alloc+0x1e/0x50 [ib_iser] Call Trace: ? scsi_alloc_sdev+0x242/0x300 scsi_probe_and_add_lun+0x9e1/0xea0 ? kfree_const+0x21/0x30 ? kobject_set_name_vargs+0x76/0x90 ? __pm_runtime_resume+0x5b/0x70 __scsi_scan_target+0xf6/0x250 scsi_scan_target+0xea/0x100 iscsi_user_scan_session.part.13+0x101/0x130 [scsi_transport_iscsi] ? iscsi_user_scan_session.part.13+0x130/0x130 [scsi_transport_iscsi] iscsi_user_scan_session+0x1e/0x30 [scsi_transport_iscsi] device_for_each_child+0x50/0x90 iscsi_user_scan+0x44/0x60 [scsi_transport_iscsi] store_scan+0xa8/0x100 ? common_file_perm+0x5d/0x1c0 dev_attr_store+0x18/0x30 sysfs_kf_write+0x37/0x40 kernfs_fop_write+0x12c/0x1c0 __vfs_write+0x18/0x40 vfs_write+0xb5/0x1a0 SyS_write+0x55/0xc0 Fixes: 318d311e8f01 ("iser: Accept arbitrary sg lists mapping if the device supports it") Signed-off-by: Vladimir Neyelov Signed-off-by: Leon Romanovsky Reviewed-by: Sagi Grimberg Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 140f3f3..e46e2b0 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -83,6 +83,7 @@ static struct scsi_host_template iscsi_iser_sht; static struct iscsi_transport iscsi_iser_transport; static struct scsi_transport_template *iscsi_iser_scsi_transport; static struct workqueue_struct *release_wq; +static DEFINE_MUTEX(unbind_iser_conn_mutex); struct iser_global ig; int iser_debug_level = 0; @@ -550,12 +551,14 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) */ if (iser_conn) { mutex_lock(&iser_conn->state_mutex); + mutex_lock(&unbind_iser_conn_mutex); iser_conn_terminate(iser_conn); iscsi_conn_stop(cls_conn, flag); /* unbind */ iser_conn->iscsi_conn = NULL; conn->dd_data = NULL; + mutex_unlock(&unbind_iser_conn_mutex); complete(&iser_conn->stop_completion); mutex_unlock(&iser_conn->state_mutex); @@ -973,13 +976,21 @@ static int iscsi_iser_slave_alloc(struct scsi_device *sdev) struct iser_conn *iser_conn; struct ib_device *ib_dev; + mutex_lock(&unbind_iser_conn_mutex); + session = starget_to_session(scsi_target(sdev))->dd_data; iser_conn = session->leadconn->dd_data; + if (!iser_conn) { + mutex_unlock(&unbind_iser_conn_mutex); + return -ENOTCONN; + } ib_dev = iser_conn->ib_conn.device->ib_device; if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)) blk_queue_virt_boundary(sdev->request_queue, ~MASK_4K); + mutex_unlock(&unbind_iser_conn_mutex); + return 0; } -- cgit v0.10.2 From dd0d6509cbf4ad5624300083ed7f98dcdac55e2a Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Tue, 23 May 2017 10:48:44 +0300 Subject: IB/core: Namespace is mandatory input for address resolution commit bebb2a473a43c8f84a8210687d1cbdde503046d7 upstream. In function addr_resolve() the namespace is a required input parameter and not an output. It is passed later for searching the routing table and device addresses. Also, it shouldn't be copied back to the caller. Fixes: 565edd1d5555 ('IB/addr: Pass network namespace as a parameter') Signed-off-by: Moni Shoua Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 8fd108d..63e82f8 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -518,6 +518,11 @@ static int addr_resolve(struct sockaddr *src_in, struct dst_entry *dst; int ret; + if (!addr->net) { + pr_warn_ratelimited("%s: missing namespace\n", __func__); + return -EINVAL; + } + if (src_in->sa_family == AF_INET) { struct rtable *rt = NULL; const struct sockaddr_in *dst_in4 = @@ -555,7 +560,6 @@ static int addr_resolve(struct sockaddr *src_in, } addr->bound_dev_if = ndev->ifindex; - addr->net = dev_net(ndev); dev_put(ndev); return ret; -- cgit v0.10.2 From 4dd0aa9ae6d0e948848f87b4c040cea8163a59bf Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 10 Jun 2017 04:59:07 +0200 Subject: sunrpc: use constant time memory comparison for mac commit 15a8b93fd5690de017ce665382ea45e5d61811a4 upstream. Otherwise, we enable a MAC forgery via timing attack. Signed-off-by: Jason A. Donenfeld Cc: "J. Bruce Fields" Cc: Jeff Layton Cc: Trond Myklebust Cc: Anna Schumaker Cc: linux-nfs@vger.kernel.org Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 90115ce..79aec90 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -34,6 +34,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#include #include #include #include @@ -927,7 +928,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, if (ret) goto out_err; - if (memcmp(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) { + if (crypto_memneq(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) { ret = GSS_S_BAD_SIG; goto out_err; } -- cgit v0.10.2 From 9ebfb4fa3ab7ea99b5d93305b10ee3714501b465 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 5 Jul 2017 12:22:20 +1000 Subject: NFS: only invalidate dentrys that are clearly invalid. commit cc89684c9a265828ce061037f1f79f4a68ccd3f7 upstream. Since commit bafc9b754f75 ("vfs: More precise tests in d_invalidate") in v3.18, a return of '0' from ->d_revalidate() will cause the dentry to be invalidated even if it has filesystems mounted on or it or on a descendant. The mounted filesystem is unmounted. This means we need to be careful not to return 0 unless the directory referred to truly is invalid. So -ESTALE or -ENOENT should invalidate the directory. Other errors such a -EPERM or -ERESTARTSYS should be returned from ->d_revalidate() so they are propagated to the caller. A particular problem can be demonstrated by: 1/ mount an NFS filesystem using NFSv3 on /mnt 2/ mount any other filesystem on /mnt/foo 3/ ls /mnt/foo 4/ turn off network, or otherwise make the server unable to respond 5/ ls /mnt/foo & 6/ cat /proc/$!/stack # note that nfs_lookup_revalidate is in the call stack 7/ kill -9 $! # this results in -ERESTARTSYS being returned 8/ observe that /mnt/foo has been unmounted. This patch changes nfs_lookup_revalidate() to only treat -ESTALE from nfs_lookup_verify_inode() and -ESTALE or -ENOENT from ->lookup() as indicating an invalid inode. Other errors are returned. Also nfs_check_inode_attributes() is changed to return -ESTALE rather than -EIO. This is consistent with the error returned in similar circumstances from nfs_update_inode(). As this bug allows any user to unmount a filesystem mounted on an NFS filesystem, this fix is suitable for stable kernels. Fixes: bafc9b754f75 ("vfs: More precise tests in d_invalidate") Signed-off-by: NeilBrown Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 53e02b8..d04ec381 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1167,11 +1167,13 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) /* Force a full look up iff the parent directory has changed */ if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) { - - if (nfs_lookup_verify_inode(inode, flags)) { + error = nfs_lookup_verify_inode(inode, flags); + if (error) { if (flags & LOOKUP_RCU) return -ECHILD; - goto out_zap_parent; + if (error == -ESTALE) + goto out_zap_parent; + goto out_error; } goto out_valid; } @@ -1195,8 +1197,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) trace_nfs_lookup_revalidate_enter(dir, dentry, flags); error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); - if (error) + if (error == -ESTALE || error == -ENOENT) goto out_bad; + if (error) + goto out_error; if (nfs_compare_fh(NFS_FH(inode), fhandle)) goto out_bad; if ((error = nfs_refresh_inode(inode, fattr)) != 0) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index bf4ec5e..76ae256 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1278,9 +1278,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat return 0; /* Has the inode gone and changed behind our back? */ if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) - return -EIO; + return -ESTALE; if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) - return -EIO; + return -ESTALE; if (!nfs_file_has_buffered_writers(nfsi)) { /* Verify a few of the more important attributes */ -- cgit v0.10.2 From fa67ac18eff4b59b7937c59e821f8b4be812113c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Jun 2017 16:20:25 +0200 Subject: udf: Fix deadlock between writeback and udf_setsize() commit f2e95355891153f66d4156bf3a142c6489cd78c6 upstream. udf_setsize() called truncate_setsize() with i_data_sem held. Thus truncate_pagecache() called from truncate_setsize() could lock a page under i_data_sem which can deadlock as page lock ranks below i_data_sem - e. g. writeback can hold page lock and try to acquire i_data_sem to map a block. Fix the problem by moving truncate_setsize() calls from under i_data_sem. It is safe for us to change i_size without holding i_data_sem as all the places that depend on i_size being stable already hold inode_lock. Fixes: 7e49b6f2480cb9a9e7322a91592e56a5c85361f5 Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 129b18a..0359435 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1243,8 +1243,8 @@ int udf_setsize(struct inode *inode, loff_t newsize) return err; } set_size: - truncate_setsize(inode, newsize); up_write(&iinfo->i_data_sem); + truncate_setsize(inode, newsize); } else { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { down_write(&iinfo->i_data_sem); @@ -1261,9 +1261,9 @@ set_size: udf_get_block); if (err) return err; + truncate_setsize(inode, newsize); down_write(&iinfo->i_data_sem); udf_clear_extent_cache(inode); - truncate_setsize(inode, newsize); udf_truncate_extents(inode); up_write(&iinfo->i_data_sem); } -- cgit v0.10.2 From 672145dfae842fe31dfaedd965a23e051a4722b5 Mon Sep 17 00:00:00 2001 From: Jiang Yi Date: Sun, 25 Jun 2017 12:28:50 -0700 Subject: target: Fix COMPARE_AND_WRITE caw_sem leak during se_cmd quiesce commit 1d6ef276594a781686058802996e09c8550fd767 upstream. This patch addresses a COMPARE_AND_WRITE se_device->caw_sem leak, that would be triggered during normal se_cmd shutdown or abort via __transport_wait_for_tasks(). This would occur because target_complete_cmd() would catch this early and do complete_all(&cmd->t_transport_stop_comp), but since target_complete_ok_work() or target_complete_failure_work() are never called to invoke se_cmd->transport_complete_callback(), the COMPARE_AND_WRITE specific callbacks never release caw_sem. To address this special case, go ahead and release caw_sem directly from target_complete_cmd(). (Remove '&& success' from check, to release caw_sem regardless of scsi_status - nab) Signed-off-by: Jiang Yi Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 1f9bfa4..e8a1f5c 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -753,6 +753,15 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) if (cmd->transport_state & CMD_T_ABORTED || cmd->transport_state & CMD_T_STOP) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); + /* + * If COMPARE_AND_WRITE was stopped by __transport_wait_for_tasks(), + * release se_device->caw_sem obtained by sbc_compare_and_write() + * since target_complete_ok_work() or target_complete_failure_work() + * won't be called to invoke the normal CAW completion callbacks. + */ + if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) { + up(&dev->caw_sem); + } complete_all(&cmd->t_transport_stop_comp); return; } else if (!success) { -- cgit v0.10.2 From d5f9cd081c66f0b3187626c1c9f7b89949aae71f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 29 Jun 2017 22:21:31 -0700 Subject: iser-target: Avoid isert_conn->cm_id dereference in isert_login_recv_done commit fce50a2fa4e9c6e103915c351b6d4a98661341d6 upstream. This patch fixes a NULL pointer dereference in isert_login_recv_done() of isert_conn->cm_id due to isert_cma_handler() -> isert_connect_error() resetting isert_conn->cm_id = NULL during a failed login attempt. As per Sagi, we will always see the completion of all recv wrs posted on the qp (given that we assigned a ->done handler), this is a FLUSH error completion, we just don't get to verify that because we deref NULL before. The issue here, was the assumption that dereferencing the connection cm_id is always safe, which is not true since: commit 4a579da2586bd3b79b025947ea24ede2bbfede62 Author: Sagi Grimberg Date: Sun Mar 29 15:52:04 2015 +0300 iser-target: Fix possible deadlock in RDMA_CM connection error As I see it, we have a direct reference to the isert_device from isert_conn which is the one-liner fix that we actually need like we do in isert_rdma_read_done() and isert_rdma_write_done(). Reported-by: Andrea Righi Tested-by: Andrea Righi Reviewed-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 6dd43f6..39d2837 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1447,7 +1447,7 @@ static void isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) { struct isert_conn *isert_conn = wc->qp->qp_context; - struct ib_device *ib_dev = isert_conn->cm_id->device; + struct ib_device *ib_dev = isert_conn->device->ib_device; if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "login recv"); -- cgit v0.10.2 From 61415418cdba50d37db8a474e2c30af1aba30092 Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Thu, 8 Jun 2017 14:01:44 +0800 Subject: perf annotate: Fix broken arrow at row 0 connecting jmp instruction to its target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 80f62589fa52f530cffc50e78c0b5a2ae572d61e upstream. When the jump instruction is displayed at the row 0 in annotate view, the arrow is broken. An example: 16.86 │ ┌──je 82 0.01 │ movsd (%rsp),%xmm0 │ movsd 0x8(%rsp),%xmm4 │ movsd 0x8(%rsp),%xmm1 │ movsd (%rsp),%xmm3 │ divsd %xmm4,%xmm0 │ divsd %xmm3,%xmm1 │ movsd (%rsp),%xmm2 │ addsd %xmm1,%xmm0 │ addsd %xmm2,%xmm0 │ movsd %xmm0,(%rsp) │82: sub $0x1,%ebx 83.03 │ ↑ jne 38 │ add $0x10,%rsp │ xor %eax,%eax │ pop %rbx │ ← retq The patch increments the row number before checking with 0. Signed-off-by: Yao Jin Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jiri Olsa Cc: Kan Liang Cc: Peter Zijlstra Fixes: 944e1abed9e1 ("perf ui browser: Add method to draw up/down arrow line") Link: http://lkml.kernel.org/r/1496901704-30275-1-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 3eb3edb..a130901 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -702,7 +702,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, ui_browser__gotorc(browser, row, column + 1); SLsmg_draw_hline(2); - if (row++ == 0) + if (++row == 0) goto out; } else row = 0; -- cgit v0.10.2 From a76a032300e26ecbc398dcaaeb10b5a850a95f76 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 11 Jul 2017 10:56:54 +0200 Subject: Revert "perf/core: Drop kernel samples even though :u is specified" commit 6a8a75f3235724c5941a33e287b2f98966ad14c5 upstream. This reverts commit cc1582c231ea041fbc68861dfaf957eaf902b829. This commit introduced a regression that broke rr-project, which uses sampling events to receive a signal on overflow (but does not care about the contents of the sample). These signals are critical to the correct operation of rr. There's been some back and forth about how to fix it - but to not keep applications in limbo queue up a revert. Reported-by: Kyle Huey Acked-by: Kyle Huey Acked-by: Peter Zijlstra Cc: Jin Yao Cc: Vince Weaver Cc: Linus Torvalds Cc: Will Deacon Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Stephane Eranian Cc: Namhyung Kim Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20170628105600.GC5981@leverpostej Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman diff --git a/kernel/events/core.c b/kernel/events/core.c index 30ccc70..f5a6935 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7088,21 +7088,6 @@ static void perf_log_itrace_start(struct perf_event *event) perf_output_end(&handle); } -static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs) -{ - /* - * Due to interrupt latency (AKA "skid"), we may enter the - * kernel before taking an overflow, even if the PMU is only - * counting user events. - * To avoid leaking information to userspace, we must always - * reject kernel samples when exclude_kernel is set. - */ - if (event->attr.exclude_kernel && !user_mode(regs)) - return false; - - return true; -} - /* * Generic event overflow handling, sampling. */ @@ -7150,12 +7135,6 @@ static int __perf_event_overflow(struct perf_event *event, } /* - * For security, drop the skid kernel samples if necessary. - */ - if (!sample_is_allowed(event, regs)) - return ret; - - /* * XXX event_limit might not quite work as expected on inherited * events */ -- cgit v0.10.2 From 964a21a1300c2857483e85f1d013c5867ee4d433 Mon Sep 17 00:00:00 2001 From: Michael Gugino Date: Mon, 17 Jul 2017 13:29:09 -0400 Subject: staging: rtl8188eu: add TL-WN722N v2 support commit 5a1d4c5dd4eb2f1f8a9b30e61762f3b3b564df70 upstream. Add support for USB Device TP-Link TL-WN722N v2. VendorID: 0x2357, ProductID: 0x010c Signed-off-by: Michael Gugino Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 68e1e6b..b432153 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -43,6 +43,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ + {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ {} /* Terminating entry */ }; -- cgit v0.10.2 From 2bc52403da8a940d3ecc1b4c770cab9a650167ae Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jun 2017 12:02:18 +0100 Subject: staging: comedi: ni_mio_common: fix AO timer off-by-one regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 15d5193104a457d5151840247e3bce561c42e3e9 upstream. As reported by Éric Piel on the Comedi mailing list (see ), the analog output asynchronous commands are running too fast with a period 50 ns shorter than it should be. This affects all boards with AO command support that are supported by the "ni_pcimio", "ni_atmio", and "ni_mio_cs" drivers. This is a regression bug introduced by commit 080e6795cba3 ("staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_cmd"), specifically, this line in `ni_ao_cmd_set_update()`: /* following line: N-1 per STC */ ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG); The `trigvar` variable value comes from a call to `ni_ns_to_timer()` which converts a timer period in nanoseconds to a hardware divisor value. The function already reduces the divisor by 1 as required by the hardware, so the above line should not reduce it further by 1. Fix it by replacing `trigvar` by `trigvar - 1` in the above line, and remove the misleading comment. Reported-by: Éric Piel Fixes: 080e6795cba3 ("staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_cmd") Cc: Éric Piel Cc: Spencer E. Olson Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1c967c3..a574885 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3078,8 +3078,7 @@ static void ni_ao_cmd_set_update(struct comedi_device *dev, /* following line: 2-1 per STC */ ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); - /* following line: N-1 per STC */ - ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG); + ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); } else { /* TRIG_EXT */ /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */ devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; -- cgit v0.10.2 From 85643f6f50282d52c8d8cedbf958092b2a03cf7a Mon Sep 17 00:00:00 2001 From: Teddy Wang Date: Fri, 30 Jun 2017 21:57:43 +0100 Subject: staging: sm750fb: avoid conflicting vesafb commit 740c433ec35187b45abe08bb6c45a321a791be8e upstream. If vesafb is enabled in the config then /dev/fb0 is created by vesa and this sm750 driver gets fb1, fb2. But we need to be fb0 and fb1 to effectively work with xorg. So if it has been alloted fb1, then try to remove the other fb0. In the previous send, why #ifdef is used was asked. https://lkml.org/lkml/2017/6/25/57 Answered at: https://lkml.org/lkml/2017/6/25/69 Also pasting here for reference. 'Did a quick research into "why". The patch d8801e4df91e ("x86/PCI: Set IORESOURCE_ROM_SHADOW only for the default VGA device") has started setting IORESOURCE_ROM_SHADOW in flags for a default VGA device and that is being done only for x86. And so, we will need that #ifdef to check IORESOURCE_ROM_SHADOW as that needs to be checked only for a x86 and not for other arch.' Signed-off-by: Teddy Wang Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 7d90e25..86ace14 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1049,6 +1049,26 @@ release_fb: return err; } +static int lynxfb_kick_out_firmware_fb(struct pci_dev *pdev) +{ + struct apertures_struct *ap; + bool primary = false; + + ap = alloc_apertures(1); + if (!ap) + return -ENOMEM; + + ap->ranges[0].base = pci_resource_start(pdev, 0); + ap->ranges[0].size = pci_resource_len(pdev, 0); +#ifdef CONFIG_X86 + primary = pdev->resource[PCI_ROM_RESOURCE].flags & + IORESOURCE_ROM_SHADOW; +#endif + remove_conflicting_framebuffers(ap, "sm750_fb1", primary); + kfree(ap); + return 0; +} + static int lynxfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1057,6 +1077,10 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, int fbidx; int err; + err = lynxfb_kick_out_firmware_fb(pdev); + if (err) + return err; + /* enable device */ err = pcim_enable_device(pdev); if (err) -- cgit v0.10.2 From d42f9c7435c06c370966281782fd0e33a2eff460 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 15 Jul 2017 11:32:08 -0400 Subject: staging: lustre: ko2iblnd: check copy_from_iter/copy_to_iter return code commit 566e1ce22e04426fa52328b2adcdf1df49acd98e upstream. We now get a helpful warning for code that calls copy_{from,to}_iter without checking the return value, introduced by commit aa28de275a24 ("iov_iter/hardening: move object size checks to inlined part"). drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c: In function 'kiblnd_send': drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c:1643:2: error: ignoring return value of 'copy_from_iter', declared with attribute warn_unused_result [-Werror=unused-result] drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c: In function 'kiblnd_recv': drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c:1744:3: error: ignoring return value of 'copy_to_iter', declared with attribute warn_unused_result [-Werror=unused-result] In case we get short copies here, we may get incorrect behavior. I've added failure handling for both rx and tx now, returning -EFAULT as expected. Signed-off-by: Arnd Bergmann Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index b27de88..995f2da 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1650,8 +1650,13 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) ibmsg = tx->tx_msg; ibmsg->ibm_u.immediate.ibim_hdr = *hdr; - copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, IBLND_MSG_SIZE, - &from); + rc = copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, payload_nob, + &from); + if (rc != payload_nob) { + kiblnd_pool_free_node(&tx->tx_pool->tpo_pool, &tx->tx_list); + return -EFAULT; + } + nob = offsetof(struct kib_immediate_msg, ibim_payload[payload_nob]); kiblnd_init_tx_msg(ni, tx, IBLND_MSG_IMMEDIATE, nob); @@ -1751,8 +1756,14 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, break; } - copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload, - IBLND_MSG_SIZE, to); + rc = copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload, rlen, + to); + if (rc != rlen) { + rc = -EFAULT; + break; + } + + rc = 0; lnet_finalize(ni, lntmsg, 0); break; -- cgit v0.10.2 From acccf01a807abddda5ceb2fe3b72a38429044d0e Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 6 Jul 2017 11:12:21 +0800 Subject: ceph: fix race in concurrent readdir commit 84583cfb973c4313955c6231cc9cb3772d280b15 upstream. For a large directory, program needs to issue multiple readdir syscalls to get all dentries. When there are multiple programs read the directory concurrently. Following sequence of events can happen. - program calls readdir with pos = 2. ceph sends readdir request to mds. The reply contains N1 entries. ceph adds these N1 entries to readdir cache. - program calls readdir with pos = N1+2. The readdir is satisfied by the readdir cache, N2 entries are returned. (Other program calls readdir in the middle, which fills the cache) - program calls readdir with pos = N1+N2+2. ceph sends readdir request to mds. The reply contains N3 entries and it reaches directory end. ceph adds these N3 entries to the readdir cache and marks directory complete. The second readdir call does not update fi->readdir_cache_idx. ceph add the last N3 entries to wrong places. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov Signed-off-by: Greg Kroah-Hartman diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index aca0d88..cec2569 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -292,6 +292,11 @@ out: if (ret < 0) err = ret; dput(last); + /* last_name no longer match cache index */ + if (fi->readdir_cache_idx >= 0) { + fi->readdir_cache_idx = -1; + fi->dir_release_count = 0; + } } return err; } -- cgit v0.10.2 From db29753960904012acfb8958bda5bc53c97f7e56 Mon Sep 17 00:00:00 2001 From: "Ismail, Mustafa" Date: Fri, 14 Jul 2017 09:41:31 -0500 Subject: RDMA/core: Initialize port_num in qp_attr commit a62ab66b13a0f9bcb17b7b761f6670941ed5cd62 upstream. Initialize the port_num for iWARP in rdma_init_qp_attr. Fixes: 5ecce4c9b17b("Check port number supplied by user verbs cmds") Reviewed-by: Steve Wise Signed-off-by: Mustafa Ismail Tested-by: Mike Marciniszyn Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index f2d40c0..809a028 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -976,6 +976,8 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, } else ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, qp_attr_mask); + qp_attr->port_num = id_priv->id.port_num; + *qp_attr_mask |= IB_QP_PORT; } else ret = -ENOSYS; -- cgit v0.10.2 From bc3bd649ebb45c9b8cac19d1703fe012ba067600 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 19 Jul 2017 14:43:28 +0300 Subject: drm/mst: Fix error handling during MST sideband message reception commit 448421b5e93b9177c5698f0cf6f5e72d2995eeca upstream. Handle any error due to partial reads, timeouts etc. to avoid parsing uninitialized data subsequently. Also bail out if the parsing itself fails. Cc: Dave Airlie Cc: Lyude Cc: Daniel Vetter Signed-off-by: Imre Deak Reviewed-by: Lyude Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20170719114330.26540-2-imre.deak@intel.com Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index f59771d..ce422d8 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2200,11 +2200,17 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply, replyblock, len); if (ret != len) { - DRM_DEBUG_KMS("failed to read a chunk\n"); + DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n", + len, ret); + return; } + ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); - if (ret == false) + if (!ret) { DRM_DEBUG_KMS("failed to build sideband msg\n"); + return; + } + curreply += len; replylen -= len; } -- cgit v0.10.2 From 48376e6b71a67616db860872c1fa3b2eae4ad359 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 19 Jul 2017 14:43:29 +0300 Subject: drm/mst: Avoid dereferencing a NULL mstb in drm_dp_mst_handle_up_req() commit 7f8b3987da54cb4d41ad2545cd4d7958b9a36bdf upstream. In case of an unknown broadcast message is sent mstb will remain unset, so check for this. Cc: Dave Airlie Cc: Lyude Cc: Daniel Vetter Signed-off-by: Imre Deak Reviewed-by: Lyude Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20170719114330.26540-3-imre.deak@intel.com Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ce422d8..4f29792 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2328,7 +2328,9 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); } - drm_dp_put_mst_branch_device(mstb); + if (mstb) + drm_dp_put_mst_branch_device(mstb); + memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); } return ret; -- cgit v0.10.2 From a440425194692f9b1d65728615b8599b9b517c0b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 19 Jul 2017 16:46:32 +0300 Subject: drm/mst: Avoid processing partially received up/down message transactions commit 636c4c3e762b62aa93632c645ca65879285b16e3 upstream. Currently we may process up/down message transactions containing uninitialized data. This can happen if there was an error during the reception of any message in the transaction, but we happened to receive the last message correctly with the end-of-message flag set. To avoid this abort the reception of the transaction when the first error is detected, rejecting any messages until a message with the start-of-message flag is received (which will start a new transaction). This is also what the DP 1.4 spec 2.11.8.2 calls for in this case. In addtion this also prevents receiving bogus transactions without the first message with the the start-of-message flag set. v2: - unchanged v3: - git add the part that actually skips messages after an error in drm_dp_sideband_msg_build() Cc: Dave Airlie Cc: Lyude Cc: Daniel Vetter Signed-off-by: Imre Deak Reviewed-by: Lyude Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20170719134632.13366-1-imre.deak@intel.com Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 4f29792..db7890c 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -330,6 +330,13 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg, return false; } + /* + * ignore out-of-order messages or messages that are part of a + * failed transaction + */ + if (!recv_hdr.somt && !msg->have_somt) + return false; + /* get length contained in this portion */ msg->curchunk_len = recv_hdr.msg_len; msg->curchunk_hdrlen = hdrlen; @@ -2168,7 +2175,7 @@ out_unlock: } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); -static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) +static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) { int len; u8 replyblock[32]; @@ -2183,12 +2190,12 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) replyblock, len); if (ret != len) { DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret); - return; + return false; } ret = drm_dp_sideband_msg_build(msg, replyblock, len, true); if (!ret) { DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]); - return; + return false; } replylen = msg->curchunk_len + msg->curchunk_hdrlen; @@ -2202,25 +2209,30 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) if (ret != len) { DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n", len, ret); - return; + return false; } ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); if (!ret) { DRM_DEBUG_KMS("failed to build sideband msg\n"); - return; + return false; } curreply += len; replylen -= len; } + return true; } static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) { int ret = 0; - drm_dp_get_one_sb_msg(mgr, false); + if (!drm_dp_get_one_sb_msg(mgr, false)) { + memset(&mgr->down_rep_recv, 0, + sizeof(struct drm_dp_sideband_msg_rx)); + return 0; + } if (mgr->down_rep_recv.have_eomt) { struct drm_dp_sideband_msg_tx *txmsg; @@ -2276,7 +2288,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) { int ret = 0; - drm_dp_get_one_sb_msg(mgr, true); + + if (!drm_dp_get_one_sb_msg(mgr, true)) { + memset(&mgr->up_req_recv, 0, + sizeof(struct drm_dp_sideband_msg_rx)); + return 0; + } if (mgr->up_req_recv.have_eomt) { struct drm_dp_sideband_msg_req_body msg; -- cgit v0.10.2 From b33da556255ce9703ab06805200bff244697b014 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 24 Apr 2017 15:15:28 -0700 Subject: mlx5: Avoid that mlx5_ib_sg_to_klms() overflows the klms[] array commit 99975cd4fda52974a767aa44fe0b1a8f74950d9d upstream. ib_map_mr_sg() can pass an SG-list to .map_mr_sg() that is larger than what fits into a single MR. .map_mr_sg() must not attempt to map more SG-list elements than what fits into a single MR. Hence make sure that mlx5_ib_sg_to_klms() does not write outside the MR klms[] array. Fixes: b005d3164713 ("mlx5: Add arbitrary sg list support") Signed-off-by: Bart Van Assche Reviewed-by: Max Gurtovoy Cc: Sagi Grimberg Cc: Leon Romanovsky Cc: Israel Rukshin Acked-by: Leon Romanovsky Reviewed-by: Sagi Grimberg Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 1fb31a4..0a260a0 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -1823,7 +1823,7 @@ mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr, mr->ndescs = sg_nents; for_each_sg(sgl, sg, sg_nents, i) { - if (unlikely(i > mr->max_descs)) + if (unlikely(i >= mr->max_descs)) break; klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset); klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset); -- cgit v0.10.2 From 5cf84432b422e92775aef5c43b0dfc58585fabb0 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 21 Jun 2017 15:02:47 +0200 Subject: hfsplus: Don't clear SGID when inheriting ACLs commit 84969465ddc4f8aeb3b993123b571aa01c5f2683 upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by creating __hfsplus_set_posix_acl() function that does not call posix_acl_update_mode() and use it when inheriting ACLs. That prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c index 9b92058..6bb5d7c 100644 --- a/fs/hfsplus/posix_acl.c +++ b/fs/hfsplus/posix_acl.c @@ -51,8 +51,8 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type) return acl; } -int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, - int type) +static int __hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, + int type) { int err; char *xattr_name; @@ -64,12 +64,6 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, switch (type) { case ACL_TYPE_ACCESS: xattr_name = XATTR_NAME_POSIX_ACL_ACCESS; - if (acl) { - err = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (err) - return err; - } - err = 0; break; case ACL_TYPE_DEFAULT: @@ -105,6 +99,18 @@ end_set_acl: return err; } +int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + int err; + + if (type == ACL_TYPE_ACCESS && acl) { + err = posix_acl_update_mode(inode, &inode->i_mode, &acl); + if (err) + return err; + } + return __hfsplus_set_posix_acl(inode, acl, type); +} + int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir) { int err = 0; @@ -122,15 +128,15 @@ int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir) return err; if (default_acl) { - err = hfsplus_set_posix_acl(inode, default_acl, - ACL_TYPE_DEFAULT); + err = __hfsplus_set_posix_acl(inode, default_acl, + ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } if (acl) { if (!err) - err = hfsplus_set_posix_acl(inode, acl, - ACL_TYPE_ACCESS); + err = __hfsplus_set_posix_acl(inode, acl, + ACL_TYPE_ACCESS); posix_acl_release(acl); } return err; -- cgit v0.10.2 From 97de6f34b42b079befb14e58e7f8b0d6e989c014 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Tue, 11 Jul 2017 15:58:35 +0300 Subject: ovl: fix random return value on mount commit 8fc646b44385ff0a9853f6590497e43049eeb311 upstream. On failure to prepare_creds(), mount fails with a random return value, as err was last set to an integer cast of a valid lower mnt pointer or set to 0 if inodes index feature is enabled. Reported-by: Dan Carpenter Fixes: 3fe6e52f0626 ("ovl: override creds with the ones from ...") Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 2a01489..e7c8ac4 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1310,6 +1310,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) else sb->s_d_op = &ovl_dentry_operations; + err = -ENOMEM; ufs->creator_cred = cred = prepare_creds(); if (!cred) goto out_put_lower_mnt; -- cgit v0.10.2 From 6b50bca7cdb0822628f45bea2bb028630999aa13 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 31 May 2017 13:32:00 -0400 Subject: acpi/nfit: Fix memory corruption/Unregister mce decoder on failure commit 7e700d2c59e5853c9126642976b4f5768f64c9b3 upstream. nfit_init() calls nfit_mce_register() on module load. When the module load fails the nfit mce decoder is not unregistered. The module's memory is freed leaving the decoder chain referencing junk. This will cause panics as future registrations will reference the free'd memory. Unregister the nfit mce decoder on module init failure. [v2]: register and then unregister mce handler to avoid losing mce events [v3]: also cleanup nfit workqueue Fixes: 6839a6d96f4e ("nfit: do an ARS scrub on hitting a latent media error") Cc: "Rafael J. Wysocki" Cc: Len Brown Cc: Vishal Verma Cc: "Lee, Chun-Yi" Cc: Linda Knippers Cc: lszubowi@redhat.com Acked-by: Jeff Moyer Signed-off-by: Prarit Bhargava Reviewed-by: Vishal Verma Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 9ef3941..f3bc901 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -2945,6 +2945,8 @@ static struct acpi_driver acpi_nfit_driver = { static __init int nfit_init(void) { + int ret; + BUILD_BUG_ON(sizeof(struct acpi_table_nfit) != 40); BUILD_BUG_ON(sizeof(struct acpi_nfit_system_address) != 56); BUILD_BUG_ON(sizeof(struct acpi_nfit_memory_map) != 48); @@ -2972,8 +2974,14 @@ static __init int nfit_init(void) return -ENOMEM; nfit_mce_register(); + ret = acpi_bus_register_driver(&acpi_nfit_driver); + if (ret) { + nfit_mce_unregister(); + destroy_workqueue(nfit_wq); + } + + return ret; - return acpi_bus_register_driver(&acpi_nfit_driver); } static __exit void nfit_exit(void) -- cgit v0.10.2 From a18935b45e9700b5d21fce80ea82c1cb5efb4f9e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 28 Dec 2016 14:56:48 -0800 Subject: of: device: Export of_device_{get_modalias, uvent_modalias} to modules commit 7a3b7cd332db08546f3cdd984f11773e0d1999e7 upstream. The ULPI bus can be built as a module, and it will soon be calling these functions when it supports probing devices from DT. Export them so they can be used by the ULPI module. Acked-by: Rob Herring Cc: Signed-off-by: Stephen Boyd Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/of/device.c b/drivers/of/device.c index fd5cfad..f7a9701 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) return tsize; } +EXPORT_SYMBOL_GPL(of_device_get_modalias); /** * of_device_uevent - Display OF related uevent information @@ -287,3 +288,4 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) return 0; } +EXPORT_SYMBOL_GPL(of_device_uevent_modalias); -- cgit v0.10.2 From 1c7e5ca092c08bd2fde78a4eaad4a8afc5dc3555 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 29 Jun 2017 14:46:44 -0700 Subject: spmi: Include OF based modalias in device uevent commit d50daa2af2618dab6d21634e65a5fbcf4ae437d6 upstream. Include the OF-based modalias in the uevent sent when registering SPMI devices, so that user space has a chance to autoload the kernel module for the device. Tested-by: Rob Clark Reported-by: Rob Clark Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c index 2b9b094..6d23226 100644 --- a/drivers/spmi/spmi.c +++ b/drivers/spmi/spmi.c @@ -365,11 +365,23 @@ static int spmi_drv_remove(struct device *dev) return 0; } +static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + int ret; + + ret = of_device_uevent_modalias(dev, env); + if (ret != -ENODEV) + return ret; + + return 0; +} + static struct bus_type spmi_bus_type = { .name = "spmi", .match = spmi_device_match, .probe = spmi_drv_probe, .remove = spmi_drv_remove, + .uevent = spmi_drv_uevent, }; /** -- cgit v0.10.2 From 69fbb442144abc4a7288d42edb6eb8a1ee799d87 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 22 Jun 2017 09:32:49 +0200 Subject: reiserfs: Don't clear SGID when inheriting ACLs commit 6883cd7f68245e43e91e5ee583b7550abf14523f upstream. When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is expected to have SGID bit set (and owning group equal to the owning group of 'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is not member of the owning group. Fix the problem by moving posix_acl_update_mode() out of __reiserfs_set_acl() into reiserfs_set_acl(). That way the function will not be called when inheriting ACLs which is what we want as it prevents SGID bit clearing and the mode has been properly set by posix_acl_create() anyway. Fixes: 073931017b49d9458aa351605b43a7e34598caef CC: reiserfs-devel@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 3d2256a..d92a1dc 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -37,7 +37,14 @@ reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) error = journal_begin(&th, inode->i_sb, jcreate_blocks); reiserfs_write_unlock(inode->i_sb); if (error == 0) { + if (type == ACL_TYPE_ACCESS && acl) { + error = posix_acl_update_mode(inode, &inode->i_mode, + &acl); + if (error) + goto unlock; + } error = __reiserfs_set_acl(&th, inode, type, acl); +unlock: reiserfs_write_lock(inode->i_sb); error2 = journal_end(&th); reiserfs_write_unlock(inode->i_sb); @@ -241,11 +248,6 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; - if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) - return error; - } break; case ACL_TYPE_DEFAULT: name = XATTR_NAME_POSIX_ACL_DEFAULT; -- cgit v0.10.2 From 7bd804a05eb00954891abf66c6125d054b8a0f93 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 14 Jul 2017 11:51:48 +0100 Subject: PM / Domains: defer dev_pm_domain_set() until genpd->attach_dev succeeds if present commit 975e83cfb8dc16e7a2fdc58188c77c0c605876c2 upstream. If the genpd->attach_dev or genpd->power_on fails, genpd_dev_pm_attach may return -EPROBE_DEFER initially. However genpd_alloc_dev_data sets the PM domain for the device unconditionally. When subsequent attempts are made to call genpd_dev_pm_attach, it may return -EEXISTS checking dev->pm_domain without re-attempting to call attach_dev or power_on. platform_drv_probe then attempts to call drv->probe as the return value -EEXIST != -EPROBE_DEFER, which may end up in a situation where the device is accessed without it's power domain switched on. Fixes: f104e1e5ef57 (PM / Domains: Re-order initialization of generic_pm_domain_data) Signed-off-by: Sudeep Holla Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 951c214..8c7d0f3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1029,8 +1029,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, spin_unlock_irq(&dev->power.lock); - dev_pm_domain_set(dev, &genpd->domain); - return gpd_data; err_free: @@ -1044,8 +1042,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, static void genpd_free_dev_data(struct device *dev, struct generic_pm_domain_data *gpd_data) { - dev_pm_domain_set(dev, NULL); - spin_lock_irq(&dev->power.lock); dev->power.subsys_data->domain_data = NULL; @@ -1082,6 +1078,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, if (ret) goto out; + dev_pm_domain_set(dev, &genpd->domain); + genpd->device_count++; genpd->max_off_time_changed = true; @@ -1143,6 +1141,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, if (genpd->detach_dev) genpd->detach_dev(genpd, dev); + dev_pm_domain_set(dev, NULL); + list_del_init(&pdd->list_node); mutex_unlock(&genpd->lock); -- cgit v0.10.2 From 919e481152ce86bf1960a71b39a29ef643aaff03 Mon Sep 17 00:00:00 2001 From: Chunyu Hu Date: Thu, 20 Jul 2017 18:36:09 +0800 Subject: tracing: Fix kmemleak in instance_rmdir commit db9108e054700c96322b0f0028546aa4e643cf0b upstream. Hit the kmemleak when executing instance_rmdir, it forgot releasing mem of tracing_cpumask. With this fix, the warn does not appear any more. unreferenced object 0xffff93a8dfaa7c18 (size 8): comm "mkdir", pid 1436, jiffies 4294763622 (age 9134.308s) hex dump (first 8 bytes): ff ff ff ff ff ff ff ff ........ backtrace: [] kmemleak_alloc+0x4a/0xa0 [] __kmalloc_node+0xf1/0x280 [] alloc_cpumask_var_node+0x23/0x30 [] alloc_cpumask_var+0xe/0x10 [] instance_mkdir+0x90/0x240 [] tracefs_syscall_mkdir+0x40/0x70 [] vfs_mkdir+0x109/0x1b0 [] SyS_mkdir+0xd0/0x100 [] do_syscall_64+0x67/0x150 [] return_from_SYSCALL_64+0x0/0x6a [] 0xffffffffffffffff Link: http://lkml.kernel.org/r/1500546969-12594-1-git-send-email-chuhu@redhat.com Fixes: ccfe9e42e451 ("tracing: Make tracing_cpumask available for all instances") Signed-off-by: Chunyu Hu Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 52ee2c5..53c3080 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7162,6 +7162,7 @@ static int instance_rmdir(const char *name) } kfree(tr->topts); + free_cpumask_var(tr->tracing_cpumask); kfree(tr->name); kfree(tr); -- cgit v0.10.2 From 91af5f04cd5b498ccafa1fa554be8d22e953bc82 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Mon, 24 Jul 2017 10:19:24 -0700 Subject: alarmtimer: don't rate limit one-shot timers Commit ff86bf0c65f1 ("alarmtimer: Rate limit periodic intervals") sets a minimum bound on the alarm timer interval. This minimum bound shouldn't be applied if the interval is 0. Otherwise, one-shot timers will be converted into periodic ones. Fixes: ff86bf0c65f1 ("alarmtimer: Rate limit periodic intervals") Reported-by: Ben Fennema Signed-off-by: Greg Hackmann Cc: stable@vger.kernel.org Cc: John Stultz Reviewed-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 9ba04aa..d67ef56 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -629,7 +629,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, * Rate limit to the tick as a hot fix to prevent DOS. Will be * mopped up later. */ - if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) + if (timr->it.alarm.interval.tv64 && + ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) timr->it.alarm.interval = ktime_set(0, TICK_NSEC); exp = timespec_to_ktime(new_setting->it_value); -- cgit v0.10.2 From efcfbfb1d8bf756d1b58fe215bf4e419d176435b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Jul 2017 15:08:24 -0700 Subject: Linux 4.9.40 diff --git a/Makefile b/Makefile index 0a2c352..d9397a9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 39 +SUBLEVEL = 40 EXTRAVERSION = NAME = Roaring Lionus -- cgit v0.10.2