From: Greg Kroah-Hartman Date: Wed, 19 Apr 2017 12:55:15 +0000 (+0200) Subject: 3.18 patches X-Git-Tag: v4.4.63~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=38717e5f75e9e20bfd776879545eb158a7e448f3;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18 patches --- diff --git a/queue-3.18/catc-combine-failure-cleanup-code-in-catc_probe.patch b/queue-3.18/catc-combine-failure-cleanup-code-in-catc_probe.patch new file mode 100644 index 00000000000..35218027c80 --- /dev/null +++ b/queue-3.18/catc-combine-failure-cleanup-code-in-catc_probe.patch @@ -0,0 +1,74 @@ +From d41149145f98fe26dcd0bfd1d6cc095e6e041418 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:56:56 +0000 +Subject: catc: Combine failure cleanup code in catc_probe() + +From: Ben Hutchings + +commit d41149145f98fe26dcd0bfd1d6cc095e6e041418 upstream. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/catc.c | 33 +++++++++++++++++---------------- + 1 file changed, 17 insertions(+), 16 deletions(-) + +--- a/drivers/net/usb/catc.c ++++ b/drivers/net/usb/catc.c +@@ -777,7 +777,7 @@ static int catc_probe(struct usb_interfa + struct net_device *netdev; + struct catc *catc; + u8 broadcast[ETH_ALEN]; +- int i, pktsz; ++ int i, pktsz, ret; + + if (usb_set_interface(usbdev, + intf->altsetting->desc.bInterfaceNumber, 1)) { +@@ -812,12 +812,8 @@ static int catc_probe(struct usb_interfa + if ((!catc->ctrl_urb) || (!catc->tx_urb) || + (!catc->rx_urb) || (!catc->irq_urb)) { + dev_err(&intf->dev, "No free urbs available.\n"); +- usb_free_urb(catc->ctrl_urb); +- usb_free_urb(catc->tx_urb); +- usb_free_urb(catc->rx_urb); +- usb_free_urb(catc->irq_urb); +- free_netdev(netdev); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto fail_free; + } + + /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */ +@@ -914,16 +910,21 @@ static int catc_probe(struct usb_interfa + usb_set_intfdata(intf, catc); + + SET_NETDEV_DEV(netdev, &intf->dev); +- if (register_netdev(netdev) != 0) { +- usb_set_intfdata(intf, NULL); +- usb_free_urb(catc->ctrl_urb); +- usb_free_urb(catc->tx_urb); +- usb_free_urb(catc->rx_urb); +- usb_free_urb(catc->irq_urb); +- free_netdev(netdev); +- return -EIO; +- } ++ ret = register_netdev(netdev); ++ if (ret) ++ goto fail_clear_intfdata; ++ + return 0; ++ ++fail_clear_intfdata: ++ usb_set_intfdata(intf, NULL); ++fail_free: ++ usb_free_urb(catc->ctrl_urb); ++ usb_free_urb(catc->tx_urb); ++ usb_free_urb(catc->rx_urb); ++ usb_free_urb(catc->irq_urb); ++ free_netdev(netdev); ++ return ret; + } + + static void catc_disconnect(struct usb_interface *intf) diff --git a/queue-3.18/catc-use-heap-buffer-for-memory-size-test.patch b/queue-3.18/catc-use-heap-buffer-for-memory-size-test.patch new file mode 100644 index 00000000000..2f914e854ac --- /dev/null +++ b/queue-3.18/catc-use-heap-buffer-for-memory-size-test.patch @@ -0,0 +1,73 @@ +From 2d6a0e9de03ee658a9adc3bfb2f0ca55dff1e478 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:57:04 +0000 +Subject: catc: Use heap buffer for memory size test + +From: Ben Hutchings + +commit 2d6a0e9de03ee658a9adc3bfb2f0ca55dff1e478 upstream. + +Allocating USB buffers on the stack is not portable, and no longer +works on x86_64 (with VMAP_STACK enabled as per default). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/catc.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/catc.c ++++ b/drivers/net/usb/catc.c +@@ -777,7 +777,7 @@ static int catc_probe(struct usb_interfa + struct net_device *netdev; + struct catc *catc; + u8 broadcast[ETH_ALEN]; +- int i, pktsz, ret; ++ int pktsz, ret; + + if (usb_set_interface(usbdev, + intf->altsetting->desc.bInterfaceNumber, 1)) { +@@ -841,15 +841,24 @@ static int catc_probe(struct usb_interfa + catc->irq_buf, 2, catc_irq_done, catc, 1); + + if (!catc->is_f5u011) { ++ u32 *buf; ++ int i; ++ + dev_dbg(dev, "Checking memory size\n"); + +- i = 0x12345678; +- catc_write_mem(catc, 0x7a80, &i, 4); +- i = 0x87654321; +- catc_write_mem(catc, 0xfa80, &i, 4); +- catc_read_mem(catc, 0x7a80, &i, 4); ++ buf = kmalloc(4, GFP_KERNEL); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto fail_free; ++ } ++ ++ *buf = 0x12345678; ++ catc_write_mem(catc, 0x7a80, buf, 4); ++ *buf = 0x87654321; ++ catc_write_mem(catc, 0xfa80, buf, 4); ++ catc_read_mem(catc, 0x7a80, buf, 4); + +- switch (i) { ++ switch (*buf) { + case 0x12345678: + catc_set_reg(catc, TxBufCount, 8); + catc_set_reg(catc, RxBufCount, 32); +@@ -864,6 +873,8 @@ static int catc_probe(struct usb_interfa + dev_dbg(dev, "32k Memory\n"); + break; + } ++ ++ kfree(buf); + + dev_dbg(dev, "Getting MAC from SEEROM.\n"); + diff --git a/queue-3.18/crypto-ahash-fix-einprogress-notification-callback.patch b/queue-3.18/crypto-ahash-fix-einprogress-notification-callback.patch new file mode 100644 index 00000000000..2a8550aed93 --- /dev/null +++ b/queue-3.18/crypto-ahash-fix-einprogress-notification-callback.patch @@ -0,0 +1,230 @@ +From ef0579b64e93188710d48667cb5e014926af9f1b Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Mon, 10 Apr 2017 17:27:57 +0800 +Subject: crypto: ahash - Fix EINPROGRESS notification callback + +From: Herbert Xu + +commit ef0579b64e93188710d48667cb5e014926af9f1b upstream. + +The ahash API modifies the request's callback function in order +to clean up after itself in some corner cases (unaligned final +and missing finup). + +When the request is complete ahash will restore the original +callback and everything is fine. However, when the request gets +an EBUSY on a full queue, an EINPROGRESS callback is made while +the request is still ongoing. + +In this case the ahash API will incorrectly call its own callback. + +This patch fixes the problem by creating a temporary request +object on the stack which is used to relay EINPROGRESS back to +the original completion function. + +This patch also adds code to preserve the original flags value. + +Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...") +Reported-by: Sabrina Dubroca +Tested-by: Sabrina Dubroca +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/ahash.c | 79 +++++++++++++++++++++++++---------------- + include/crypto/internal/hash.h | 10 +++++ + 2 files changed, 60 insertions(+), 29 deletions(-) + +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -31,6 +31,7 @@ struct ahash_request_priv { + crypto_completion_t complete; + void *data; + u8 *result; ++ u32 flags; + void *ubuf[] CRYPTO_MINALIGN_ATTR; + }; + +@@ -269,6 +270,8 @@ static int ahash_save_req(struct ahash_r + priv->result = req->result; + priv->complete = req->base.complete; + priv->data = req->base.data; ++ priv->flags = req->base.flags; ++ + /* + * WARNING: We do not backup req->priv here! The req->priv + * is for internal use of the Crypto API and the +@@ -283,38 +286,44 @@ static int ahash_save_req(struct ahash_r + return 0; + } + +-static void ahash_restore_req(struct ahash_request *req) ++static void ahash_restore_req(struct ahash_request *req, int err) + { + struct ahash_request_priv *priv = req->priv; + ++ if (!err) ++ memcpy(priv->result, req->result, ++ crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ + /* Restore the original crypto request. */ + req->result = priv->result; +- req->base.complete = priv->complete; +- req->base.data = priv->data; ++ ++ ahash_request_set_callback(req, priv->flags, ++ priv->complete, priv->data); + req->priv = NULL; + + /* Free the req->priv.priv from the ADJUSTED request. */ + kzfree(priv); + } + +-static void ahash_op_unaligned_finish(struct ahash_request *req, int err) ++static void ahash_notify_einprogress(struct ahash_request *req) + { + struct ahash_request_priv *priv = req->priv; ++ struct crypto_async_request oreq; + +- if (err == -EINPROGRESS) +- return; +- +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ oreq.data = priv->data; + +- ahash_restore_req(req); ++ priv->complete(&oreq, -EINPROGRESS); + } + + static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ + /* + * Restore the original request, see ahash_op_unaligned() for what + * goes where. +@@ -325,7 +334,7 @@ static void ahash_op_unaligned_done(stru + */ + + /* First copy req->result into req->priv.result */ +- ahash_op_unaligned_finish(areq, err); ++ ahash_restore_req(areq, err); + + /* Complete the ORIGINAL request. */ + areq->base.complete(&areq->base, err); +@@ -341,7 +350,12 @@ static int ahash_op_unaligned(struct aha + return err; + + err = op(req); +- ahash_op_unaligned_finish(req, err); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ ++ ahash_restore_req(req, err); + + return err; + } +@@ -376,25 +390,14 @@ int crypto_ahash_digest(struct ahash_req + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +-static void ahash_def_finup_finish2(struct ahash_request *req, int err) ++static void ahash_def_finup_done2(struct crypto_async_request *req, int err) + { +- struct ahash_request_priv *priv = req->priv; ++ struct ahash_request *areq = req->data; + + if (err == -EINPROGRESS) + return; + +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); +- +- ahash_restore_req(req); +-} +- +-static void ahash_def_finup_done2(struct crypto_async_request *req, int err) +-{ +- struct ahash_request *areq = req->data; +- +- ahash_def_finup_finish2(areq, err); ++ ahash_restore_req(areq, err); + + areq->base.complete(&areq->base, err); + } +@@ -405,11 +408,15 @@ static int ahash_def_finup_finish1(struc + goto out; + + req->base.complete = ahash_def_finup_done2; +- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = crypto_ahash_reqtfm(req)->final(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; + + out: +- ahash_def_finup_finish2(req, err); ++ ahash_restore_req(req, err); + return err; + } + +@@ -417,7 +424,16 @@ static void ahash_def_finup_done1(struct + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ ++ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = ahash_def_finup_finish1(areq, err); ++ if (areq->priv) ++ return; + + areq->base.complete(&areq->base, err); + } +@@ -432,6 +448,11 @@ static int ahash_def_finup(struct ahash_ + return err; + + err = tfm->update(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ + return ahash_def_finup_finish1(req, err); + } + +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -173,6 +173,16 @@ static inline struct ahash_instance *aha + return crypto_alloc_instance2(name, alg, ahash_instance_headroom()); + } + ++static inline void ahash_request_complete(struct ahash_request *req, int err) ++{ ++ req->base.complete(&req->base, err); ++} ++ ++static inline u32 ahash_request_flags(struct ahash_request *req) ++{ ++ return req->base.flags; ++} ++ + static inline struct crypto_ahash *crypto_spawn_ahash( + struct crypto_ahash_spawn *spawn) + { diff --git a/queue-3.18/dvb-usb-don-t-use-stack-for-firmware-load.patch b/queue-3.18/dvb-usb-don-t-use-stack-for-firmware-load.patch new file mode 100644 index 00000000000..15abf750869 --- /dev/null +++ b/queue-3.18/dvb-usb-don-t-use-stack-for-firmware-load.patch @@ -0,0 +1,136 @@ +From 43fab9793c1f44e665b4f98035a14942edf03ddc Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Tue, 24 Jan 2017 08:13:11 -0200 +Subject: [media] dvb-usb: don't use stack for firmware load + +From: Mauro Carvalho Chehab + +commit 43fab9793c1f44e665b4f98035a14942edf03ddc upstream. + +As reported by Marc Duponcheel , firmware load on +dvb-usb is using the stack, with is not allowed anymore on default +Kernel configurations: + +[ 1025.958836] dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)' in cold state, will try to load a firmware +[ 1025.958853] dvb-usb: downloading firmware from file 'dvb-usb-wt220u-zl0353-01.fw' +[ 1025.958855] dvb-usb: could not stop the USB controller CPU. +[ 1025.958856] dvb-usb: error while transferring firmware (transferred size: -11, block size: 3) +[ 1025.958856] dvb-usb: firmware download failed at 8 with -22 +[ 1025.958867] usbcore: registered new interface driver dvb_usb_dtt200u + +[ 2.789902] dvb-usb: downloading firmware from file 'dvb-usb-wt220u-zl0353-01.fw' +[ 2.789905] ------------[ cut here ]------------ +[ 2.789911] WARNING: CPU: 3 PID: 2196 at drivers/usb/core/hcd.c:1584 usb_hcd_map_urb_for_dma+0x430/0x560 [usbcore] +[ 2.789912] transfer buffer not dma capable +[ 2.789912] Modules linked in: btusb dvb_usb_dtt200u(+) dvb_usb_af9035(+) btrtl btbcm dvb_usb dvb_usb_v2 btintel dvb_core bluetooth rc_core rfkill x86_pkg_temp_thermal intel_powerclamp coretemp crc32_pclmul aesni_intel aes_x86_64 glue_helper lrw gf128mul ablk_helper cryptd drm_kms_helper syscopyarea sysfillrect pcspkr i2c_i801 sysimgblt fb_sys_fops drm i2c_smbus i2c_core r8169 lpc_ich mfd_core mii thermal fan rtc_cmos video button acpi_cpufreq processor snd_hda_codec_realtek snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd crc32c_intel ahci libahci libata xhci_pci ehci_pci xhci_hcd ehci_hcd usbcore usb_common dm_mirror dm_region_hash dm_log dm_mod +[ 2.789936] CPU: 3 PID: 2196 Comm: systemd-udevd Not tainted 4.9.0-gentoo #1 +[ 2.789937] Hardware name: ASUS All Series/H81I-PLUS, BIOS 0401 07/23/2013 +[ 2.789938] ffffc9000339b690 ffffffff812bd397 ffffc9000339b6e0 0000000000000000 +[ 2.789939] ffffc9000339b6d0 ffffffff81055c86 000006300339b6a0 ffff880116c0c000 +[ 2.789941] 0000000000000000 0000000000000000 0000000000000001 ffff880116c08000 +[ 2.789942] Call Trace: +[ 2.789945] [] dump_stack+0x4d/0x66 +[ 2.789947] [] __warn+0xc6/0xe0 +[ 2.789948] [] warn_slowpath_fmt+0x4a/0x50 +[ 2.789952] [] usb_hcd_map_urb_for_dma+0x430/0x560 [usbcore] +[ 2.789954] [] ? io_schedule_timeout+0xd8/0x110 +[ 2.789956] [] usb_hcd_submit_urb+0x9c/0x980 [usbcore] +[ 2.789958] [] ? copy_page_to_iter+0x14f/0x2b0 +[ 2.789960] [] ? pagecache_get_page+0x28/0x240 +[ 2.789962] [] ? touch_atime+0x20/0xa0 +[ 2.789964] [] usb_submit_urb+0x2c4/0x520 [usbcore] +[ 2.789967] [] usb_start_wait_urb+0x5a/0xe0 [usbcore] +[ 2.789969] [] usb_control_msg+0xbc/0xf0 [usbcore] +[ 2.789970] [] usb_cypress_writemem+0x3d/0x40 [dvb_usb] +[ 2.789972] [] usb_cypress_load_firmware+0x4f/0x130 [dvb_usb] +[ 2.789973] [] ? console_unlock+0x2fe/0x5d0 +[ 2.789974] [] ? vprintk_emit+0x27c/0x410 +[ 2.789975] [] ? vprintk_default+0x1a/0x20 +[ 2.789976] [] ? printk+0x43/0x4b +[ 2.789977] [] dvb_usb_download_firmware+0x60/0xd0 [dvb_usb] +[ 2.789979] [] dvb_usb_device_init+0x3d8/0x610 [dvb_usb] +[ 2.789981] [] dtt200u_usb_probe+0x92/0xd0 [dvb_usb_dtt200u] +[ 2.789984] [] usb_probe_interface+0xfc/0x270 [usbcore] +[ 2.789985] [] driver_probe_device+0x215/0x2d0 +[ 2.789986] [] __driver_attach+0x96/0xa0 +[ 2.789987] [] ? driver_probe_device+0x2d0/0x2d0 +[ 2.789988] [] bus_for_each_dev+0x5b/0x90 +[ 2.789989] [] driver_attach+0x19/0x20 +[ 2.789990] [] bus_add_driver+0x11c/0x220 +[ 2.789991] [] driver_register+0x5b/0xd0 +[ 2.789994] [] usb_register_driver+0x7c/0x130 [usbcore] +[ 2.789994] [] ? 0xffffffffa06a5000 +[ 2.789996] [] dtt200u_usb_driver_init+0x1e/0x20 [dvb_usb_dtt200u] +[ 2.789997] [] do_one_initcall+0x38/0x140 +[ 2.789998] [] ? __vunmap+0x7c/0xc0 +[ 2.789999] [] ? do_init_module+0x22/0x1d2 +[ 2.790000] [] do_init_module+0x5a/0x1d2 +[ 2.790002] [] load_module+0x1e11/0x2580 +[ 2.790003] [] ? show_taint+0x30/0x30 +[ 2.790004] [] ? kernel_read_file+0x100/0x190 +[ 2.790005] [] SyS_finit_module+0xba/0xc0 +[ 2.790007] [] entry_SYSCALL_64_fastpath+0x13/0x94 +[ 2.790008] ---[ end trace c78a74e78baec6fc ]--- + +So, allocate the structure dynamically. + +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 4.9: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +@@ -35,29 +35,34 @@ static int usb_cypress_writemem(struct u + + int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) + { +- struct hexline hx; ++ struct hexline *hx; + u8 reset; + int ret,pos=0; + ++ hx = kmalloc(sizeof(*hx), GFP_KERNEL); ++ if (!hx) ++ return -ENOMEM; ++ + /* stop the CPU */ + reset = 1; + if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) + err("could not stop the USB controller CPU."); + +- while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) { +- deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk); +- ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len); ++ while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) { ++ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n", hx->addr, hx->len, hx->chk); ++ ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len); + +- if (ret != hx.len) { ++ if (ret != hx->len) { + err("error while transferring firmware " + "(transferred size: %d, block size: %d)", +- ret,hx.len); ++ ret, hx->len); + ret = -EINVAL; + break; + } + } + if (ret < 0) { + err("firmware download failed at %d with %d",pos,ret); ++ kfree(hx); + return ret; + } + +@@ -71,6 +76,8 @@ int usb_cypress_load_firmware(struct usb + } else + ret = -EIO; + ++ kfree(hx); ++ + return ret; + } + EXPORT_SYMBOL(usb_cypress_load_firmware); diff --git a/queue-3.18/dvb-usb-firmware-don-t-do-dma-on-stack.patch b/queue-3.18/dvb-usb-firmware-don-t-do-dma-on-stack.patch new file mode 100644 index 00000000000..f9ed480de2b --- /dev/null +++ b/queue-3.18/dvb-usb-firmware-don-t-do-dma-on-stack.patch @@ -0,0 +1,80 @@ +From 67b0503db9c29b04eadfeede6bebbfe5ddad94ef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20Br=C3=BCns?= +Date: Sun, 12 Feb 2017 13:02:13 -0200 +Subject: [media] dvb-usb-firmware: don't do DMA on stack +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stefan Brüns + +commit 67b0503db9c29b04eadfeede6bebbfe5ddad94ef upstream. + +The buffer allocation for the firmware data was changed in +commit 43fab9793c1f ("[media] dvb-usb: don't use stack for firmware load") +but the same applies for the reset value. + +Fixes: 43fab9793c1f ("[media] dvb-usb: don't use stack for firmware load") +Signed-off-by: Stefan Brüns +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +@@ -36,16 +36,18 @@ static int usb_cypress_writemem(struct u + int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) + { + struct hexline *hx; +- u8 reset; +- int ret,pos=0; ++ u8 *buf; ++ int ret, pos = 0; ++ u16 cpu_cs_register = cypress[type].cpu_cs_register; + +- hx = kmalloc(sizeof(*hx), GFP_KERNEL); +- if (!hx) ++ buf = kmalloc(sizeof(*hx), GFP_KERNEL); ++ if (!buf) + return -ENOMEM; ++ hx = (struct hexline *)buf; + + /* stop the CPU */ +- reset = 1; +- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) ++ buf[0] = 1; ++ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) + err("could not stop the USB controller CPU."); + + while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) { +@@ -62,21 +64,21 @@ int usb_cypress_load_firmware(struct usb + } + if (ret < 0) { + err("firmware download failed at %d with %d",pos,ret); +- kfree(hx); ++ kfree(buf); + return ret; + } + + if (ret == 0) { + /* restart the CPU */ +- reset = 0; +- if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { ++ buf[0] = 0; ++ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) { + err("could not restart the USB controller CPU."); + ret = -EINVAL; + } + } else + ret = -EIO; + +- kfree(hx); ++ kfree(buf); + + return ret; + } diff --git a/queue-3.18/dvb-usb-v2-avoid-use-after-free.patch b/queue-3.18/dvb-usb-v2-avoid-use-after-free.patch new file mode 100644 index 00000000000..a4211c8bee4 --- /dev/null +++ b/queue-3.18/dvb-usb-v2-avoid-use-after-free.patch @@ -0,0 +1,60 @@ +From 005145378c9ad7575a01b6ce1ba118fb427f583a Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 2 Feb 2017 12:36:01 -0200 +Subject: [media] dvb-usb-v2: avoid use-after-free + +From: Arnd Bergmann + +commit 005145378c9ad7575a01b6ce1ba118fb427f583a upstream. + +I ran into a stack frame size warning because of the on-stack copy of +the USB device structure: + +drivers/media/usb/dvb-usb-v2/dvb_usb_core.c: In function 'dvb_usbv2_disconnect': +drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:1029:1: error: the frame size of 1104 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] + +Copying a device structure like this is wrong for a number of other reasons +too aside from the possible stack overflow. One of them is that the +dev_info() call will print the name of the device later, but AFAICT +we have only copied a pointer to the name earlier and the actual name +has been freed by the time it gets printed. + +This removes the on-stack copy of the device and instead copies the +device name using kstrdup(). I'm ignoring the possible failure here +as both printk() and kfree() are able to deal with NULL pointers. + +Signed-off-by: Arnd Bergmann +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c ++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +@@ -952,8 +952,9 @@ EXPORT_SYMBOL(dvb_usbv2_probe); + void dvb_usbv2_disconnect(struct usb_interface *intf) + { + struct dvb_usb_device *d = usb_get_intfdata(intf); +- const char *name = d->name; +- struct device dev = d->udev->dev; ++ const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL); ++ const char *drvname = d->name; ++ + dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + +@@ -962,8 +963,9 @@ void dvb_usbv2_disconnect(struct usb_int + + dvb_usbv2_exit(d); + +- dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", +- KBUILD_MODNAME, name); ++ pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n", ++ KBUILD_MODNAME, drvname, devname); ++ kfree(devname); + } + EXPORT_SYMBOL(dvb_usbv2_disconnect); + diff --git a/queue-3.18/mm-tighten-x86-dev-mem-with-zeroing-reads.patch b/queue-3.18/mm-tighten-x86-dev-mem-with-zeroing-reads.patch new file mode 100644 index 00000000000..ab910345961 --- /dev/null +++ b/queue-3.18/mm-tighten-x86-dev-mem-with-zeroing-reads.patch @@ -0,0 +1,209 @@ +From a4866aa812518ed1a37d8ea0c881dc946409de94 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 5 Apr 2017 09:39:08 -0700 +Subject: mm: Tighten x86 /dev/mem with zeroing reads + +From: Kees Cook + +commit a4866aa812518ed1a37d8ea0c881dc946409de94 upstream. + +Under CONFIG_STRICT_DEVMEM, reading System RAM through /dev/mem is +disallowed. However, on x86, the first 1MB was always allowed for BIOS +and similar things, regardless of it actually being System RAM. It was +possible for heap to end up getting allocated in low 1MB RAM, and then +read by things like x86info or dd, which would trip hardened usercopy: + +usercopy: kernel memory exposure attempt detected from ffff880000090000 (dma-kmalloc-256) (4096 bytes) + +This changes the x86 exception for the low 1MB by reading back zeros for +System RAM areas instead of blindly allowing them. More work is needed to +extend this to mmap, but currently mmap doesn't go through usercopy, so +hardened usercopy won't Oops the kernel. + +Reported-by: Tommi Rantala +Tested-by: Tommi Rantala +Signed-off-by: Kees Cook +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/init.c | 40 +++++++++++++++++++------ + drivers/char/mem.c | 82 +++++++++++++++++++++++++++++++++-------------------- + 2 files changed, 82 insertions(+), 40 deletions(-) + +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -581,20 +581,40 @@ void __init init_mem_mapping(void) + * is valid. The argument is a physical page number. + * + * +- * On x86, access has to be given to the first megabyte of ram because that area +- * contains bios code and data regions used by X and dosemu and similar apps. +- * Access has to be given to non-kernel-ram areas as well, these contain the PCI +- * mmio resources as well as potential bios/acpi data regions. ++ * On x86, access has to be given to the first megabyte of RAM because that ++ * area traditionally contains BIOS code and data regions used by X, dosemu, ++ * and similar apps. Since they map the entire memory range, the whole range ++ * must be allowed (for mapping), but any areas that would otherwise be ++ * disallowed are flagged as being "zero filled" instead of rejected. ++ * Access has to be given to non-kernel-ram areas as well, these contain the ++ * PCI mmio resources as well as potential bios/acpi data regions. + */ + int devmem_is_allowed(unsigned long pagenr) + { +- if (pagenr < 256) +- return 1; +- if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) ++ if (page_is_ram(pagenr)) { ++ /* ++ * For disallowed memory regions in the low 1MB range, ++ * request that the page be shown as all zeros. ++ */ ++ if (pagenr < 256) ++ return 2; ++ + return 0; +- if (!page_is_ram(pagenr)) +- return 1; +- return 0; ++ } ++ ++ /* ++ * This must follow RAM test, since System RAM is considered a ++ * restricted resource under CONFIG_STRICT_IOMEM. ++ */ ++ if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) { ++ /* Low 1MB bypasses iomem restrictions. */ ++ if (pagenr < 256) ++ return 1; ++ ++ return 0; ++ } ++ ++ return 1; + } + + void free_init_pages(char *what, unsigned long begin, unsigned long end) +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -59,6 +59,10 @@ static inline int valid_mmap_phys_addr_r + #endif + + #ifdef CONFIG_STRICT_DEVMEM ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return devmem_is_allowed(pfn); ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + u64 from = ((u64)pfn) << PAGE_SHIFT; +@@ -78,6 +82,10 @@ static inline int range_is_allowed(unsig + return 1; + } + #else ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return 1; ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + return 1; +@@ -122,23 +130,31 @@ static ssize_t read_mem(struct file *fil + + while (count > 0) { + unsigned long remaining; ++ int allowed; + + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, count)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; ++ if (allowed == 2) { ++ /* Show zeros for restricted memory. */ ++ remaining = clear_user(buf, sz); ++ } else { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) ++ return -EFAULT; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) +- return -EFAULT; ++ remaining = copy_to_user(buf, ptr, sz); ++ ++ unxlate_dev_mem_ptr(p, ptr); ++ } + +- remaining = copy_to_user(buf, ptr, sz); +- unxlate_dev_mem_ptr(p, ptr); + if (remaining) + return -EFAULT; + +@@ -181,30 +197,36 @@ static ssize_t write_mem(struct file *fi + #endif + + while (count > 0) { ++ int allowed; ++ + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, sz)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) { +- if (written) +- break; +- return -EFAULT; +- } ++ /* Skip actual writing when a page is marked as restricted. */ ++ if (allowed == 1) { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) { ++ if (written) ++ break; ++ return -EFAULT; ++ } + +- copied = copy_from_user(ptr, buf, sz); +- unxlate_dev_mem_ptr(p, ptr); +- if (copied) { +- written += sz - copied; +- if (written) +- break; +- return -EFAULT; ++ copied = copy_from_user(ptr, buf, sz); ++ unxlate_dev_mem_ptr(p, ptr); ++ if (copied) { ++ written += sz - copied; ++ if (written) ++ break; ++ return -EFAULT; ++ } + } + + buf += sz; diff --git a/queue-3.18/pegasus-use-heap-buffers-for-all-register-access.patch b/queue-3.18/pegasus-use-heap-buffers-for-all-register-access.patch new file mode 100644 index 00000000000..666c3659195 --- /dev/null +++ b/queue-3.18/pegasus-use-heap-buffers-for-all-register-access.patch @@ -0,0 +1,96 @@ +From 5593523f968bc86d42a035c6df47d5e0979b5ace Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:56:03 +0000 +Subject: pegasus: Use heap buffers for all register access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ben Hutchings + +commit 5593523f968bc86d42a035c6df47d5e0979b5ace upstream. + +Allocating USB buffers on the stack is not portable, and no longer +works on x86_64 (with VMAP_STACK enabled as per default). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +References: https://bugs.debian.org/852556 +Reported-by: Lisandro Damián Nicanor Pérez Meyer +Tested-by: Lisandro Damián Nicanor Pérez Meyer +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/pegasus.c | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -126,40 +126,61 @@ static void async_ctrl_callback(struct u + + static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) + { ++ u8 *buf; + int ret; + ++ buf = kmalloc(size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, +- indx, data, size, 1000); ++ indx, buf, size, 1000); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ else if (ret <= size) ++ memcpy(data, buf, ret); ++ kfree(buf); + return ret; + } + +-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) ++static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, ++ const void *data) + { ++ u8 *buf; + int ret; + ++ buf = kmemdup(data, size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, +- indx, data, size, 100); ++ indx, buf, size, 100); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ kfree(buf); + return ret; + } + + static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) + { ++ u8 *buf; + int ret; + ++ buf = kmemdup(&data, 1, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, +- indx, &data, 1, 1000); ++ indx, buf, 1, 1000); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ kfree(buf); + return ret; + } + diff --git a/queue-3.18/platform-x86-acer-wmi-setup-accelerometer-when-machine-has-appropriate-notify-event.patch b/queue-3.18/platform-x86-acer-wmi-setup-accelerometer-when-machine-has-appropriate-notify-event.patch new file mode 100644 index 00000000000..13cd5a8c616 --- /dev/null +++ b/queue-3.18/platform-x86-acer-wmi-setup-accelerometer-when-machine-has-appropriate-notify-event.patch @@ -0,0 +1,84 @@ +From 98d610c3739ac354319a6590b915f4624d9151e6 Mon Sep 17 00:00:00 2001 +From: "Lee, Chun-Yi" +Date: Thu, 3 Nov 2016 08:18:52 +0800 +Subject: platform/x86: acer-wmi: setup accelerometer when machine has appropriate notify event +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lee, Chun-Yi + +commit 98d610c3739ac354319a6590b915f4624d9151e6 upstream. + +The accelerometer event relies on the ACERWMID_EVENT_GUID notify. +So, this patch changes the codes to setup accelerometer input device +when detected ACERWMID_EVENT_GUID. It avoids that the accel input +device created on every Acer machines. + +In addition, patch adds a clearly parsing logic of accelerometer hid +to acer_wmi_get_handle_cb callback function. It is positive matching +the "SENR" name with "BST0001" device to avoid non-supported hardware. + +Reported-by: Bjørn Mork +Cc: Darren Hart +Signed-off-by: Lee, Chun-Yi +[andy: slightly massage commit message] +Signed-off-by: Andy Shevchenko +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/acer-wmi.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -1867,11 +1867,24 @@ static int __init acer_wmi_enable_lm(voi + return status; + } + ++#define ACER_WMID_ACCEL_HID "BST0001" ++ + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, + void *ctx, void **retval) + { ++ struct acpi_device *dev; ++ ++ if (!strcmp(ctx, "SENR")) { ++ if (acpi_bus_get_device(ah, &dev)) ++ return AE_OK; ++ if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) ++ return AE_OK; ++ } else ++ return AE_OK; ++ + *(acpi_handle *)retval = ah; +- return AE_OK; ++ ++ return AE_CTRL_TERMINATE; + } + + static int __init acer_wmi_get_handle(const char *name, const char *prop, +@@ -1898,7 +1911,7 @@ static int __init acer_wmi_accel_setup(v + { + int err; + +- err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); ++ err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle); + if (err) + return err; + +@@ -2274,10 +2287,11 @@ static int __init acer_wmi_init(void) + err = acer_wmi_input_setup(); + if (err) + return err; ++ err = acer_wmi_accel_setup(); ++ if (err) ++ return err; + } + +- acer_wmi_accel_setup(); +- + err = platform_driver_register(&acer_platform_driver); + if (err) { + pr_err("Unable to register platform driver\n"); diff --git a/queue-3.18/powerpc-disable-hfscr-if-tm-is-not-supported.patch b/queue-3.18/powerpc-disable-hfscr-if-tm-is-not-supported.patch new file mode 100644 index 00000000000..8d1b6ea4fbf --- /dev/null +++ b/queue-3.18/powerpc-disable-hfscr-if-tm-is-not-supported.patch @@ -0,0 +1,60 @@ +From 7ed23e1bae8bf7e37fd555066550a00b95a3a98b Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Mon, 20 Mar 2017 17:49:03 +1100 +Subject: powerpc: Disable HFSCR[TM] if TM is not supported + +From: Benjamin Herrenschmidt + +commit 7ed23e1bae8bf7e37fd555066550a00b95a3a98b upstream. + +On Power8 & Power9 the early CPU inititialisation in __init_HFSCR() +turns on HFSCR[TM] (Hypervisor Facility Status and Control Register +[Transactional Memory]), but that doesn't take into account that TM +might be disabled by CPU features, or disabled by the kernel being built +with CONFIG_PPC_TRANSACTIONAL_MEM=n. + +So later in boot, when we have setup the CPU features, clear HSCR[TM] if +the TM CPU feature has been disabled. We use CPU_FTR_TM_COMP to account +for the CONFIG_PPC_TRANSACTIONAL_MEM=n case. + +Without this a KVM guest might try use TM, even if told not to, and +cause an oops in the host kernel. Typically the oops is seen in +__kvmppc_vcore_entry() and may or may not be fatal to the host, but is +always bad news. + +In practice all shipping CPU revisions do support TM, and all host +kernels we are aware of build with TM support enabled, so no one should +actually be able to hit this in the wild. + +Fixes: 2a3563b023e5 ("powerpc: Setup in HFSCR for POWER8") +Cc: stable@vger.kernel.org # v3.10+ +Signed-off-by: Benjamin Herrenschmidt +Tested-by: Sam Bobroff +[mpe: Rewrite change log with input from Sam, add Fixes/stable] +Signed-off-by: Michael Ellerman +[sb: Backported to linux-4.4.y: adjusted context] +Signed-off-by: Sam Bobroff +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/setup_64.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -211,6 +211,15 @@ static void cpu_ready_for_interrupts(voi + unsigned long lpcr = mfspr(SPRN_LPCR); + mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3); + } ++ ++ /* ++ * Fixup HFSCR:TM based on CPU features. The bit is set by our ++ * early asm init because at that point we haven't updated our ++ * CPU features from firmware and device-tree. Here we have, ++ * so let's do it. ++ */ ++ if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP)) ++ mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); + } + + /* diff --git a/queue-3.18/rtc-tegra-implement-clock-handling.patch b/queue-3.18/rtc-tegra-implement-clock-handling.patch new file mode 100644 index 00000000000..02775c81703 --- /dev/null +++ b/queue-3.18/rtc-tegra-implement-clock-handling.patch @@ -0,0 +1,125 @@ +From 5fa4086987506b2ab8c92f8f99f2295db9918856 Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Thu, 12 Jan 2017 17:07:43 +0100 +Subject: rtc: tegra: Implement clock handling + +From: Thierry Reding + +commit 5fa4086987506b2ab8c92f8f99f2295db9918856 upstream. + +Accessing the registers of the RTC block on Tegra requires the module +clock to be enabled. This only works because the RTC module clock will +be enabled by default during early boot. However, because the clock is +unused, the CCF will disable it at late_init time. This causes the RTC +to become unusable afterwards. This can easily be reproduced by trying +to use the RTC: + + $ hwclock --rtc /dev/rtc1 + +This will hang the system. I ran into this by following up on a report +by Martin Michlmayr that reboot wasn't working on Tegra210 systems. It +turns out that the rtc-tegra driver's ->shutdown() implementation will +hang the CPU, because of the disabled clock, before the system can be +rebooted. + +What confused me for a while is that the same driver is used on prior +Tegra generations where the hang can not be observed. However, as Peter +De Schrijver pointed out, this is because on 32-bit Tegra chips the RTC +clock is enabled by the tegra20_timer.c clocksource driver, which uses +the RTC to provide a persistent clock. This code is never enabled on +64-bit Tegra because the persistent clock infrastructure does not exist +on 64-bit ARM. + +The proper fix for this is to add proper clock handling to the RTC +driver in order to ensure that the clock is enabled when the driver +requires it. All device trees contain the clock already, therefore +no additional changes are required. + +Reported-by: Martin Michlmayr +Acked-By Peter De Schrijver +Signed-off-by: Thierry Reding +Signed-off-by: Alexandre Belloni +[bwh: Backported to 4.9: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rtc/rtc-tegra.c | 28 ++++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-tegra.c ++++ b/drivers/rtc/rtc-tegra.c +@@ -18,6 +18,7 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + #include ++#include + #include + #include + #include +@@ -59,6 +60,7 @@ struct tegra_rtc_info { + struct platform_device *pdev; + struct rtc_device *rtc_dev; + void __iomem *rtc_base; /* NULL if not initialized. */ ++ struct clk *clk; + int tegra_rtc_irq; /* alarm and periodic irq */ + spinlock_t tegra_rtc_lock; + }; +@@ -330,6 +332,14 @@ static int __init tegra_rtc_probe(struct + if (info->tegra_rtc_irq <= 0) + return -EBUSY; + ++ info->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(info->clk)) ++ return PTR_ERR(info->clk); ++ ++ ret = clk_prepare_enable(info->clk); ++ if (ret < 0) ++ return ret; ++ + /* set context info. */ + info->pdev = pdev; + spin_lock_init(&info->tegra_rtc_lock); +@@ -350,7 +360,7 @@ static int __init tegra_rtc_probe(struct + ret = PTR_ERR(info->rtc_dev); + dev_err(&pdev->dev, "Unable to register device (err=%d).\n", + ret); +- return ret; ++ goto disable_clk; + } + + ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, +@@ -360,12 +370,25 @@ static int __init tegra_rtc_probe(struct + dev_err(&pdev->dev, + "Unable to request interrupt for device (err=%d).\n", + ret); +- return ret; ++ goto disable_clk; + } + + dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); + + return 0; ++ ++disable_clk: ++ clk_disable_unprepare(info->clk); ++ return ret; ++} ++ ++static int tegra_rtc_remove(struct platform_device *pdev) ++{ ++ struct tegra_rtc_info *info = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(info->clk); ++ ++ return 0; + } + + #ifdef CONFIG_PM_SLEEP +@@ -417,6 +440,7 @@ static void tegra_rtc_shutdown(struct pl + + MODULE_ALIAS("platform:tegra_rtc"); + static struct platform_driver tegra_rtc_driver = { ++ .remove = tegra_rtc_remove, + .shutdown = tegra_rtc_shutdown, + .driver = { + .name = "tegra_rtc", diff --git a/queue-3.18/rtl8150-use-heap-buffers-for-all-register-access.patch b/queue-3.18/rtl8150-use-heap-buffers-for-all-register-access.patch new file mode 100644 index 00000000000..7b59f2b9cc3 --- /dev/null +++ b/queue-3.18/rtl8150-use-heap-buffers-for-all-register-access.patch @@ -0,0 +1,68 @@ +From 7926aff5c57b577ab0f43364ff0c59d968f6a414 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:56:32 +0000 +Subject: rtl8150: Use heap buffers for all register access + +From: Ben Hutchings + +commit 7926aff5c57b577ab0f43364ff0c59d968f6a414 upstream. + +Allocating USB buffers on the stack is not portable, and no longer +works on x86_64 (with VMAP_STACK enabled as per default). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/rtl8150.c | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/rtl8150.c ++++ b/drivers/net/usb/rtl8150.c +@@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8 + */ + static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) + { +- return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), +- RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, +- indx, 0, data, size, 500); ++ void *buf; ++ int ret; ++ ++ buf = kmalloc(size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), ++ RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, ++ indx, 0, buf, size, 500); ++ if (ret > 0 && ret <= size) ++ memcpy(data, buf, ret); ++ kfree(buf); ++ return ret; + } + +-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) ++static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) + { +- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), +- RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, +- indx, 0, data, size, 500); ++ void *buf; ++ int ret; ++ ++ buf = kmemdup(data, size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), ++ RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, ++ indx, 0, buf, size, 500); ++ kfree(buf); ++ return ret; + } + + static void async_set_reg_cb(struct urb *urb) diff --git a/queue-3.18/series b/queue-3.18/series index 71f8540d676..00f9bb71183 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -48,3 +48,16 @@ xen-acpi-upload-pm-state-from-init-domain-to-xen.patch crypto-caam-fix-rng-deinstantiation-error-checking.patch tty-serial-atmel-fix-race-condition-tx-dma.patch zram-do-not-use-copy_page-with-non-page-aligned-address.patch +powerpc-disable-hfscr-if-tm-is-not-supported.patch +crypto-ahash-fix-einprogress-notification-callback.patch +dvb-usb-v2-avoid-use-after-free.patch +platform-x86-acer-wmi-setup-accelerometer-when-machine-has-appropriate-notify-event.patch +rtc-tegra-implement-clock-handling.patch +mm-tighten-x86-dev-mem-with-zeroing-reads.patch +dvb-usb-don-t-use-stack-for-firmware-load.patch +dvb-usb-firmware-don-t-do-dma-on-stack.patch +virtio-console-avoid-dma-from-stack.patch +pegasus-use-heap-buffers-for-all-register-access.patch +rtl8150-use-heap-buffers-for-all-register-access.patch +catc-combine-failure-cleanup-code-in-catc_probe.patch +catc-use-heap-buffer-for-memory-size-test.patch diff --git a/queue-3.18/virtio-console-avoid-dma-from-stack.patch b/queue-3.18/virtio-console-avoid-dma-from-stack.patch new file mode 100644 index 00000000000..46f713ed78b --- /dev/null +++ b/queue-3.18/virtio-console-avoid-dma-from-stack.patch @@ -0,0 +1,52 @@ +From c4baad50297d84bde1a7ad45e50c73adae4a2192 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Wed, 1 Feb 2017 00:02:27 -0800 +Subject: virtio-console: avoid DMA from stack + +From: Omar Sandoval + +commit c4baad50297d84bde1a7ad45e50c73adae4a2192 upstream. + +put_chars() stuffs the buffer it gets into an sg, but that buffer may be +on the stack. This breaks with CONFIG_VMAP_STACK=y (for me, it +manifested as printks getting turned into NUL bytes). + +Signed-off-by: Omar Sandoval +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Amit Shah +Cc: Ben Hutchings +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/virtio_console.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1129,6 +1129,8 @@ static int put_chars(u32 vtermno, const + { + struct port *port; + struct scatterlist sg[1]; ++ void *data; ++ int ret; + + if (unlikely(early_put_chars)) + return early_put_chars(vtermno, buf, count); +@@ -1137,8 +1139,14 @@ static int put_chars(u32 vtermno, const + if (!port) + return -EPIPE; + +- sg_init_one(sg, buf, count); +- return __send_to_port(port, sg, 1, count, (void *)buf, false); ++ data = kmemdup(buf, count, GFP_ATOMIC); ++ if (!data) ++ return -ENOMEM; ++ ++ sg_init_one(sg, data, count); ++ ret = __send_to_port(port, sg, 1, count, data, false); ++ kfree(data); ++ return ret; + } + + /*