--- /dev/null
+From 21ffceda1c8b3807615c40d440d7815e0c85d366 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 2 Jan 2018 14:01:34 -0500
+Subject: alpha: fix crash if pthread_create races with signal delivery
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 21ffceda1c8b3807615c40d440d7815e0c85d366 upstream.
+
+On alpha, a process will crash if it attempts to start a thread and a
+signal is delivered at the same time. The crash can be reproduced with
+this program: https://cygwin.com/ml/cygwin/2014-11/msg00473.html
+
+The reason for the crash is this:
+* we call the clone syscall
+* we go to the function copy_process
+* copy process calls copy_thread_tls, it is a wrapper around copy_thread
+* copy_thread sets the tls pointer: childti->pcb.unique = regs->r20
+* copy_thread sets regs->r20 to zero
+* we go back to copy_process
+* copy process checks "if (signal_pending(current))" and returns
+ -ERESTARTNOINTR
+* the clone syscall is restarted, but this time, regs->r20 is zero, so
+ the new thread is created with zero tls pointer
+* the new thread crashes in start_thread when attempting to access tls
+
+The comment in the code says that setting the register r20 is some
+compatibility with OSF/1. But OSF/1 doesn't use the CLONE_SETTLS flag, so
+we don't have to zero r20 if CLONE_SETTLS is set. This patch fixes the bug
+by zeroing regs->r20 only if CLONE_SETTLS is not set.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Matt Turner <mattst88@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/alpha/kernel/process.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/alpha/kernel/process.c
++++ b/arch/alpha/kernel/process.c
+@@ -273,12 +273,13 @@ copy_thread(unsigned long clone_flags, u
+ application calling fork. */
+ if (clone_flags & CLONE_SETTLS)
+ childti->pcb.unique = regs->r20;
++ else
++ regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
+ childti->pcb.usp = usp ?: rdusp();
+ *childregs = *regs;
+ childregs->r0 = 0;
+ childregs->r19 = 0;
+ childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
+- regs->r20 = 0;
+ stack = ((struct switch_stack *) regs) - 1;
+ *childstack = *stack;
+ childstack->r26 = (unsigned long) ret_from_fork;
--- /dev/null
+From 55fc633c41a08ce9244ff5f528f420b16b1e04d6 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 2 Jan 2018 13:59:54 -0500
+Subject: alpha: fix reboot on Avanti platform
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 55fc633c41a08ce9244ff5f528f420b16b1e04d6 upstream.
+
+We need to define NEED_SRM_SAVE_RESTORE on the Avanti, otherwise we get
+machine check exception when attempting to reboot the machine.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Matt Turner <mattst88@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/alpha/kernel/pci_impl.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/alpha/kernel/pci_impl.h
++++ b/arch/alpha/kernel/pci_impl.h
+@@ -143,7 +143,8 @@ struct pci_iommu_arena
+ };
+
+ #if defined(CONFIG_ALPHA_SRM) && \
+- (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
++ (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \
++ defined(CONFIG_ALPHA_AVANTI))
+ # define NEED_SRM_SAVE_RESTORE
+ #else
+ # undef NEED_SRM_SAVE_RESTORE
--- /dev/null
+From 20e8175d246e9f9deb377f2784b3e7dfb2ad3e86 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 6 Feb 2018 17:56:06 +0000
+Subject: arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit 20e8175d246e9f9deb377f2784b3e7dfb2ad3e86 upstream.
+
+KVM doesn't follow the SMCCC when it comes to unimplemented calls,
+and inject an UNDEF instead of returning an error. Since firmware
+calls are now used for security mitigation, they are becoming more
+common, and the undef is counter productive.
+
+Instead, let's follow the SMCCC which states that -1 must be returned
+to the caller when getting an unknown function number.
+
+Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/kvm/handle_exit.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/kvm/handle_exit.c
++++ b/arch/arm/kvm/handle_exit.c
+@@ -45,7 +45,7 @@ static int handle_hvc(struct kvm_vcpu *v
+
+ ret = kvm_psci_call(vcpu);
+ if (ret < 0) {
+- kvm_inject_undefined(vcpu);
++ vcpu_set_reg(vcpu, 0, ~0UL);
+ return 1;
+ }
+
+@@ -54,7 +54,16 @@ static int handle_hvc(struct kvm_vcpu *v
+
+ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+ {
+- kvm_inject_undefined(vcpu);
++ /*
++ * "If an SMC instruction executed at Non-secure EL1 is
++ * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
++ * Trap exception, not a Secure Monitor Call exception [...]"
++ *
++ * We need to advance the PC after the trap, as it would
++ * otherwise return to the same address...
++ */
++ vcpu_set_reg(vcpu, 0, ~0UL);
++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+ return 1;
+ }
+
--- /dev/null
+From c2856ae2f315d754a0b6a268e4c6745b332b42e7 Mon Sep 17 00:00:00 2001
+From: Ming Lei <ming.lei@redhat.com>
+Date: Sat, 6 Jan 2018 16:27:37 +0800
+Subject: blk-mq: quiesce queue before freeing queue
+
+From: Ming Lei <ming.lei@redhat.com>
+
+commit c2856ae2f315d754a0b6a268e4c6745b332b42e7 upstream.
+
+After queue is frozen, dispatch still may happen, for example:
+
+1) requests are submitted from several contexts
+2) requests from all these contexts are inserted to queue, but may dispatch
+to LLD in one of these paths, but other paths sill need to move on even all
+these requests are completed(that means blk_mq_freeze_queue_wait() returns
+at that time)
+3) dispatch after queue freezing still moves on and causes use-after-free,
+because request queue is freed
+
+This patch quiesces queue after it is frozen, and makes sure all
+in-progress dispatch are completed.
+
+This patch fixes the following kernel crash when running heavy IOs vs.
+deleting device:
+
+[ 36.719251] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
+[ 36.720318] IP: kyber_has_work+0x14/0x40
+[ 36.720847] PGD 254bf5067 P4D 254bf5067 PUD 255e6a067 PMD 0
+[ 36.721584] Oops: 0000 [#1] PREEMPT SMP
+[ 36.722105] Dumping ftrace buffer:
+[ 36.722570] (ftrace buffer empty)
+[ 36.723057] Modules linked in: scsi_debug ebtable_filter ebtables ip6table_filter ip6_tables tcm_loop iscsi_target_mod target_core_file target_core_iblock target_core_pscsi target_core_mod xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack libcrc32c bridge stp llc fuse iptable_filter ip_tables sd_mod sg btrfs xor zstd_decompress zstd_compress xxhash raid6_pq mptsas mptscsih bcache crc32c_intel ahci mptbase libahci serio_raw scsi_transport_sas nvme libata shpchp lpc_ich virtio_scsi nvme_core binfmt_misc dm_mod iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi null_blk configs
+[ 36.733438] CPU: 2 PID: 2374 Comm: fio Not tainted 4.15.0-rc2.blk_mq_quiesce+ #714
+[ 36.735143] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.9.3-1.fc25 04/01/2014
+[ 36.736688] RIP: 0010:kyber_has_work+0x14/0x40
+[ 36.737515] RSP: 0018:ffffc9000209bca0 EFLAGS: 00010202
+[ 36.738431] RAX: 0000000000000008 RBX: ffff88025578bfc8 RCX: ffff880257bf4ed0
+[ 36.739581] RDX: 0000000000000038 RSI: ffffffff81a98c6d RDI: ffff88025578bfc8
+[ 36.740730] RBP: ffff880253cebfc8 R08: ffffc9000209bda0 R09: ffff8802554f3480
+[ 36.741885] R10: ffffc9000209be60 R11: ffff880263f72538 R12: ffff88025573e9e8
+[ 36.743036] R13: ffff88025578bfd0 R14: 0000000000000001 R15: 0000000000000000
+[ 36.744189] FS: 00007f9b9bee67c0(0000) GS:ffff88027fc80000(0000) knlGS:0000000000000000
+[ 36.746617] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 36.748483] CR2: 0000000000000008 CR3: 0000000254bf4001 CR4: 00000000003606e0
+[ 36.750164] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 36.751455] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 36.752796] Call Trace:
+[ 36.753992] blk_mq_do_dispatch_sched+0x7f/0xe0
+[ 36.755110] blk_mq_sched_dispatch_requests+0x119/0x190
+[ 36.756179] __blk_mq_run_hw_queue+0x83/0x90
+[ 36.757144] __blk_mq_delay_run_hw_queue+0xaf/0x110
+[ 36.758046] blk_mq_run_hw_queue+0x24/0x70
+[ 36.758845] blk_mq_flush_plug_list+0x1e7/0x270
+[ 36.759676] blk_flush_plug_list+0xd6/0x240
+[ 36.760463] blk_finish_plug+0x27/0x40
+[ 36.761195] do_io_submit+0x19b/0x780
+[ 36.761921] ? entry_SYSCALL_64_fastpath+0x1a/0x7d
+[ 36.762788] entry_SYSCALL_64_fastpath+0x1a/0x7d
+[ 36.763639] RIP: 0033:0x7f9b9699f697
+[ 36.764352] RSP: 002b:00007ffc10f991b8 EFLAGS: 00000206 ORIG_RAX: 00000000000000d1
+[ 36.765773] RAX: ffffffffffffffda RBX: 00000000008f6f00 RCX: 00007f9b9699f697
+[ 36.766965] RDX: 0000000000a5e6c0 RSI: 0000000000000001 RDI: 00007f9b8462a000
+[ 36.768377] RBP: 0000000000000000 R08: 0000000000000001 R09: 00000000008f6420
+[ 36.769649] R10: 00007f9b846e5000 R11: 0000000000000206 R12: 00007f9b795d6a70
+[ 36.770807] R13: 00007f9b795e4140 R14: 00007f9b795e3fe0 R15: 0000000100000000
+[ 36.771955] Code: 83 c7 10 e9 3f 68 d1 ff 0f 1f 44 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 8b 97 b0 00 00 00 48 8d 42 08 48 83 c2 38 <48> 3b 00 74 06 b8 01 00 00 00 c3 48 3b 40 08 75 f4 48 83 c0 10
+[ 36.775004] RIP: kyber_has_work+0x14/0x40 RSP: ffffc9000209bca0
+[ 36.776012] CR2: 0000000000000008
+[ 36.776690] ---[ end trace 4045cbce364ff2a4 ]---
+[ 36.777527] Kernel panic - not syncing: Fatal exception
+[ 36.778526] Dumping ftrace buffer:
+[ 36.779313] (ftrace buffer empty)
+[ 36.780081] Kernel Offset: disabled
+[ 36.780877] ---[ end Kernel panic - not syncing: Fatal exception
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Tested-by: Yi Zhang <yi.zhang@redhat.com>
+Signed-off-by: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/blk-core.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -579,6 +579,15 @@ void blk_cleanup_queue(struct request_qu
+ queue_flag_set(QUEUE_FLAG_DEAD, q);
+ spin_unlock_irq(lock);
+
++ /*
++ * make sure all in-progress dispatch are completed because
++ * blk_freeze_queue() can only complete all requests, and
++ * dispatch may still be in-progress since we dispatch requests
++ * from more than one contexts
++ */
++ if (q->mq_ops)
++ blk_mq_quiesce_queue(q);
++
+ /* for synchronous bio-based driver finish in-flight integrity i/o */
+ blk_flush_integrity();
+
--- /dev/null
+From b4cdaba274247c9c841c6a682c08fa91fb3aa549 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 29 Nov 2017 20:29:07 +0100
+Subject: Bluetooth: btsdio: Do not bind to non-removable BCM43341
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit b4cdaba274247c9c841c6a682c08fa91fb3aa549 upstream.
+
+BCM43341 devices soldered onto the PCB (non-removable) always (AFAICT)
+use an UART connection for bluetooth. But they also advertise btsdio
+support on their 3th sdio function, this causes 2 problems:
+
+1) A non functioning BT HCI getting registered
+
+2) Since the btsdio driver does not have suspend/resume callbacks,
+mmc_sdio_pre_suspend will return -ENOSYS, causing mmc_pm_notify()
+to react as if the SDIO-card is removed and since the slot is
+marked as non-removable it will never get detected as inserted again.
+Which results in wifi no longer working after a suspend/resume.
+
+This commit fixes both by making btsdio ignore BCM43341 devices
+when connected to a slot which is marked non-removable.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/bluetooth/btsdio.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/bluetooth/btsdio.c
++++ b/drivers/bluetooth/btsdio.c
+@@ -31,6 +31,7 @@
+ #include <linux/errno.h>
+ #include <linux/skbuff.h>
+
++#include <linux/mmc/host.h>
+ #include <linux/mmc/sdio_ids.h>
+ #include <linux/mmc/sdio_func.h>
+
+@@ -291,6 +292,14 @@ static int btsdio_probe(struct sdio_func
+ tuple = tuple->next;
+ }
+
++ /* BCM43341 devices soldered onto the PCB (non-removable) use an
++ * uart connection for bluetooth, ignore the BT SDIO interface.
++ */
++ if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
++ func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
++ !mmc_card_is_removable(func->card->host))
++ return -ENODEV;
++
+ data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
--- /dev/null
+From 61f5acea8737d9b717fcc22bb6679924f3c82b98 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 8 Jan 2018 10:44:16 +0100
+Subject: Bluetooth: btusb: Restore QCA Rome suspend/resume fix with a "rewritten" version
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 61f5acea8737d9b717fcc22bb6679924f3c82b98 upstream.
+
+Commit 7d06d5895c15 ("Revert "Bluetooth: btusb: fix QCA...suspend/resume"")
+removed the setting of the BTUSB_RESET_RESUME quirk for QCA Rome devices,
+instead favoring adding USB_QUIRK_RESET_RESUME quirks in usb/core/quirks.c.
+
+This was done because the DIY BTUSB_RESET_RESUME reset-resume handling
+has several issues (see the original commit message). An added advantage
+of moving over to the USB-core reset-resume handling is that it also
+disables autosuspend for these devices, which is similarly broken on these.
+
+But there are 2 issues with this approach:
+1) It leaves the broken DIY BTUSB_RESET_RESUME code in place for Realtek
+ devices.
+2) Sofar only 2 of the 10 QCA devices known to the btusb code have been
+ added to usb/core/quirks.c and if we fix the Realtek case the same way
+ we need to add an additional 14 entries. So in essence we need to
+ duplicate a large part of the usb_device_id table in btusb.c in
+ usb/core/quirks.c and manually keep them in sync.
+
+This commit instead restores setting a reset-resume quirk for QCA devices
+in the btusb.c code, avoiding the duplicate usb_device_id table problem.
+
+This commit avoids the problems with the original DIY BTUSB_RESET_RESUME
+code by simply setting the USB_QUIRK_RESET_RESUME quirk directly on the
+usb_device.
+
+This commit also moves the BTUSB_REALTEK case over to directly setting the
+USB_QUIRK_RESET_RESUME on the usb_device and removes the now unused
+BTUSB_RESET_RESUME code.
+
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1514836
+Fixes: 7d06d5895c15 ("Revert "Bluetooth: btusb: fix QCA...suspend/resume"")
+Cc: Leif Liddy <leif.linux@gmail.com>
+Cc: Matthias Kaehlcke <mka@chromium.org>
+Cc: Brian Norris <briannorris@chromium.org>
+Cc: Daniel Drake <drake@endlessm.com>
+Cc: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/bluetooth/btusb.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -23,6 +23,7 @@
+
+ #include <linux/module.h>
+ #include <linux/usb.h>
++#include <linux/usb/quirks.h>
+ #include <linux/firmware.h>
+ #include <asm/unaligned.h>
+
+@@ -360,8 +361,8 @@ static const struct usb_device_id blackl
+ #define BTUSB_FIRMWARE_LOADED 7
+ #define BTUSB_FIRMWARE_FAILED 8
+ #define BTUSB_BOOTING 9
+-#define BTUSB_RESET_RESUME 10
+-#define BTUSB_DIAG_RUNNING 11
++#define BTUSB_DIAG_RUNNING 10
++#define BTUSB_OOB_WAKE_ENABLED 11
+
+ struct btusb_data {
+ struct hci_dev *hdev;
+@@ -2969,6 +2970,12 @@ static int btusb_probe(struct usb_interf
+ if (id->driver_info & BTUSB_QCA_ROME) {
+ data->setup_on_usb = btusb_setup_qca;
+ hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
++
++ /* QCA Rome devices lose their updated firmware over suspend,
++ * but the USB hub doesn't notice any status change.
++ * explicitly request a device reset on resume.
++ */
++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
+ }
+
+ #ifdef CONFIG_BT_HCIBTUSB_RTL
+@@ -2979,7 +2986,7 @@ static int btusb_probe(struct usb_interf
+ * but the USB hub doesn't notice any status change.
+ * Explicitly request a device reset on resume.
+ */
+- set_bit(BTUSB_RESET_RESUME, &data->flags);
++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
+ }
+ #endif
+
+@@ -3136,14 +3143,6 @@ static int btusb_suspend(struct usb_inte
+ btusb_stop_traffic(data);
+ usb_kill_anchored_urbs(&data->tx_anchor);
+
+- /* Optionally request a device reset on resume, but only when
+- * wakeups are disabled. If wakeups are enabled we assume the
+- * device will stay powered up throughout suspend.
+- */
+- if (test_bit(BTUSB_RESET_RESUME, &data->flags) &&
+- !device_may_wakeup(&data->udev->dev))
+- data->udev->reset_resume = 1;
+-
+ return 0;
+ }
+
--- /dev/null
+From 225ece3e7dad4cfc44cca38ce7a3a80f255ea8f1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Horia=20Geant=C4=83?= <horia.geanta@nxp.com>
+Date: Mon, 5 Feb 2018 11:15:52 +0200
+Subject: crypto: caam - fix endless loop when DECO acquire fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Horia Geantă <horia.geanta@nxp.com>
+
+commit 225ece3e7dad4cfc44cca38ce7a3a80f255ea8f1 upstream.
+
+In case DECO0 cannot be acquired - i.e. run_descriptor_deco0() fails
+with -ENODEV, caam_probe() enters an endless loop:
+
+run_descriptor_deco0
+ ret -ENODEV
+ -> instantiate_rng
+ -ENODEV, overwritten by -EAGAIN
+ ret -EAGAIN
+ -> caam_probe
+ -EAGAIN results in endless loop
+
+It turns out the error path in instantiate_rng() is incorrect,
+the checks are done in the wrong order.
+
+Fixes: 1005bccd7a4a6 ("crypto: caam - enable instantiation of all RNG4 state handles")
+Reported-by: Bryan O'Donoghue <pure.logic@nexus-software.ie>
+Suggested-by: Auer Lukas <lukas.auer@aisec.fraunhofer.de>
+Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/caam/ctrl.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/crypto/caam/ctrl.c
++++ b/drivers/crypto/caam/ctrl.c
+@@ -224,12 +224,16 @@ static int instantiate_rng(struct device
+ * without any error (HW optimizations for later
+ * CAAM eras), then try again.
+ */
++ if (ret)
++ break;
++
+ rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
+ if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
+- !(rdsta_val & (1 << sh_idx)))
++ !(rdsta_val & (1 << sh_idx))) {
+ ret = -EAGAIN;
+- if (ret)
+ break;
++ }
++
+ dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
+ /* Clear the contents before recreating the descriptor */
+ memset(desc, 0x00, CAAM_CMD_SZ * 7);
--- /dev/null
+From 544e92581a2ac44607d7cc602c6b54d18656f56d Mon Sep 17 00:00:00 2001
+From: James Hogan <jhogan@kernel.org>
+Date: Mon, 13 Nov 2017 16:12:06 +0000
+Subject: EDAC, octeon: Fix an uninitialized variable warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: James Hogan <jhogan@kernel.org>
+
+commit 544e92581a2ac44607d7cc602c6b54d18656f56d upstream.
+
+Fix an uninitialized variable warning in the Octeon EDAC driver, as seen
+in MIPS cavium_octeon_defconfig builds since v4.14 with Codescape GNU
+Tools 2016.05-03:
+
+ drivers/edac/octeon_edac-lmc.c In function ‘octeon_lmc_edac_poll_o2’:
+ drivers/edac/octeon_edac-lmc.c:87:24: warning: ‘((long unsigned int*)&int_reg)[1]’ may \
+ be used uninitialized in this function [-Wmaybe-uninitialized]
+ if (int_reg.s.sec_err || int_reg.s.ded_err) {
+ ^
+Iinitialise the whole int_reg variable to zero before the conditional
+assignments in the error injection case.
+
+Signed-off-by: James Hogan <jhogan@kernel.org>
+Acked-by: David Daney <david.daney@cavium.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+Cc: linux-mips@linux-mips.org
+Fixes: 1bc021e81565 ("EDAC: Octeon: Add error injection support")
+Link: http://lkml.kernel.org/r/20171113161206.20990-1-james.hogan@mips.com
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/edac/octeon_edac-lmc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/edac/octeon_edac-lmc.c
++++ b/drivers/edac/octeon_edac-lmc.c
+@@ -79,6 +79,7 @@ static void octeon_lmc_edac_poll_o2(stru
+ if (!pvt->inject)
+ int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx));
+ else {
++ int_reg.u64 = 0;
+ if (pvt->error_type == 1)
+ int_reg.s.sec_err = 1;
+ if (pvt->error_type == 2)
--- /dev/null
+From edfc3722cfef4217c7fe92b272cbe0288ba1ff57 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 17 Jan 2018 21:05:55 +0100
+Subject: HID: quirks: Fix keyboard + touchpad on Toshiba Click Mini not working
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit edfc3722cfef4217c7fe92b272cbe0288ba1ff57 upstream.
+
+The Toshiba Click Mini uses an i2c attached keyboard/touchpad combo
+(single i2c_hid device for both) which has a vid:pid of 04F3:0401,
+which is also used by a bunch of Elan touchpads which are handled by the
+drivers/input/mouse/elan_i2c driver, but that driver deals with pure
+touchpads and does not work for a combo device such as the one on the
+Toshiba Click Mini.
+
+The combo on the Mini has an ACPI id of ELAN0800, which is not claimed
+by the elan_i2c driver, so check for that and if it is found do not ignore
+the device. This fixes the keyboard/touchpad combo on the Mini not working
+(although with the touchpad in mouse emulation mode).
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-core.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2308,7 +2308,6 @@ static const struct hid_device_id hid_ig
+ { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) },
+- { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
+@@ -2578,6 +2577,17 @@ bool hid_ignore(struct hid_device *hdev)
+ strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
+ return true;
+ break;
++ case USB_VENDOR_ID_ELAN:
++ /*
++ * Many Elan devices have a product id of 0x0401 and are handled
++ * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev
++ * is not (and cannot be) handled by that driver ->
++ * Ignore all 0x0401 devs except for the ELAN0800 dev.
++ */
++ if (hdev->product == 0x0401 &&
++ strncmp(hdev->name, "ELAN0800", 8) != 0)
++ return true;
++ break;
+ }
+
+ if (hdev->type == HID_TYPE_USBMOUSE &&
--- /dev/null
+From 4f7e988e63e336827f4150de48163bed05d653bd Mon Sep 17 00:00:00 2001
+From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Date: Tue, 6 Feb 2018 15:37:55 -0800
+Subject: kernel/async.c: revert "async: simplify lowest_in_progress()"
+
+From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+
+commit 4f7e988e63e336827f4150de48163bed05d653bd upstream.
+
+This reverts commit 92266d6ef60c ("async: simplify lowest_in_progress()")
+which was simply wrong: In the case where domain is NULL, we now use the
+wrong offsetof() in the list_first_entry macro, so we don't actually
+fetch the ->cookie value, but rather the eight bytes located
+sizeof(struct list_head) further into the struct async_entry.
+
+On 64 bit, that's the data member, while on 32 bit, that's a u64 built
+from func and data in some order.
+
+I think the bug happens to be harmless in practice: It obviously only
+affects callers which pass a NULL domain, and AFAICT the only such
+caller is
+
+ async_synchronize_full() ->
+ async_synchronize_full_domain(NULL) ->
+ async_synchronize_cookie_domain(ASYNC_COOKIE_MAX, NULL)
+
+and the ASYNC_COOKIE_MAX means that in practice we end up waiting for
+the async_global_pending list to be empty - but it would break if
+somebody happened to pass (void*)-1 as the data element to
+async_schedule, and of course also if somebody ever does a
+async_synchronize_cookie_domain(, NULL) with a "finite" cookie value.
+
+Maybe the "harmless in practice" means this isn't -stable material. But
+I'm not completely confident my quick git grep'ing is enough, and there
+might be affected code in one of the earlier kernels that has since been
+removed, so I'll leave the decision to the stable guys.
+
+Link: http://lkml.kernel.org/r/20171128104938.3921-1-linux@rasmusvillemoes.dk
+Fixes: 92266d6ef60c "async: simplify lowest_in_progress()"
+Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Acked-by: Tejun Heo <tj@kernel.org>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: Adam Wallis <awallis@codeaurora.org>
+Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/async.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+--- a/kernel/async.c
++++ b/kernel/async.c
+@@ -84,20 +84,24 @@ static atomic_t entry_count;
+
+ static async_cookie_t lowest_in_progress(struct async_domain *domain)
+ {
+- struct list_head *pending;
++ struct async_entry *first = NULL;
+ async_cookie_t ret = ASYNC_COOKIE_MAX;
+ unsigned long flags;
+
+ spin_lock_irqsave(&async_lock, flags);
+
+- if (domain)
+- pending = &domain->pending;
+- else
+- pending = &async_global_pending;
++ if (domain) {
++ if (!list_empty(&domain->pending))
++ first = list_first_entry(&domain->pending,
++ struct async_entry, domain_list);
++ } else {
++ if (!list_empty(&async_global_pending))
++ first = list_first_entry(&async_global_pending,
++ struct async_entry, global_list);
++ }
+
+- if (!list_empty(pending))
+- ret = list_first_entry(pending, struct async_entry,
+- domain_list)->cookie;
++ if (first)
++ ret = first->cookie;
+
+ spin_unlock_irqrestore(&async_lock, flags);
+ return ret;
--- /dev/null
+From 6b6977117f50d60455ace86b2d256f6fb4f3de05 Mon Sep 17 00:00:00 2001
+From: Liran Alon <liran.alon@oracle.com>
+Date: Thu, 9 Nov 2017 20:27:20 +0200
+Subject: KVM: nVMX: Fix races when sending nested PI while dest enters/leaves L2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Liran Alon <liran.alon@oracle.com>
+
+commit 6b6977117f50d60455ace86b2d256f6fb4f3de05 upstream.
+
+Consider the following scenario:
+1. CPU A calls vmx_deliver_nested_posted_interrupt() to send an IPI
+to CPU B via virtual posted-interrupt mechanism.
+2. CPU B is currently executing L2 guest.
+3. vmx_deliver_nested_posted_interrupt() calls
+kvm_vcpu_trigger_posted_interrupt() which will note that
+vcpu->mode == IN_GUEST_MODE.
+4. Assume that before CPU A sends the physical POSTED_INTR_NESTED_VECTOR
+IPI, CPU B exits from L2 to L0 during event-delivery
+(valid IDT-vectoring-info).
+5. CPU A now sends the physical IPI. The IPI is received in host and
+it's handler (smp_kvm_posted_intr_nested_ipi()) does nothing.
+6. Assume that before CPU A sets pi_pending=true and KVM_REQ_EVENT,
+CPU B continues to run in L0 and reach vcpu_enter_guest(). As
+KVM_REQ_EVENT is not set yet, vcpu_enter_guest() will continue and resume
+L2 guest.
+7. At this point, CPU A sets pi_pending=true and KVM_REQ_EVENT but
+it's too late! CPU B already entered L2 and KVM_REQ_EVENT will only be
+consumed at next L2 entry!
+
+Another scenario to consider:
+1. CPU A calls vmx_deliver_nested_posted_interrupt() to send an IPI
+to CPU B via virtual posted-interrupt mechanism.
+2. Assume that before CPU A calls kvm_vcpu_trigger_posted_interrupt(),
+CPU B is at L0 and is about to resume into L2. Further assume that it is
+in vcpu_enter_guest() after check for KVM_REQ_EVENT.
+3. At this point, CPU A calls kvm_vcpu_trigger_posted_interrupt() which
+will note that vcpu->mode != IN_GUEST_MODE. Therefore, do nothing and
+return false. Then, will set pi_pending=true and KVM_REQ_EVENT.
+4. Now CPU B continue and resumes into L2 guest without processing
+the posted-interrupt until next L2 entry!
+
+To fix both issues, we just need to change
+vmx_deliver_nested_posted_interrupt() to set pi_pending=true and
+KVM_REQ_EVENT before calling kvm_vcpu_trigger_posted_interrupt().
+
+It will fix the first scenario by chaging step (6) to note that
+KVM_REQ_EVENT and pi_pending=true and therefore process
+nested posted-interrupt.
+
+It will fix the second scenario by two possible ways:
+1. If kvm_vcpu_trigger_posted_interrupt() is called while CPU B has changed
+vcpu->mode to IN_GUEST_MODE, physical IPI will be sent and will be received
+when CPU resumes into L2.
+2. If kvm_vcpu_trigger_posted_interrupt() is called while CPU B hasn't yet
+changed vcpu->mode to IN_GUEST_MODE, then after CPU B will change
+vcpu->mode it will call kvm_request_pending() which will return true and
+therefore force another round of vcpu_enter_guest() which will note that
+KVM_REQ_EVENT and pi_pending=true and therefore process nested
+posted-interrupt.
+
+Fixes: 705699a13994 ("KVM: nVMX: Enable nested posted interrupt processing")
+Signed-off-by: Liran Alon <liran.alon@oracle.com>
+Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
+Reviewed-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
+[Add kvm_vcpu_kick to also handle the case where L1 doesn't intercept L2 HLT
+ and L2 executes HLT instruction. - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/vmx.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -4595,14 +4595,15 @@ static int vmx_deliver_nested_posted_int
+
+ if (is_guest_mode(vcpu) &&
+ vector == vmx->nested.posted_intr_nv) {
+- /* the PIR and ON have been set by L1. */
+- kvm_vcpu_trigger_posted_interrupt(vcpu);
+ /*
+ * If a posted intr is not recognized by hardware,
+ * we will accomplish it in the next vmentry.
+ */
+ vmx->nested.pi_pending = true;
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
++ /* the PIR and ON have been set by L1. */
++ if (!kvm_vcpu_trigger_posted_interrupt(vcpu))
++ kvm_vcpu_kick(vcpu);
+ return 0;
+ }
+ return -1;
--- /dev/null
+From 9893b905e743ded332575ca04486bd586c0772f7 Mon Sep 17 00:00:00 2001
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Date: Wed, 24 Jan 2018 06:01:57 -0500
+Subject: media: cxusb, dib0700: ignore XC2028_I2C_FLUSH
+
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+
+commit 9893b905e743ded332575ca04486bd586c0772f7 upstream.
+
+The XC2028_I2C_FLUSH only needs to be implemented on a few
+devices. Others can safely ignore it.
+
+That prevents filling the dmesg with lots of messages like:
+
+ dib0700: stk7700ph_xc3028_callback: unknown command 2, arg 0
+
+Fixes: 4d37ece757a8 ("[media] tuner/xc2028: Add I2C flush callback")
+Reported-by: Enrico Mioso <mrkiko.rs@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb/cxusb.c | 2 ++
+ drivers/media/usb/dvb-usb/dib0700_devices.c | 1 +
+ 2 files changed, 3 insertions(+)
+
+--- a/drivers/media/usb/dvb-usb/cxusb.c
++++ b/drivers/media/usb/dvb-usb/cxusb.c
+@@ -818,6 +818,8 @@ static int dvico_bluebird_xc2028_callbac
+ case XC2028_RESET_CLK:
+ deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
+ break;
++ case XC2028_I2C_FLUSH:
++ break;
+ default:
+ deb_info("%s: unknown command %d, arg %d\n", __func__,
+ command, arg);
+--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
++++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
+@@ -431,6 +431,7 @@ static int stk7700ph_xc3028_callback(voi
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ break;
+ case XC2028_RESET_CLK:
++ case XC2028_I2C_FLUSH:
+ break;
+ default:
+ err("%s: unknown command %d, arg %d\n", __func__,
--- /dev/null
+From 81742be14b6a90c9fd0ff6eb4218bdf696ad8e46 Mon Sep 17 00:00:00 2001
+From: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Date: Wed, 10 Jan 2018 07:20:39 -0500
+Subject: media: ts2020: avoid integer overflows on 32 bit machines
+
+From: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+
+commit 81742be14b6a90c9fd0ff6eb4218bdf696ad8e46 upstream.
+
+Before this patch, when compiled for arm32, the signal strength
+were reported as:
+
+Lock (0x1f) Signal= 4294908.66dBm C/N= 12.79dB
+
+Because of a 32 bit integer overflow. After it, it is properly
+reported as:
+
+ Lock (0x1f) Signal= -58.64dBm C/N= 12.79dB
+
+Fixes: 0f91c9d6bab9 ("[media] TS2020: Calculate tuner gain correctly")
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/dvb-frontends/ts2020.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/dvb-frontends/ts2020.c
++++ b/drivers/media/dvb-frontends/ts2020.c
+@@ -369,7 +369,7 @@ static int ts2020_read_tuner_gain(struct
+ gain2 = clamp_t(long, gain2, 0, 13);
+ v_agc = clamp_t(long, v_agc, 400, 1100);
+
+- *_gain = -(gain1 * 2330 +
++ *_gain = -((__s64)gain1 * 2330 +
+ gain2 * 3500 +
+ v_agc * 24 / 10 * 10 +
+ 10000);
+@@ -387,7 +387,7 @@ static int ts2020_read_tuner_gain(struct
+ gain3 = clamp_t(long, gain3, 0, 6);
+ v_agc = clamp_t(long, v_agc, 600, 1600);
+
+- *_gain = -(gain1 * 2650 +
++ *_gain = -((__s64)gain1 * 2650 +
+ gain2 * 3380 +
+ gain3 * 2850 +
+ v_agc * 176 / 100 * 10 -
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:36 +0100
+Subject: media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Daniel Mentz <danielmentz@google.com>, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-11-hverkuil@xs4all.nl>
+
+From: Daniel Mentz <danielmentz@google.com>
+
+commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.
+
+Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
+overlays.") added the field global_alpha to struct v4l2_window but did
+not update the compat layer accordingly. This change adds global_alpha
+to struct v4l2_window32 and copies the value for global_alpha back and
+forth.
+
+Signed-off-by: Daniel Mentz <danielmentz@google.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -45,6 +45,7 @@ struct v4l2_window32 {
+ compat_caddr_t clips; /* actually struct v4l2_clip32 * */
+ __u32 clipcount;
+ compat_caddr_t bitmap;
++ __u8 global_alpha;
+ };
+
+ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+@@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2
+ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+ get_user(kp->field, &up->field) ||
+ get_user(kp->chromakey, &up->chromakey) ||
+- get_user(kp->clipcount, &up->clipcount))
++ get_user(kp->clipcount, &up->clipcount) ||
++ get_user(kp->global_alpha, &up->global_alpha))
+ return -EFAULT;
+ if (kp->clipcount > 2048)
+ return -EINVAL;
+@@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2
+ if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+- put_user(kp->clipcount, &up->clipcount))
++ put_user(kp->clipcount, &up->clipcount) ||
++ put_user(kp->global_alpha, &up->global_alpha))
+ return -EFAULT;
+ return 0;
+ }
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:29 +0100
+Subject: media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-4-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.
+
+The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
+to userspace since it was missing in the switch.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -1022,6 +1022,7 @@ static long do_video_ioctl(struct file *
+ err = put_v4l2_create32(&karg.v2crt, up);
+ break;
+
++ case VIDIOC_PREPARE_BUF:
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:32 +0100
+Subject: media: v4l2-compat-ioctl32.c: avoid sizeof(type)
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-7-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.
+
+Instead of doing sizeof(struct foo) use sizeof(*up). There even were
+cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
+which is very dangerous when the size of the reserved array changes.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 77 ++++++++++++--------------
+ 1 file changed, 36 insertions(+), 41 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -47,7 +47,7 @@ struct v4l2_window32 {
+
+ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+ {
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+ get_user(kp->field, &up->field) ||
+ get_user(kp->chromakey, &up->chromakey) ||
+@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
+- kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
++ kclips = compat_alloc_user_space(n * sizeof(*kclips));
+ kp->clips = kclips;
+ while (--n >= 0) {
+ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+@@ -157,14 +157,14 @@ static int __get_v4l2_format32(struct v4
+
+ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+ {
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+ return -EFAULT;
+ return __get_v4l2_format32(kp, up);
+ }
+
+ static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+ {
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
+ return -EFAULT;
+ return __get_v4l2_format32(&kp->format, &up->format);
+@@ -208,14 +208,14 @@ static int __put_v4l2_format32(struct v4
+
+ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+ {
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
+ return -EFAULT;
+ return __put_v4l2_format32(kp, up);
+ }
+
+ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+ {
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
+ copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+@@ -234,7 +234,7 @@ struct v4l2_standard32 {
+ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+ {
+ /* other fields are not set by the user, nor used by the driver */
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(kp->index, &up->index))
+ return -EFAULT;
+ return 0;
+@@ -242,13 +242,13 @@ static int get_v4l2_standard32(struct v4
+
+ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+ {
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(kp->index, &up->index) ||
+ put_user(kp->id, &up->id) ||
+- copy_to_user(up->name, kp->name, 24) ||
++ copy_to_user(up->name, kp->name, sizeof(up->name)) ||
+ copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
+ put_user(kp->framelines, &up->framelines) ||
+- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
++ copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -296,7 +296,7 @@ static int get_v4l2_plane32(struct v4l2_
+
+ if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
+ copy_in_user(&up->data_offset, &up32->data_offset,
+- sizeof(__u32)))
++ sizeof(up->data_offset)))
+ return -EFAULT;
+
+ if (memory == V4L2_MEMORY_USERPTR) {
+@@ -306,11 +306,11 @@ static int get_v4l2_plane32(struct v4l2_
+ if (put_user((unsigned long)up_pln, &up->m.userptr))
+ return -EFAULT;
+ } else if (memory == V4L2_MEMORY_DMABUF) {
+- if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
++ if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
+ return -EFAULT;
+ } else {
+ if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
+- sizeof(__u32)))
++ sizeof(up32->m.mem_offset)))
+ return -EFAULT;
+ }
+
+@@ -322,19 +322,19 @@ static int put_v4l2_plane32(struct v4l2_
+ {
+ if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
+ copy_in_user(&up32->data_offset, &up->data_offset,
+- sizeof(__u32)))
++ sizeof(up->data_offset)))
+ return -EFAULT;
+
+ /* For MMAP, driver might've set up the offset, so copy it back.
+ * USERPTR stays the same (was userspace-provided), so no copying. */
+ if (memory == V4L2_MEMORY_MMAP)
+ if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
+- sizeof(__u32)))
++ sizeof(up->m.mem_offset)))
+ return -EFAULT;
+ /* For DMABUF, driver might've set up the fd, so copy it back. */
+ if (memory == V4L2_MEMORY_DMABUF)
+ if (copy_in_user(&up32->m.fd, &up->m.fd,
+- sizeof(int)))
++ sizeof(up->m.fd)))
+ return -EFAULT;
+
+ return 0;
+@@ -348,7 +348,7 @@ static int get_v4l2_buffer32(struct v4l2
+ int num_planes;
+ int ret;
+
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(kp->index, &up->index) ||
+ get_user(kp->type, &up->type) ||
+ get_user(kp->flags, &up->flags) ||
+@@ -360,8 +360,7 @@ static int get_v4l2_buffer32(struct v4l2
+ if (get_user(kp->bytesused, &up->bytesused) ||
+ get_user(kp->field, &up->field) ||
+ get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- get_user(kp->timestamp.tv_usec,
+- &up->timestamp.tv_usec))
++ get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec))
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+@@ -378,13 +377,12 @@ static int get_v4l2_buffer32(struct v4l2
+
+ uplane32 = compat_ptr(p);
+ if (!access_ok(VERIFY_READ, uplane32,
+- num_planes * sizeof(struct v4l2_plane32)))
++ num_planes * sizeof(*uplane32)))
+ return -EFAULT;
+
+ /* We don't really care if userspace decides to kill itself
+ * by passing a very big num_planes value */
+- uplane = compat_alloc_user_space(num_planes *
+- sizeof(struct v4l2_plane));
++ uplane = compat_alloc_user_space(num_planes * sizeof(*uplane));
+ kp->m.planes = (__force struct v4l2_plane *)uplane;
+
+ while (--num_planes >= 0) {
+@@ -432,7 +430,7 @@ static int put_v4l2_buffer32(struct v4l2
+ int num_planes;
+ int ret;
+
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(kp->index, &up->index) ||
+ put_user(kp->type, &up->type) ||
+ put_user(kp->flags, &up->flags) ||
+@@ -443,7 +441,7 @@ static int put_v4l2_buffer32(struct v4l2
+ put_user(kp->field, &up->field) ||
+ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
+- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
++ copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
+ put_user(kp->sequence, &up->sequence) ||
+ put_user(kp->reserved2, &up->reserved2) ||
+ put_user(kp->reserved, &up->reserved) ||
+@@ -511,7 +509,7 @@ static int get_v4l2_framebuffer32(struct
+ {
+ u32 tmp;
+
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(tmp, &up->base) ||
+ get_user(kp->capability, &up->capability) ||
+ get_user(kp->flags, &up->flags) ||
+@@ -525,7 +523,7 @@ static int put_v4l2_framebuffer32(struct
+ {
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(tmp, &up->base) ||
+ put_user(kp->capability, &up->capability) ||
+ put_user(kp->flags, &up->flags) ||
+@@ -549,14 +547,14 @@ struct v4l2_input32 {
+ Otherwise it is identical to the 32-bit version. */
+ static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+ {
+- if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
++ if (copy_from_user(kp, up, sizeof(*up)))
+ return -EFAULT;
+ return 0;
+ }
+
+ static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+ {
+- if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
++ if (copy_to_user(up, kp, sizeof(*up)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -604,12 +602,11 @@ static int get_v4l2_ext_controls32(struc
+ int n;
+ compat_caddr_t p;
+
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(kp->ctrl_class, &up->ctrl_class) ||
+ get_user(kp->count, &up->count) ||
+ get_user(kp->error_idx, &up->error_idx) ||
+- copy_from_user(kp->reserved, up->reserved,
+- sizeof(kp->reserved)))
++ copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+ n = kp->count;
+ if (n == 0) {
+@@ -619,10 +616,9 @@ static int get_v4l2_ext_controls32(struc
+ if (get_user(p, &up->controls))
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+- if (!access_ok(VERIFY_READ, ucontrols,
+- n * sizeof(struct v4l2_ext_control32)))
++ if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(*ucontrols)))
+ return -EFAULT;
+- kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
++ kcontrols = compat_alloc_user_space(n * sizeof(*kcontrols));
+ kp->controls = (__force struct v4l2_ext_control *)kcontrols;
+ while (--n >= 0) {
+ u32 id;
+@@ -654,7 +650,7 @@ static int put_v4l2_ext_controls32(struc
+ int n = kp->count;
+ compat_caddr_t p;
+
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(kp->ctrl_class, &up->ctrl_class) ||
+ put_user(kp->count, &up->count) ||
+ put_user(kp->error_idx, &up->error_idx) ||
+@@ -666,8 +662,7 @@ static int put_v4l2_ext_controls32(struc
+ if (get_user(p, &up->controls))
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+- if (!access_ok(VERIFY_WRITE, ucontrols,
+- n * sizeof(struct v4l2_ext_control32)))
++ if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols)))
+ return -EFAULT;
+
+ while (--n >= 0) {
+@@ -704,7 +699,7 @@ struct v4l2_event32 {
+
+ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+ {
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(kp->type, &up->type) ||
+ copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
+ put_user(kp->pending, &up->pending) ||
+@@ -712,7 +707,7 @@ static int put_v4l2_event32(struct v4l2_
+ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
+ put_user(kp->id, &up->id) ||
+- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
++ copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -729,7 +724,7 @@ static int get_v4l2_edid32(struct v4l2_e
+ {
+ u32 tmp;
+
+- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(kp->pad, &up->pad) ||
+ get_user(kp->start_block, &up->start_block) ||
+ get_user(kp->blocks, &up->blocks) ||
+@@ -744,7 +739,7 @@ static int put_v4l2_edid32(struct v4l2_e
+ {
+ u32 tmp = (u32)((unsigned long)kp->edid);
+
+- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ put_user(kp->pad, &up->pad) ||
+ put_user(kp->start_block, &up->start_block) ||
+ put_user(kp->blocks, &up->blocks) ||
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:37 +0100
+Subject: media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-12-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.
+
+put_v4l2_window32() didn't copy back the clip list to userspace.
+Drivers can update the clip rectangles, so this should be done.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 +++++++++++++++++---------
+ 1 file changed, 40 insertions(+), 19 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -50,6 +50,11 @@ struct v4l2_window32 {
+
+ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+ {
++ struct v4l2_clip32 __user *uclips;
++ struct v4l2_clip __user *kclips;
++ compat_caddr_t p;
++ u32 n;
++
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+ get_user(kp->field, &up->field) ||
+@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2
+ return -EFAULT;
+ if (kp->clipcount > 2048)
+ return -EINVAL;
+- if (kp->clipcount) {
+- struct v4l2_clip32 __user *uclips;
+- struct v4l2_clip __user *kclips;
+- int n = kp->clipcount;
+- compat_caddr_t p;
++ if (!kp->clipcount) {
++ kp->clips = NULL;
++ return 0;
++ }
+
+- if (get_user(p, &up->clips))
++ n = kp->clipcount;
++ if (get_user(p, &up->clips))
++ return -EFAULT;
++ uclips = compat_ptr(p);
++ kclips = compat_alloc_user_space(n * sizeof(*kclips));
++ kp->clips = kclips;
++ while (n--) {
++ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+- uclips = compat_ptr(p);
+- kclips = compat_alloc_user_space(n * sizeof(*kclips));
+- kp->clips = kclips;
+- while (--n >= 0) {
+- if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+- return -EFAULT;
+- if (put_user(n ? kclips + 1 : NULL, &kclips->next))
+- return -EFAULT;
+- uclips += 1;
+- kclips += 1;
+- }
+- } else
+- kp->clips = NULL;
++ if (put_user(n ? kclips + 1 : NULL, &kclips->next))
++ return -EFAULT;
++ uclips++;
++ kclips++;
++ }
+ return 0;
+ }
+
+ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+ {
++ struct v4l2_clip __user *kclips = kp->clips;
++ struct v4l2_clip32 __user *uclips;
++ u32 n = kp->clipcount;
++ compat_caddr_t p;
++
+ if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+ put_user(kp->clipcount, &up->clipcount) ||
+ put_user(kp->global_alpha, &up->global_alpha))
+ return -EFAULT;
++
++ if (!kp->clipcount)
++ return 0;
++
++ if (get_user(p, &up->clips))
++ return -EFAULT;
++ uclips = compat_ptr(p);
++ while (n--) {
++ if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
++ return -EFAULT;
++ uclips++;
++ kclips++;
++ }
+ return 0;
+ }
+
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:33 +0100
+Subject: media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-8-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.
+
+The struct v4l2_plane32 should set m.userptr as well. The same
+happens in v4l2_buffer32 and v4l2-compliance tests for this.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 +++++++++++++++-----------
+ 1 file changed, 28 insertions(+), 19 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -299,19 +299,24 @@ static int get_v4l2_plane32(struct v4l2_
+ sizeof(up->data_offset)))
+ return -EFAULT;
+
+- if (memory == V4L2_MEMORY_USERPTR) {
++ switch (memory) {
++ case V4L2_MEMORY_MMAP:
++ case V4L2_MEMORY_OVERLAY:
++ if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
++ sizeof(up32->m.mem_offset)))
++ return -EFAULT;
++ break;
++ case V4L2_MEMORY_USERPTR:
+ if (get_user(p, &up32->m.userptr))
+ return -EFAULT;
+ up_pln = compat_ptr(p);
+ if (put_user((unsigned long)up_pln, &up->m.userptr))
+ return -EFAULT;
+- } else if (memory == V4L2_MEMORY_DMABUF) {
++ break;
++ case V4L2_MEMORY_DMABUF:
+ if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
+ return -EFAULT;
+- } else {
+- if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
+- sizeof(up32->m.mem_offset)))
+- return -EFAULT;
++ break;
+ }
+
+ return 0;
+@@ -320,22 +325,32 @@ static int get_v4l2_plane32(struct v4l2_
+ static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
+ enum v4l2_memory memory)
+ {
++ unsigned long p;
++
+ if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
+ copy_in_user(&up32->data_offset, &up->data_offset,
+ sizeof(up->data_offset)))
+ return -EFAULT;
+
+- /* For MMAP, driver might've set up the offset, so copy it back.
+- * USERPTR stays the same (was userspace-provided), so no copying. */
+- if (memory == V4L2_MEMORY_MMAP)
++ switch (memory) {
++ case V4L2_MEMORY_MMAP:
++ case V4L2_MEMORY_OVERLAY:
+ if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
+ sizeof(up->m.mem_offset)))
+ return -EFAULT;
+- /* For DMABUF, driver might've set up the fd, so copy it back. */
+- if (memory == V4L2_MEMORY_DMABUF)
++ break;
++ case V4L2_MEMORY_USERPTR:
++ if (get_user(p, &up->m.userptr) ||
++ put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
++ &up32->m.userptr))
++ return -EFAULT;
++ break;
++ case V4L2_MEMORY_DMABUF:
+ if (copy_in_user(&up32->m.fd, &up->m.fd,
+ sizeof(up->m.fd)))
+ return -EFAULT;
++ break;
++ }
+
+ return 0;
+ }
+@@ -395,6 +410,7 @@ static int get_v4l2_buffer32(struct v4l2
+ } else {
+ switch (kp->memory) {
+ case V4L2_MEMORY_MMAP:
++ case V4L2_MEMORY_OVERLAY:
+ if (get_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+@@ -408,10 +424,6 @@ static int get_v4l2_buffer32(struct v4l2
+ kp->m.userptr = (unsigned long)compat_ptr(tmp);
+ }
+ break;
+- case V4L2_MEMORY_OVERLAY:
+- if (get_user(kp->m.offset, &up->m.offset))
+- return -EFAULT;
+- break;
+ case V4L2_MEMORY_DMABUF:
+ if (get_user(kp->m.fd, &up->m.fd))
+ return -EFAULT;
+@@ -468,6 +480,7 @@ static int put_v4l2_buffer32(struct v4l2
+ } else {
+ switch (kp->memory) {
+ case V4L2_MEMORY_MMAP:
++ case V4L2_MEMORY_OVERLAY:
+ if (put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+@@ -475,10 +488,6 @@ static int put_v4l2_buffer32(struct v4l2
+ if (put_user(kp->m.userptr, &up->m.userptr))
+ return -EFAULT;
+ break;
+- case V4L2_MEMORY_OVERLAY:
+- if (put_user(kp->m.offset, &up->m.offset))
+- return -EFAULT;
+- break;
+ case V4L2_MEMORY_DMABUF:
+ if (put_user(kp->m.fd, &up->m.fd))
+ return -EFAULT;
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:39 +0100
+Subject: media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-14-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.
+
+Some ioctls need to copy back the result even if the ioctl returned
+an error. However, don't do this for the error code -ENOTTY.
+It makes no sense in that cases.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -956,6 +956,9 @@ static long do_video_ioctl(struct file *
+ set_fs(old_fs);
+ }
+
++ if (err == -ENOTTY)
++ return err;
++
+ /* Special case: even after an error we need to put the
+ results back for these ioctls since the error_idx will
+ contain information on which control failed. */
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:38 +0100
+Subject: media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-13-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.
+
+There is nothing wrong with using an unknown buffer type. So
+stop spamming the kernel log whenever this happens. The kernel
+will just return -EINVAL to signal this.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -175,8 +175,6 @@ static int __get_v4l2_format32(struct v4
+ return copy_from_user(&kp->fmt.sdr, &up->fmt.sdr,
+ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+- kp->type);
+ return -EINVAL;
+ }
+ }
+@@ -226,8 +224,6 @@ static int __put_v4l2_format32(struct v4
+ return copy_to_user(&up->fmt.sdr, &kp->fmt.sdr,
+ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+- kp->type);
+ return -EINVAL;
+ }
+ }
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:34 +0100
+Subject: media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-9-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.
+
+ctrl_is_pointer just hardcoded two known string controls, but that
+caused problems when using e.g. custom controls that use a pointer
+for the payload.
+
+Reimplement this function: it now finds the v4l2_ctrl (if the driver
+uses the control framework) or it calls vidioc_query_ext_ctrl (if the
+driver implements that directly).
+
+In both cases it can now check if the control is a pointer control
+or not.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 +++++++++++++++++---------
+ 1 file changed, 39 insertions(+), 20 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -18,6 +18,8 @@
+ #include <linux/videodev2.h>
+ #include <linux/v4l2-subdev.h>
+ #include <media/v4l2-dev.h>
++#include <media/v4l2-fh.h>
++#include <media/v4l2-ctrls.h>
+ #include <media/v4l2-ioctl.h>
+
+ static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -587,24 +589,39 @@ struct v4l2_ext_control32 {
+ };
+ } __attribute__ ((packed));
+
+-/* The following function really belong in v4l2-common, but that causes
+- a circular dependency between modules. We need to think about this, but
+- for now this will do. */
+-
+-/* Return non-zero if this control is a pointer type. Currently only
+- type STRING is a pointer type. */
+-static inline int ctrl_is_pointer(u32 id)
+-{
+- switch (id) {
+- case V4L2_CID_RDS_TX_PS_NAME:
+- case V4L2_CID_RDS_TX_RADIO_TEXT:
+- return 1;
+- default:
+- return 0;
++/* Return true if this control is a pointer type. */
++static inline bool ctrl_is_pointer(struct file *file, u32 id)
++{
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_fh *fh = NULL;
++ struct v4l2_ctrl_handler *hdl = NULL;
++ struct v4l2_query_ext_ctrl qec = { id };
++ const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
++
++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
++ fh = file->private_data;
++
++ if (fh && fh->ctrl_handler)
++ hdl = fh->ctrl_handler;
++ else if (vdev->ctrl_handler)
++ hdl = vdev->ctrl_handler;
++
++ if (hdl) {
++ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
++
++ return ctrl && ctrl->is_ptr;
+ }
++
++ if (!ops->vidioc_query_ext_ctrl)
++ return false;
++
++ return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
++ (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
+ }
+
+-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
++static int get_v4l2_ext_controls32(struct file *file,
++ struct v4l2_ext_controls *kp,
++ struct v4l2_ext_controls32 __user *up)
+ {
+ struct v4l2_ext_control32 __user *ucontrols;
+ struct v4l2_ext_control __user *kcontrols;
+@@ -636,7 +653,7 @@ static int get_v4l2_ext_controls32(struc
+ return -EFAULT;
+ if (get_user(id, &kcontrols->id))
+ return -EFAULT;
+- if (ctrl_is_pointer(id)) {
++ if (ctrl_is_pointer(file, id)) {
+ void __user *s;
+
+ if (get_user(p, &ucontrols->string))
+@@ -651,7 +668,9 @@ static int get_v4l2_ext_controls32(struc
+ return 0;
+ }
+
+-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
++static int put_v4l2_ext_controls32(struct file *file,
++ struct v4l2_ext_controls *kp,
++ struct v4l2_ext_controls32 __user *up)
+ {
+ struct v4l2_ext_control32 __user *ucontrols;
+ struct v4l2_ext_control __user *kcontrols =
+@@ -683,7 +702,7 @@ static int put_v4l2_ext_controls32(struc
+ /* Do not modify the pointer when copying a pointer control.
+ The contents of the pointer was changed, not the pointer
+ itself. */
+- if (ctrl_is_pointer(id))
++ if (ctrl_is_pointer(file, id))
+ size -= sizeof(ucontrols->value64);
+ if (copy_in_user(ucontrols, kcontrols, size))
+ return -EFAULT;
+@@ -897,7 +916,7 @@ static long do_video_ioctl(struct file *
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+- err = get_v4l2_ext_controls32(&karg.v2ecs, up);
++ err = get_v4l2_ext_controls32(file, &karg.v2ecs, up);
+ compatible_arg = 0;
+ break;
+ case VIDIOC_DQEVENT:
+@@ -924,7 +943,7 @@ static long do_video_ioctl(struct file *
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+- if (put_v4l2_ext_controls32(&karg.v2ecs, up))
++ if (put_v4l2_ext_controls32(file, &karg.v2ecs, up))
+ err = -EFAULT;
+ break;
+ }
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:30 +0100
+Subject: media: v4l2-compat-ioctl32.c: fix the indentation
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-5-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit b7b957d429f601d6d1942122b339474f31191d75 upstream.
+
+The indentation of this source is all over the place. Fix this.
+This patch only changes whitespace.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 208 +++++++++++++-------------
+ 1 file changed, 104 insertions(+), 104 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -48,11 +48,11 @@ struct v4l2_window32 {
+ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+ {
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+- copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+- get_user(kp->field, &up->field) ||
+- get_user(kp->chromakey, &up->chromakey) ||
+- get_user(kp->clipcount, &up->clipcount))
+- return -EFAULT;
++ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
++ get_user(kp->field, &up->field) ||
++ get_user(kp->chromakey, &up->chromakey) ||
++ get_user(kp->clipcount, &up->clipcount))
++ return -EFAULT;
+ if (kp->clipcount > 2048)
+ return -EINVAL;
+ if (kp->clipcount) {
+@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2
+ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+ {
+ if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
+- put_user(kp->field, &up->field) ||
+- put_user(kp->chromakey, &up->chromakey) ||
+- put_user(kp->clipcount, &up->clipcount))
+- return -EFAULT;
++ put_user(kp->field, &up->field) ||
++ put_user(kp->chromakey, &up->chromakey) ||
++ put_user(kp->clipcount, &up->clipcount))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(st
+ }
+
+ static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+- struct v4l2_pix_format_mplane __user *up)
++ struct v4l2_pix_format_mplane __user *up)
+ {
+ if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+ return -EFAULT;
+@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(st
+ }
+
+ static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+- struct v4l2_pix_format_mplane __user *up)
++ struct v4l2_pix_format_mplane __user *up)
+ {
+ if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+ return -EFAULT;
+@@ -218,7 +218,7 @@ static int __get_v4l2_format32(struct v4
+ return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+ default:
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+- kp->type);
++ kp->type);
+ return -EINVAL;
+ }
+ }
+@@ -265,7 +265,7 @@ static int __put_v4l2_format32(struct v4
+ return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+ default:
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+- kp->type);
++ kp->type);
+ return -EINVAL;
+ }
+ }
+@@ -299,7 +299,7 @@ static int get_v4l2_standard32(struct v4
+ {
+ /* other fields are not set by the user, nor used by the driver */
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+- get_user(kp->index, &up->index))
++ get_user(kp->index, &up->index))
+ return -EFAULT;
+ return 0;
+ }
+@@ -307,13 +307,13 @@ static int get_v4l2_standard32(struct v4
+ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+- put_user(kp->index, &up->index) ||
+- put_user(kp->id, &up->id) ||
+- copy_to_user(up->name, kp->name, 24) ||
+- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
+- put_user(kp->framelines, &up->framelines) ||
+- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+- return -EFAULT;
++ put_user(kp->index, &up->index) ||
++ put_user(kp->id, &up->id) ||
++ copy_to_user(up->name, kp->name, 24) ||
++ copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
++ put_user(kp->framelines, &up->framelines) ||
++ copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -353,14 +353,14 @@ struct v4l2_buffer32 {
+ };
+
+ static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
+- enum v4l2_memory memory)
++ enum v4l2_memory memory)
+ {
+ void __user *up_pln;
+ compat_long_t p;
+
+ if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
+- copy_in_user(&up->data_offset, &up32->data_offset,
+- sizeof(__u32)))
++ copy_in_user(&up->data_offset, &up32->data_offset,
++ sizeof(__u32)))
+ return -EFAULT;
+
+ if (memory == V4L2_MEMORY_USERPTR) {
+@@ -374,7 +374,7 @@ static int get_v4l2_plane32(struct v4l2_
+ return -EFAULT;
+ } else {
+ if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
+- sizeof(__u32)))
++ sizeof(__u32)))
+ return -EFAULT;
+ }
+
+@@ -382,23 +382,23 @@ static int get_v4l2_plane32(struct v4l2_
+ }
+
+ static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
+- enum v4l2_memory memory)
++ enum v4l2_memory memory)
+ {
+ if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
+- copy_in_user(&up32->data_offset, &up->data_offset,
+- sizeof(__u32)))
++ copy_in_user(&up32->data_offset, &up->data_offset,
++ sizeof(__u32)))
+ return -EFAULT;
+
+ /* For MMAP, driver might've set up the offset, so copy it back.
+ * USERPTR stays the same (was userspace-provided), so no copying. */
+ if (memory == V4L2_MEMORY_MMAP)
+ if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
+- sizeof(__u32)))
++ sizeof(__u32)))
+ return -EFAULT;
+ /* For DMABUF, driver might've set up the fd, so copy it back. */
+ if (memory == V4L2_MEMORY_DMABUF)
+ if (copy_in_user(&up32->m.fd, &up->m.fd,
+- sizeof(int)))
++ sizeof(int)))
+ return -EFAULT;
+
+ return 0;
+@@ -413,19 +413,19 @@ static int get_v4l2_buffer32(struct v4l2
+ int ret;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
+- get_user(kp->index, &up->index) ||
+- get_user(kp->type, &up->type) ||
+- get_user(kp->flags, &up->flags) ||
+- get_user(kp->memory, &up->memory) ||
+- get_user(kp->length, &up->length))
+- return -EFAULT;
++ get_user(kp->index, &up->index) ||
++ get_user(kp->type, &up->type) ||
++ get_user(kp->flags, &up->flags) ||
++ get_user(kp->memory, &up->memory) ||
++ get_user(kp->length, &up->length))
++ return -EFAULT;
+
+ if (V4L2_TYPE_IS_OUTPUT(kp->type))
+ if (get_user(kp->bytesused, &up->bytesused) ||
+- get_user(kp->field, &up->field) ||
+- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- get_user(kp->timestamp.tv_usec,
+- &up->timestamp.tv_usec))
++ get_user(kp->field, &up->field) ||
++ get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
++ get_user(kp->timestamp.tv_usec,
++ &up->timestamp.tv_usec))
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+@@ -442,13 +442,13 @@ static int get_v4l2_buffer32(struct v4l2
+
+ uplane32 = compat_ptr(p);
+ if (!access_ok(VERIFY_READ, uplane32,
+- num_planes * sizeof(struct v4l2_plane32)))
++ num_planes * sizeof(struct v4l2_plane32)))
+ return -EFAULT;
+
+ /* We don't really care if userspace decides to kill itself
+ * by passing a very big num_planes value */
+ uplane = compat_alloc_user_space(num_planes *
+- sizeof(struct v4l2_plane));
++ sizeof(struct v4l2_plane));
+ kp->m.planes = (__force struct v4l2_plane *)uplane;
+
+ while (--num_planes >= 0) {
+@@ -466,12 +466,12 @@ static int get_v4l2_buffer32(struct v4l2
+ break;
+ case V4L2_MEMORY_USERPTR:
+ {
+- compat_long_t tmp;
++ compat_long_t tmp;
+
+- if (get_user(tmp, &up->m.userptr))
+- return -EFAULT;
++ if (get_user(tmp, &up->m.userptr))
++ return -EFAULT;
+
+- kp->m.userptr = (unsigned long)compat_ptr(tmp);
++ kp->m.userptr = (unsigned long)compat_ptr(tmp);
+ }
+ break;
+ case V4L2_MEMORY_OVERLAY:
+@@ -497,22 +497,22 @@ static int put_v4l2_buffer32(struct v4l2
+ int ret;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
+- put_user(kp->index, &up->index) ||
+- put_user(kp->type, &up->type) ||
+- put_user(kp->flags, &up->flags) ||
+- put_user(kp->memory, &up->memory))
+- return -EFAULT;
++ put_user(kp->index, &up->index) ||
++ put_user(kp->type, &up->type) ||
++ put_user(kp->flags, &up->flags) ||
++ put_user(kp->memory, &up->memory))
++ return -EFAULT;
+
+ if (put_user(kp->bytesused, &up->bytesused) ||
+- put_user(kp->field, &up->field) ||
+- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
+- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
+- put_user(kp->sequence, &up->sequence) ||
+- put_user(kp->reserved2, &up->reserved2) ||
+- put_user(kp->reserved, &up->reserved) ||
+- put_user(kp->length, &up->length))
+- return -EFAULT;
++ put_user(kp->field, &up->field) ||
++ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
++ put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
++ copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
++ put_user(kp->sequence, &up->sequence) ||
++ put_user(kp->reserved2, &up->reserved2) ||
++ put_user(kp->reserved, &up->reserved) ||
++ put_user(kp->length, &up->length))
++ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+ num_planes = kp->length;
+@@ -576,11 +576,11 @@ static int get_v4l2_framebuffer32(struct
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+- get_user(tmp, &up->base) ||
+- get_user(kp->capability, &up->capability) ||
+- get_user(kp->flags, &up->flags) ||
+- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
+- return -EFAULT;
++ get_user(tmp, &up->base) ||
++ get_user(kp->capability, &up->capability) ||
++ get_user(kp->flags, &up->flags) ||
++ copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
++ return -EFAULT;
+ kp->base = (__force void *)compat_ptr(tmp);
+ return 0;
+ }
+@@ -590,11 +590,11 @@ static int put_v4l2_framebuffer32(struct
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
+- put_user(tmp, &up->base) ||
+- put_user(kp->capability, &up->capability) ||
+- put_user(kp->flags, &up->flags) ||
+- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
+- return -EFAULT;
++ put_user(tmp, &up->base) ||
++ put_user(kp->capability, &up->capability) ||
++ put_user(kp->flags, &up->flags) ||
++ copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -669,12 +669,12 @@ static int get_v4l2_ext_controls32(struc
+ compat_caddr_t p;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
+- get_user(kp->ctrl_class, &up->ctrl_class) ||
+- get_user(kp->count, &up->count) ||
+- get_user(kp->error_idx, &up->error_idx) ||
+- copy_from_user(kp->reserved, up->reserved,
+- sizeof(kp->reserved)))
+- return -EFAULT;
++ get_user(kp->ctrl_class, &up->ctrl_class) ||
++ get_user(kp->count, &up->count) ||
++ get_user(kp->error_idx, &up->error_idx) ||
++ copy_from_user(kp->reserved, up->reserved,
++ sizeof(kp->reserved)))
++ return -EFAULT;
+ n = kp->count;
+ if (n == 0) {
+ kp->controls = NULL;
+@@ -684,7 +684,7 @@ static int get_v4l2_ext_controls32(struc
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+ if (!access_ok(VERIFY_READ, ucontrols,
+- n * sizeof(struct v4l2_ext_control32)))
++ n * sizeof(struct v4l2_ext_control32)))
+ return -EFAULT;
+ kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
+ kp->controls = (__force struct v4l2_ext_control *)kcontrols;
+@@ -719,11 +719,11 @@ static int put_v4l2_ext_controls32(struc
+ compat_caddr_t p;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
+- put_user(kp->ctrl_class, &up->ctrl_class) ||
+- put_user(kp->count, &up->count) ||
+- put_user(kp->error_idx, &up->error_idx) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+- return -EFAULT;
++ put_user(kp->ctrl_class, &up->ctrl_class) ||
++ put_user(kp->count, &up->count) ||
++ put_user(kp->error_idx, &up->error_idx) ||
++ copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
++ return -EFAULT;
+ if (!kp->count)
+ return 0;
+
+@@ -731,7 +731,7 @@ static int put_v4l2_ext_controls32(struc
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+ if (!access_ok(VERIFY_WRITE, ucontrols,
+- n * sizeof(struct v4l2_ext_control32)))
++ n * sizeof(struct v4l2_ext_control32)))
+ return -EFAULT;
+
+ while (--n >= 0) {
+@@ -769,15 +769,15 @@ struct v4l2_event32 {
+ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
+- put_user(kp->type, &up->type) ||
+- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
+- put_user(kp->pending, &up->pending) ||
+- put_user(kp->sequence, &up->sequence) ||
+- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
+- put_user(kp->id, &up->id) ||
+- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
+- return -EFAULT;
++ put_user(kp->type, &up->type) ||
++ copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
++ put_user(kp->pending, &up->pending) ||
++ put_user(kp->sequence, &up->sequence) ||
++ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
++ put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
++ put_user(kp->id, &up->id) ||
++ copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -794,12 +794,12 @@ static int get_v4l2_edid32(struct v4l2_e
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
+- get_user(kp->pad, &up->pad) ||
+- get_user(kp->start_block, &up->start_block) ||
+- get_user(kp->blocks, &up->blocks) ||
+- get_user(tmp, &up->edid) ||
+- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+- return -EFAULT;
++ get_user(kp->pad, &up->pad) ||
++ get_user(kp->start_block, &up->start_block) ||
++ get_user(kp->blocks, &up->blocks) ||
++ get_user(tmp, &up->edid) ||
++ copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
++ return -EFAULT;
+ kp->edid = (__force u8 *)compat_ptr(tmp);
+ return 0;
+ }
+@@ -809,12 +809,12 @@ static int put_v4l2_edid32(struct v4l2_e
+ u32 tmp = (u32)((unsigned long)kp->edid);
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
+- put_user(kp->pad, &up->pad) ||
+- put_user(kp->start_block, &up->start_block) ||
+- put_user(kp->blocks, &up->blocks) ||
+- put_user(tmp, &up->edid) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+- return -EFAULT;
++ put_user(kp->pad, &up->pad) ||
++ put_user(kp->start_block, &up->start_block) ||
++ put_user(kp->blocks, &up->blocks) ||
++ put_user(tmp, &up->edid) ||
++ copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
++ return -EFAULT;
+ return 0;
+ }
+
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:35 +0100
+Subject: media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-10-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hansverk@cisco.com>
+
+commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream.
+
+If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops
+is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash.
+Add a test for !ops to the condition.
+
+All sub-devices that have controls will use the control framework,
+so they do not have an equivalent to ops->vidioc_query_ext_ctrl.
+Returning false if ops is NULL is the correct thing to do here.
+
+Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer")
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reported-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -612,7 +612,7 @@ static inline bool ctrl_is_pointer(struc
+ return ctrl && ctrl->is_ptr;
+ }
+
+- if (!ops->vidioc_query_ext_ctrl)
++ if (!ops || !ops->vidioc_query_ext_ctrl)
+ return false;
+
+ return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:31 +0100
+Subject: media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-6-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.
+
+These helper functions do not really help. Move the code to the
+__get/put_v4l2_format32 functions.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 104 +++++---------------------
+ 1 file changed, 20 insertions(+), 84 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -89,78 +89,6 @@ static int put_v4l2_window32(struct v4l2
+ return 0;
+ }
+
+-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+-{
+- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+- struct v4l2_pix_format_mplane __user *up)
+-{
+- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+-{
+- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+- struct v4l2_pix_format_mplane __user *up)
+-{
+- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+-{
+- if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+-{
+- if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+-{
+- if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+-{
+- if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+-{
+- if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+-{
+- if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
+- return -EFAULT;
+- return 0;
+-}
+-
+ struct v4l2_format32 {
+ __u32 type; /* enum v4l2_buf_type */
+ union {
+@@ -199,23 +127,27 @@ static int __get_v4l2_format32(struct v4
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+- return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
++ return copy_from_user(&kp->fmt.pix, &up->fmt.pix,
++ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+- return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
+- &up->fmt.pix_mp);
++ return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+- return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
++ return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi,
++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+- return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
++ return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced,
++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+- return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
++ return copy_from_user(&kp->fmt.sdr, &up->fmt.sdr,
++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+ kp->type);
+@@ -246,23 +178,27 @@ static int __put_v4l2_format32(struct v4
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+- return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
++ return copy_to_user(&up->fmt.pix, &kp->fmt.pix,
++ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+- return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
+- &up->fmt.pix_mp);
++ return copy_to_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+- return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
++ return copy_to_user(&up->fmt.vbi, &kp->fmt.vbi,
++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+- return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
++ return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced,
++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+- return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
++ return copy_to_user(&up->fmt.sdr, &kp->fmt.sdr,
++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+ pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+ kp->type);
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:40 +0100
+Subject: media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Daniel Mentz <danielmentz@google.com>, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-15-hverkuil@xs4all.nl>
+
+From: Daniel Mentz <danielmentz@google.com>
+
+commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.
+
+The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
+equivalent. It converts 32-bit data structures into its 64-bit
+equivalents and needs to provide the data to the 64-bit ioctl in user
+space memory which is commonly allocated using
+compat_alloc_user_space().
+
+However, due to how that function is implemented, it can only be called
+a single time for every syscall invocation.
+
+Supposedly to avoid this limitation, the existing code uses a mix of
+memory from the kernel stack and memory allocated through
+compat_alloc_user_space().
+
+Under normal circumstances, this would not work, because the 64-bit
+ioctl expects all pointers to point to user space memory. As a
+workaround, set_fs(KERNEL_DS) is called to temporarily disable this
+extra safety check and allow kernel pointers. However, this might
+introduce a security vulnerability: The result of the 32-bit to 64-bit
+conversion is writeable by user space because the output buffer has been
+allocated via compat_alloc_user_space(). A malicious user space process
+could then manipulate pointers inside this output buffer, and due to the
+previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
+no longer prevent kernel memory access.
+
+The new approach is to pre-calculate the total amount of user space
+memory that is needed, allocate it using compat_alloc_user_space() and
+then divide up the allocated memory to accommodate all data structures
+that need to be converted.
+
+An alternative approach would have been to retain the union type karg
+that they allocated on the kernel stack in do_video_ioctl(), copy all
+data from user space into karg and then back to user space. However, we
+decided against this approach because it does not align with other
+compat syscall implementations. Instead, we tried to replicate the
+get_user/put_user pairs as found in other places in the kernel:
+
+ if (get_user(clipcount, &up->clipcount) ||
+ put_user(clipcount, &kp->clipcount)) return -EFAULT;
+
+Notes from hans.verkuil@cisco.com:
+
+This patch was taken from:
+ https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
+
+Clearly nobody could be bothered to upstream this patch or at minimum
+tell us :-( We only heard about this a week ago.
+
+This patch was rebased and cleaned up. Compared to the original I
+also swapped the order of the convert_in_user arguments so that they
+matched copy_in_user. It was hard to review otherwise. I also replaced
+the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
+
+Fixes: 6b5a9492ca ("v4l: introduce string control support.")
+
+Signed-off-by: Daniel Mentz <danielmentz@google.com>
+Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 752 ++++++++++++++++----------
+ 1 file changed, 487 insertions(+), 265 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -22,6 +22,14 @@
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-ioctl.h>
+
++/* Use the same argument order as copy_in_user */
++#define assign_in_user(to, from) \
++({ \
++ typeof(*from) __assign_tmp; \
++ \
++ get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
++})
++
+ static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+ long ret = -ENOIOCTLCMD;
+@@ -35,12 +43,12 @@ static long native_ioctl(struct file *fi
+
+ struct v4l2_clip32 {
+ struct v4l2_rect c;
+- compat_caddr_t next;
++ compat_caddr_t next;
+ };
+
+ struct v4l2_window32 {
+ struct v4l2_rect w;
+- __u32 field; /* enum v4l2_field */
++ __u32 field; /* enum v4l2_field */
+ __u32 chromakey;
+ compat_caddr_t clips; /* actually struct v4l2_clip32 * */
+ __u32 clipcount;
+@@ -48,37 +56,41 @@ struct v4l2_window32 {
+ __u8 global_alpha;
+ };
+
+-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
++static int get_v4l2_window32(struct v4l2_window __user *kp,
++ struct v4l2_window32 __user *up,
++ void __user *aux_buf, u32 aux_space)
+ {
+ struct v4l2_clip32 __user *uclips;
+ struct v4l2_clip __user *kclips;
+ compat_caddr_t p;
+- u32 n;
++ u32 clipcount;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+- get_user(kp->field, &up->field) ||
+- get_user(kp->chromakey, &up->chromakey) ||
+- get_user(kp->clipcount, &up->clipcount) ||
+- get_user(kp->global_alpha, &up->global_alpha))
++ copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
++ assign_in_user(&kp->field, &up->field) ||
++ assign_in_user(&kp->chromakey, &up->chromakey) ||
++ assign_in_user(&kp->global_alpha, &up->global_alpha) ||
++ get_user(clipcount, &up->clipcount) ||
++ put_user(clipcount, &kp->clipcount))
+ return -EFAULT;
+- if (kp->clipcount > 2048)
++ if (clipcount > 2048)
+ return -EINVAL;
+- if (!kp->clipcount) {
+- kp->clips = NULL;
+- return 0;
+- }
++ if (!clipcount)
++ return put_user(NULL, &kp->clips);
+
+- n = kp->clipcount;
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
+- kclips = compat_alloc_user_space(n * sizeof(*kclips));
+- kp->clips = kclips;
+- while (n--) {
++ if (aux_space < clipcount * sizeof(*kclips))
++ return -EFAULT;
++ kclips = aux_buf;
++ if (put_user(kclips, &kp->clips))
++ return -EFAULT;
++
++ while (clipcount--) {
+ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+- if (put_user(n ? kclips + 1 : NULL, &kclips->next))
++ if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
+ return -EFAULT;
+ uclips++;
+ kclips++;
+@@ -86,27 +98,28 @@ static int get_v4l2_window32(struct v4l2
+ return 0;
+ }
+
+-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
++static int put_v4l2_window32(struct v4l2_window __user *kp,
++ struct v4l2_window32 __user *up)
+ {
+ struct v4l2_clip __user *kclips = kp->clips;
+ struct v4l2_clip32 __user *uclips;
+- u32 n = kp->clipcount;
+ compat_caddr_t p;
++ u32 clipcount;
+
+- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
+- put_user(kp->field, &up->field) ||
+- put_user(kp->chromakey, &up->chromakey) ||
+- put_user(kp->clipcount, &up->clipcount) ||
+- put_user(kp->global_alpha, &up->global_alpha))
++ if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
++ assign_in_user(&up->field, &kp->field) ||
++ assign_in_user(&up->chromakey, &kp->chromakey) ||
++ assign_in_user(&up->global_alpha, &kp->global_alpha) ||
++ get_user(clipcount, &kp->clipcount) ||
++ put_user(clipcount, &up->clipcount))
+ return -EFAULT;
+-
+- if (!kp->clipcount)
++ if (!clipcount)
+ return 0;
+
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
+- while (n--) {
++ while (clipcount--) {
+ if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ uclips++;
+@@ -145,101 +158,158 @@ struct v4l2_create_buffers32 {
+ __u32 reserved[8];
+ };
+
+-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
++static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
++{
++ u32 type;
++
++ if (get_user(type, &up->type))
++ return -EFAULT;
++
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
++ u32 clipcount;
++
++ if (get_user(clipcount, &up->fmt.win.clipcount))
++ return -EFAULT;
++ if (clipcount > 2048)
++ return -EINVAL;
++ *size = clipcount * sizeof(struct v4l2_clip);
++ return 0;
++ }
++ default:
++ *size = 0;
++ return 0;
++ }
++}
++
++static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
+ {
+- if (get_user(kp->type, &up->type))
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+ return -EFAULT;
++ return __bufsize_v4l2_format(up, size);
++}
+
+- switch (kp->type) {
++static int __get_v4l2_format32(struct v4l2_format __user *kp,
++ struct v4l2_format32 __user *up,
++ void __user *aux_buf, u32 aux_space)
++{
++ u32 type;
++
++ if (get_user(type, &up->type) || put_user(type, &kp->type))
++ return -EFAULT;
++
++ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+- return copy_from_user(&kp->fmt.pix, &up->fmt.pix,
+- sizeof(kp->fmt.pix)) ? -EFAULT : 0;
++ return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
++ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+- return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
+- sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
++ return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+- return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
++ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
++ aux_buf, aux_space);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+- return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi,
+- sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
++ return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+- return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced,
+- sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
++ return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+- return copy_from_user(&kp->fmt.sdr, &up->fmt.sdr,
+- sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
++ return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+ return -EINVAL;
+ }
+ }
+
+-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
++static int get_v4l2_format32(struct v4l2_format __user *kp,
++ struct v4l2_format32 __user *up,
++ void __user *aux_buf, u32 aux_space)
++{
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
++ return -EFAULT;
++ return __get_v4l2_format32(kp, up, aux_buf, aux_space);
++}
++
++static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
++ u32 *size)
+ {
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+ return -EFAULT;
+- return __get_v4l2_format32(kp, up);
++ return __bufsize_v4l2_format(&up->format, size);
+ }
+
+-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
++static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
++ struct v4l2_create_buffers32 __user *up,
++ void __user *aux_buf, u32 aux_space)
+ {
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
++ copy_in_user(kp, up,
++ offsetof(struct v4l2_create_buffers32, format)))
+ return -EFAULT;
+- return __get_v4l2_format32(&kp->format, &up->format);
++ return __get_v4l2_format32(&kp->format, &up->format,
++ aux_buf, aux_space);
+ }
+
+-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
++static int __put_v4l2_format32(struct v4l2_format __user *kp,
++ struct v4l2_format32 __user *up)
+ {
+- if (put_user(kp->type, &up->type))
++ u32 type;
++
++ if (get_user(type, &kp->type))
+ return -EFAULT;
+
+- switch (kp->type) {
++ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+- return copy_to_user(&up->fmt.pix, &kp->fmt.pix,
++ return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+- return copy_to_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
++ return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+- return copy_to_user(&up->fmt.vbi, &kp->fmt.vbi,
++ return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+- return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced,
++ return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
+ case V4L2_BUF_TYPE_SDR_CAPTURE:
+ case V4L2_BUF_TYPE_SDR_OUTPUT:
+- return copy_to_user(&up->fmt.sdr, &kp->fmt.sdr,
++ return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
+ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
+ default:
+ return -EINVAL;
+ }
+ }
+
+-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
++static int put_v4l2_format32(struct v4l2_format __user *kp,
++ struct v4l2_format32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
+ return -EFAULT;
+ return __put_v4l2_format32(kp, up);
+ }
+
+-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
++static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
++ struct v4l2_create_buffers32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
++ copy_in_user(up, kp,
++ offsetof(struct v4l2_create_buffers32, format)) ||
++ copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+ return __put_v4l2_format32(&kp->format, &up->format);
+ }
+@@ -253,24 +323,27 @@ struct v4l2_standard32 {
+ __u32 reserved[4];
+ };
+
+-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
++static int get_v4l2_standard32(struct v4l2_standard __user *kp,
++ struct v4l2_standard32 __user *up)
+ {
+ /* other fields are not set by the user, nor used by the driver */
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- get_user(kp->index, &up->index))
++ assign_in_user(&kp->index, &up->index))
+ return -EFAULT;
+ return 0;
+ }
+
+-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
++static int put_v4l2_standard32(struct v4l2_standard __user *kp,
++ struct v4l2_standard32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(kp->index, &up->index) ||
+- put_user(kp->id, &up->id) ||
+- copy_to_user(up->name, kp->name, sizeof(up->name)) ||
+- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
+- put_user(kp->framelines, &up->framelines) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
++ assign_in_user(&up->index, &kp->index) ||
++ assign_in_user(&up->id, &kp->id) ||
++ copy_in_user(up->name, kp->name, sizeof(up->name)) ||
++ copy_in_user(&up->frameperiod, &kp->frameperiod,
++ sizeof(up->frameperiod)) ||
++ assign_in_user(&up->framelines, &kp->framelines) ||
++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -310,11 +383,11 @@ struct v4l2_buffer32 {
+ __u32 reserved;
+ };
+
+-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
++static int get_v4l2_plane32(struct v4l2_plane __user *up,
++ struct v4l2_plane32 __user *up32,
+ enum v4l2_memory memory)
+ {
+- void __user *up_pln;
+- compat_long_t p;
++ compat_ulong_t p;
+
+ if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
+ copy_in_user(&up->data_offset, &up32->data_offset,
+@@ -329,10 +402,8 @@ static int get_v4l2_plane32(struct v4l2_
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+- if (get_user(p, &up32->m.userptr))
+- return -EFAULT;
+- up_pln = compat_ptr(p);
+- if (put_user((unsigned long)up_pln, &up->m.userptr))
++ if (get_user(p, &up32->m.userptr) ||
++ put_user((unsigned long)compat_ptr(p), &up->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_DMABUF:
+@@ -344,7 +415,8 @@ static int get_v4l2_plane32(struct v4l2_
+ return 0;
+ }
+
+-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
++static int put_v4l2_plane32(struct v4l2_plane __user *up,
++ struct v4l2_plane32 __user *up32,
+ enum v4l2_memory memory)
+ {
+ unsigned long p;
+@@ -368,8 +440,7 @@ static int put_v4l2_plane32(struct v4l2_
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_DMABUF:
+- if (copy_in_user(&up32->m.fd, &up->m.fd,
+- sizeof(up->m.fd)))
++ if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
+ return -EFAULT;
+ break;
+ }
+@@ -377,37 +448,75 @@ static int put_v4l2_plane32(struct v4l2_
+ return 0;
+ }
+
+-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
++static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
+ {
++ u32 type;
++ u32 length;
++
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
++ get_user(type, &up->type) ||
++ get_user(length, &up->length))
++ return -EFAULT;
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
++ if (length > VIDEO_MAX_PLANES)
++ return -EINVAL;
++
++ /*
++ * We don't really care if userspace decides to kill itself
++ * by passing a very big length value
++ */
++ *size = length * sizeof(struct v4l2_plane);
++ } else {
++ *size = 0;
++ }
++ return 0;
++}
++
++static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
++ struct v4l2_buffer32 __user *up,
++ void __user *aux_buf, u32 aux_space)
++{
++ u32 type;
++ u32 length;
++ enum v4l2_memory memory;
+ struct v4l2_plane32 __user *uplane32;
+ struct v4l2_plane __user *uplane;
+ compat_caddr_t p;
+- int num_planes;
+ int ret;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- get_user(kp->index, &up->index) ||
+- get_user(kp->type, &up->type) ||
+- get_user(kp->flags, &up->flags) ||
+- get_user(kp->memory, &up->memory) ||
+- get_user(kp->length, &up->length))
+- return -EFAULT;
+-
+- if (V4L2_TYPE_IS_OUTPUT(kp->type))
+- if (get_user(kp->bytesused, &up->bytesused) ||
+- get_user(kp->field, &up->field) ||
+- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec))
++ assign_in_user(&kp->index, &up->index) ||
++ get_user(type, &up->type) ||
++ put_user(type, &kp->type) ||
++ assign_in_user(&kp->flags, &up->flags) ||
++ get_user(memory, &up->memory) ||
++ put_user(memory, &kp->memory) ||
++ get_user(length, &up->length) ||
++ put_user(length, &kp->length))
++ return -EFAULT;
++
++ if (V4L2_TYPE_IS_OUTPUT(type))
++ if (assign_in_user(&kp->bytesused, &up->bytesused) ||
++ assign_in_user(&kp->field, &up->field) ||
++ assign_in_user(&kp->timestamp.tv_sec,
++ &up->timestamp.tv_sec) ||
++ assign_in_user(&kp->timestamp.tv_usec,
++ &up->timestamp.tv_usec))
+ return -EFAULT;
+
+- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+- num_planes = kp->length;
++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
++ u32 num_planes = length;
++
+ if (num_planes == 0) {
+- kp->m.planes = NULL;
+- /* num_planes == 0 is legal, e.g. when userspace doesn't
+- * need planes array on DQBUF*/
+- return 0;
++ /*
++ * num_planes == 0 is legal, e.g. when userspace doesn't
++ * need planes array on DQBUF
++ */
++ return put_user(NULL, &kp->m.planes);
+ }
++ if (num_planes > VIDEO_MAX_PLANES)
++ return -EINVAL;
+
+ if (get_user(p, &up->m.planes))
+ return -EFAULT;
+@@ -417,37 +526,43 @@ static int get_v4l2_buffer32(struct v4l2
+ num_planes * sizeof(*uplane32)))
+ return -EFAULT;
+
+- /* We don't really care if userspace decides to kill itself
+- * by passing a very big num_planes value */
+- uplane = compat_alloc_user_space(num_planes * sizeof(*uplane));
+- kp->m.planes = (__force struct v4l2_plane *)uplane;
++ /*
++ * We don't really care if userspace decides to kill itself
++ * by passing a very big num_planes value
++ */
++ if (aux_space < num_planes * sizeof(*uplane))
++ return -EFAULT;
++
++ uplane = aux_buf;
++ if (put_user((__force struct v4l2_plane *)uplane,
++ &kp->m.planes))
++ return -EFAULT;
+
+- while (--num_planes >= 0) {
+- ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
++ while (num_planes--) {
++ ret = get_v4l2_plane32(uplane, uplane32, memory);
+ if (ret)
+ return ret;
+- ++uplane;
+- ++uplane32;
++ uplane++;
++ uplane32++;
+ }
+ } else {
+- switch (kp->memory) {
++ switch (memory) {
+ case V4L2_MEMORY_MMAP:
+ case V4L2_MEMORY_OVERLAY:
+- if (get_user(kp->m.offset, &up->m.offset))
++ if (assign_in_user(&kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+- case V4L2_MEMORY_USERPTR:
+- {
+- compat_long_t tmp;
+-
+- if (get_user(tmp, &up->m.userptr))
+- return -EFAULT;
++ case V4L2_MEMORY_USERPTR: {
++ compat_ulong_t userptr;
+
+- kp->m.userptr = (unsigned long)compat_ptr(tmp);
+- }
++ if (get_user(userptr, &up->m.userptr) ||
++ put_user((unsigned long)compat_ptr(userptr),
++ &kp->m.userptr))
++ return -EFAULT;
+ break;
++ }
+ case V4L2_MEMORY_DMABUF:
+- if (get_user(kp->m.fd, &up->m.fd))
++ if (assign_in_user(&kp->m.fd, &up->m.fd))
+ return -EFAULT;
+ break;
+ }
+@@ -456,62 +571,70 @@ static int get_v4l2_buffer32(struct v4l2
+ return 0;
+ }
+
+-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
++static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
++ struct v4l2_buffer32 __user *up)
+ {
++ u32 type;
++ u32 length;
++ enum v4l2_memory memory;
+ struct v4l2_plane32 __user *uplane32;
+ struct v4l2_plane __user *uplane;
+ compat_caddr_t p;
+- int num_planes;
+ int ret;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(kp->index, &up->index) ||
+- put_user(kp->type, &up->type) ||
+- put_user(kp->flags, &up->flags) ||
+- put_user(kp->memory, &up->memory))
+- return -EFAULT;
+-
+- if (put_user(kp->bytesused, &up->bytesused) ||
+- put_user(kp->field, &up->field) ||
+- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
+- copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
+- put_user(kp->sequence, &up->sequence) ||
+- put_user(kp->reserved2, &up->reserved2) ||
+- put_user(kp->reserved, &up->reserved) ||
+- put_user(kp->length, &up->length))
++ assign_in_user(&up->index, &kp->index) ||
++ get_user(type, &kp->type) ||
++ put_user(type, &up->type) ||
++ assign_in_user(&up->flags, &kp->flags) ||
++ get_user(memory, &kp->memory) ||
++ put_user(memory, &up->memory))
++ return -EFAULT;
++
++ if (assign_in_user(&up->bytesused, &kp->bytesused) ||
++ assign_in_user(&up->field, &kp->field) ||
++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
++ assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
++ copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
++ assign_in_user(&up->sequence, &kp->sequence) ||
++ assign_in_user(&up->reserved2, &kp->reserved2) ||
++ assign_in_user(&up->reserved, &kp->reserved) ||
++ get_user(length, &kp->length) ||
++ put_user(length, &up->length))
+ return -EFAULT;
+
+- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+- num_planes = kp->length;
++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
++ u32 num_planes = length;
++
+ if (num_planes == 0)
+ return 0;
+
+- uplane = (__force struct v4l2_plane __user *)kp->m.planes;
++ if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
++ return -EFAULT;
+ if (get_user(p, &up->m.planes))
+ return -EFAULT;
+ uplane32 = compat_ptr(p);
+
+- while (--num_planes >= 0) {
+- ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
++ while (num_planes--) {
++ ret = put_v4l2_plane32(uplane, uplane32, memory);
+ if (ret)
+ return ret;
+ ++uplane;
+ ++uplane32;
+ }
+ } else {
+- switch (kp->memory) {
++ switch (memory) {
+ case V4L2_MEMORY_MMAP:
+ case V4L2_MEMORY_OVERLAY:
+- if (put_user(kp->m.offset, &up->m.offset))
++ if (assign_in_user(&up->m.offset, &kp->m.offset))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+- if (put_user(kp->m.userptr, &up->m.userptr))
++ if (assign_in_user(&up->m.userptr, &kp->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_DMABUF:
+- if (put_user(kp->m.fd, &up->m.fd))
++ if (assign_in_user(&up->m.fd, &kp->m.fd))
+ return -EFAULT;
+ break;
+ }
+@@ -523,7 +646,7 @@ static int put_v4l2_buffer32(struct v4l2
+ struct v4l2_framebuffer32 {
+ __u32 capability;
+ __u32 flags;
+- compat_caddr_t base;
++ compat_caddr_t base;
+ struct {
+ __u32 width;
+ __u32 height;
+@@ -536,29 +659,32 @@ struct v4l2_framebuffer32 {
+ } fmt;
+ };
+
+-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
++static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
++ struct v4l2_framebuffer32 __user *up)
+ {
+- u32 tmp;
++ compat_caddr_t tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(tmp, &up->base) ||
+- get_user(kp->capability, &up->capability) ||
+- get_user(kp->flags, &up->flags) ||
+- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
++ put_user((__force void *)compat_ptr(tmp), &kp->base) ||
++ assign_in_user(&kp->capability, &up->capability) ||
++ assign_in_user(&kp->flags, &up->flags) ||
++ copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
+ return -EFAULT;
+- kp->base = (__force void *)compat_ptr(tmp);
+ return 0;
+ }
+
+-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
++static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
++ struct v4l2_framebuffer32 __user *up)
+ {
+- u32 tmp = (u32)((unsigned long)kp->base);
++ void *base;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(tmp, &up->base) ||
+- put_user(kp->capability, &up->capability) ||
+- put_user(kp->flags, &up->flags) ||
+- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
++ get_user(base, &kp->base) ||
++ put_user(ptr_to_compat(base), &up->base) ||
++ assign_in_user(&up->capability, &kp->capability) ||
++ assign_in_user(&up->flags, &kp->flags) ||
++ copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -571,21 +697,26 @@ struct v4l2_input32 {
+ __u32 tuner; /* Associated tuner */
+ compat_u64 std;
+ __u32 status;
+- __u32 reserved[4];
++ __u32 capabilities;
++ __u32 reserved[3];
+ };
+
+-/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
+- Otherwise it is identical to the 32-bit version. */
+-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
++/*
++ * The 64-bit v4l2_input struct has extra padding at the end of the struct.
++ * Otherwise it is identical to the 32-bit version.
++ */
++static inline int get_v4l2_input32(struct v4l2_input __user *kp,
++ struct v4l2_input32 __user *up)
+ {
+- if (copy_from_user(kp, up, sizeof(*up)))
++ if (copy_in_user(kp, up, sizeof(*up)))
+ return -EFAULT;
+ return 0;
+ }
+
+-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
++static inline int put_v4l2_input32(struct v4l2_input __user *kp,
++ struct v4l2_input32 __user *up)
+ {
+- if (copy_to_user(up, kp, sizeof(*up)))
++ if (copy_in_user(up, kp, sizeof(*up)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -639,40 +770,64 @@ static inline bool ctrl_is_pointer(struc
+ (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
+ }
+
++static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
++ u32 *size)
++{
++ u32 count;
++
++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
++ get_user(count, &up->count))
++ return -EFAULT;
++ if (count > V4L2_CID_MAX_CTRLS)
++ return -EINVAL;
++ *size = count * sizeof(struct v4l2_ext_control);
++ return 0;
++}
++
+ static int get_v4l2_ext_controls32(struct file *file,
+- struct v4l2_ext_controls *kp,
+- struct v4l2_ext_controls32 __user *up)
++ struct v4l2_ext_controls __user *kp,
++ struct v4l2_ext_controls32 __user *up,
++ void __user *aux_buf, u32 aux_space)
+ {
+ struct v4l2_ext_control32 __user *ucontrols;
+ struct v4l2_ext_control __user *kcontrols;
+- int n;
++ u32 count;
++ u32 n;
+ compat_caddr_t p;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- get_user(kp->ctrl_class, &up->ctrl_class) ||
+- get_user(kp->count, &up->count) ||
+- get_user(kp->error_idx, &up->error_idx) ||
+- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+- return -EFAULT;
+- n = kp->count;
+- if (n == 0) {
+- kp->controls = NULL;
+- return 0;
+- }
++ assign_in_user(&kp->ctrl_class, &up->ctrl_class) ||
++ get_user(count, &up->count) ||
++ put_user(count, &kp->count) ||
++ assign_in_user(&kp->error_idx, &up->error_idx) ||
++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
++ return -EFAULT;
++
++ if (count == 0)
++ return put_user(NULL, &kp->controls);
++ if (count > V4L2_CID_MAX_CTRLS)
++ return -EINVAL;
+ if (get_user(p, &up->controls))
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+- if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(*ucontrols)))
++ if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
++ return -EFAULT;
++ if (aux_space < count * sizeof(*kcontrols))
+ return -EFAULT;
+- kcontrols = compat_alloc_user_space(n * sizeof(*kcontrols));
+- kp->controls = (__force struct v4l2_ext_control *)kcontrols;
+- while (--n >= 0) {
++ kcontrols = aux_buf;
++ if (put_user((__force struct v4l2_ext_control *)kcontrols,
++ &kp->controls))
++ return -EFAULT;
++
++ for (n = 0; n < count; n++) {
+ u32 id;
+
+ if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
+ return -EFAULT;
++
+ if (get_user(id, &kcontrols->id))
+ return -EFAULT;
++
+ if (ctrl_is_pointer(file, id)) {
+ void __user *s;
+
+@@ -689,43 +844,54 @@ static int get_v4l2_ext_controls32(struc
+ }
+
+ static int put_v4l2_ext_controls32(struct file *file,
+- struct v4l2_ext_controls *kp,
++ struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
+ {
+ struct v4l2_ext_control32 __user *ucontrols;
+- struct v4l2_ext_control __user *kcontrols =
+- (__force struct v4l2_ext_control __user *)kp->controls;
+- int n = kp->count;
++ struct v4l2_ext_control __user *kcontrols;
++ u32 count;
++ u32 n;
+ compat_caddr_t p;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(kp->ctrl_class, &up->ctrl_class) ||
+- put_user(kp->count, &up->count) ||
+- put_user(kp->error_idx, &up->error_idx) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
++ assign_in_user(&up->ctrl_class, &kp->ctrl_class) ||
++ get_user(count, &kp->count) ||
++ put_user(count, &up->count) ||
++ assign_in_user(&up->error_idx, &kp->error_idx) ||
++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
++ get_user(kcontrols, &kp->controls))
+ return -EFAULT;
+- if (!kp->count)
+- return 0;
+
++ if (!count)
++ return 0;
+ if (get_user(p, &up->controls))
+ return -EFAULT;
+ ucontrols = compat_ptr(p);
+- if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols)))
++ if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
+ return -EFAULT;
+
+- while (--n >= 0) {
+- unsigned size = sizeof(*ucontrols);
++ for (n = 0; n < count; n++) {
++ unsigned int size = sizeof(*ucontrols);
+ u32 id;
+
+- if (get_user(id, &kcontrols->id))
++ if (get_user(id, &kcontrols->id) ||
++ put_user(id, &ucontrols->id) ||
++ assign_in_user(&ucontrols->size, &kcontrols->size) ||
++ copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
++ sizeof(ucontrols->reserved2)))
+ return -EFAULT;
+- /* Do not modify the pointer when copying a pointer control.
+- The contents of the pointer was changed, not the pointer
+- itself. */
++
++ /*
++ * Do not modify the pointer when copying a pointer control.
++ * The contents of the pointer was changed, not the pointer
++ * itself.
++ */
+ if (ctrl_is_pointer(file, id))
+ size -= sizeof(ucontrols->value64);
++
+ if (copy_in_user(ucontrols, kcontrols, size))
+ return -EFAULT;
++
+ ucontrols++;
+ kcontrols++;
+ }
+@@ -745,17 +911,18 @@ struct v4l2_event32 {
+ __u32 reserved[8];
+ };
+
+-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
++static int put_v4l2_event32(struct v4l2_event __user *kp,
++ struct v4l2_event32 __user *up)
+ {
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(kp->type, &up->type) ||
+- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
+- put_user(kp->pending, &up->pending) ||
+- put_user(kp->sequence, &up->sequence) ||
+- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+- put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
+- put_user(kp->id, &up->id) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
++ assign_in_user(&up->type, &kp->type) ||
++ copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
++ assign_in_user(&up->pending, &kp->pending) ||
++ assign_in_user(&up->sequence, &kp->sequence) ||
++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
++ assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
++ assign_in_user(&up->id, &kp->id) ||
++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -768,31 +935,34 @@ struct v4l2_edid32 {
+ compat_caddr_t edid;
+ };
+
+-static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
++static int get_v4l2_edid32(struct v4l2_edid __user *kp,
++ struct v4l2_edid32 __user *up)
+ {
+- u32 tmp;
++ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+- get_user(kp->pad, &up->pad) ||
+- get_user(kp->start_block, &up->start_block) ||
+- get_user(kp->blocks, &up->blocks) ||
++ assign_in_user(&kp->pad, &up->pad) ||
++ assign_in_user(&kp->start_block, &up->start_block) ||
++ assign_in_user(&kp->blocks, &up->blocks) ||
+ get_user(tmp, &up->edid) ||
+- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
++ put_user(compat_ptr(tmp), &kp->edid) ||
++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
+- kp->edid = (__force u8 *)compat_ptr(tmp);
+ return 0;
+ }
+
+-static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
++static int put_v4l2_edid32(struct v4l2_edid __user *kp,
++ struct v4l2_edid32 __user *up)
+ {
+- u32 tmp = (u32)((unsigned long)kp->edid);
++ void *edid;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+- put_user(kp->pad, &up->pad) ||
+- put_user(kp->start_block, &up->start_block) ||
+- put_user(kp->blocks, &up->blocks) ||
+- put_user(tmp, &up->edid) ||
+- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
++ assign_in_user(&up->pad, &kp->pad) ||
++ assign_in_user(&up->start_block, &kp->start_block) ||
++ assign_in_user(&up->blocks, &kp->blocks) ||
++ get_user(edid, &kp->edid) ||
++ put_user(ptr_to_compat(edid), &up->edid) ||
++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -809,7 +979,7 @@ static int put_v4l2_edid32(struct v4l2_e
+ #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
+ #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
+ #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
+-#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
++#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
+ #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
+ #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
+ #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
+@@ -825,22 +995,23 @@ static int put_v4l2_edid32(struct v4l2_e
+ #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
+ #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
+
++static int alloc_userspace(unsigned int size, u32 aux_space,
++ void __user **up_native)
++{
++ *up_native = compat_alloc_user_space(size + aux_space);
++ if (!*up_native)
++ return -ENOMEM;
++ if (clear_user(*up_native, size))
++ return -EFAULT;
++ return 0;
++}
++
+ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+- union {
+- struct v4l2_format v2f;
+- struct v4l2_buffer v2b;
+- struct v4l2_framebuffer v2fb;
+- struct v4l2_input v2i;
+- struct v4l2_standard v2s;
+- struct v4l2_ext_controls v2ecs;
+- struct v4l2_event v2ev;
+- struct v4l2_create_buffers v2crt;
+- struct v4l2_edid v2edid;
+- unsigned long vx;
+- int vi;
+- } karg;
+ void __user *up = compat_ptr(arg);
++ void __user *up_native = NULL;
++ void __user *aux_buf;
++ u32 aux_space;
+ int compatible_arg = 1;
+ long err = 0;
+
+@@ -879,30 +1050,52 @@ static long do_video_ioctl(struct file *
+ case VIDIOC_STREAMOFF:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_S_OUTPUT:
+- err = get_user(karg.vi, (s32 __user *)up);
++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
++ if (!err && assign_in_user((unsigned int __user *)up_native,
++ (compat_uint_t __user *)up))
++ err = -EFAULT;
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_INPUT:
+ case VIDIOC_G_OUTPUT:
++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_EDID:
+ case VIDIOC_S_EDID:
+- err = get_v4l2_edid32(&karg.v2edid, up);
++ err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
++ if (!err)
++ err = get_v4l2_edid32(up_native, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+- err = get_v4l2_format32(&karg.v2f, up);
++ err = bufsize_v4l2_format(up, &aux_space);
++ if (!err)
++ err = alloc_userspace(sizeof(struct v4l2_format),
++ aux_space, &up_native);
++ if (!err) {
++ aux_buf = up_native + sizeof(struct v4l2_format);
++ err = get_v4l2_format32(up_native, up,
++ aux_buf, aux_space);
++ }
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_CREATE_BUFS:
+- err = get_v4l2_create32(&karg.v2crt, up);
++ err = bufsize_v4l2_create(up, &aux_space);
++ if (!err)
++ err = alloc_userspace(sizeof(struct v4l2_create_buffers),
++ aux_space, &up_native);
++ if (!err) {
++ aux_buf = up_native + sizeof(struct v4l2_create_buffers);
++ err = get_v4l2_create32(up_native, up,
++ aux_buf, aux_space);
++ }
+ compatible_arg = 0;
+ break;
+
+@@ -910,36 +1103,63 @@ static long do_video_ioctl(struct file *
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+- err = get_v4l2_buffer32(&karg.v2b, up);
++ err = bufsize_v4l2_buffer(up, &aux_space);
++ if (!err)
++ err = alloc_userspace(sizeof(struct v4l2_buffer),
++ aux_space, &up_native);
++ if (!err) {
++ aux_buf = up_native + sizeof(struct v4l2_buffer);
++ err = get_v4l2_buffer32(up_native, up,
++ aux_buf, aux_space);
++ }
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_S_FBUF:
+- err = get_v4l2_framebuffer32(&karg.v2fb, up);
++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
++ &up_native);
++ if (!err)
++ err = get_v4l2_framebuffer32(up_native, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_FBUF:
++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
++ &up_native);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMSTD:
+- err = get_v4l2_standard32(&karg.v2s, up);
++ err = alloc_userspace(sizeof(struct v4l2_standard), 0,
++ &up_native);
++ if (!err)
++ err = get_v4l2_standard32(up_native, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMINPUT:
+- err = get_v4l2_input32(&karg.v2i, up);
++ err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
++ if (!err)
++ err = get_v4l2_input32(up_native, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+- err = get_v4l2_ext_controls32(file, &karg.v2ecs, up);
++ err = bufsize_v4l2_ext_controls(up, &aux_space);
++ if (!err)
++ err = alloc_userspace(sizeof(struct v4l2_ext_controls),
++ aux_space, &up_native);
++ if (!err) {
++ aux_buf = up_native + sizeof(struct v4l2_ext_controls);
++ err = get_v4l2_ext_controls32(file, up_native, up,
++ aux_buf, aux_space);
++ }
+ compatible_arg = 0;
+ break;
+ case VIDIOC_DQEVENT:
++ err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
+ compatible_arg = 0;
+ break;
+ }
+@@ -948,25 +1168,26 @@ static long do_video_ioctl(struct file *
+
+ if (compatible_arg)
+ err = native_ioctl(file, cmd, (unsigned long)up);
+- else {
+- mm_segment_t old_fs = get_fs();
+-
+- set_fs(KERNEL_DS);
+- err = native_ioctl(file, cmd, (unsigned long)&karg);
+- set_fs(old_fs);
+- }
++ else
++ err = native_ioctl(file, cmd, (unsigned long)up_native);
+
+ if (err == -ENOTTY)
+ return err;
+
+- /* Special case: even after an error we need to put the
+- results back for these ioctls since the error_idx will
+- contain information on which control failed. */
++ /*
++ * Special case: even after an error we need to put the
++ * results back for these ioctls since the error_idx will
++ * contain information on which control failed.
++ */
+ switch (cmd) {
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+- if (put_v4l2_ext_controls32(file, &karg.v2ecs, up))
++ if (put_v4l2_ext_controls32(file, up_native, up))
++ err = -EFAULT;
++ break;
++ case VIDIOC_S_EDID:
++ if (put_v4l2_edid32(up_native, up))
+ err = -EFAULT;
+ break;
+ }
+@@ -978,45 +1199,46 @@ static long do_video_ioctl(struct file *
+ case VIDIOC_S_OUTPUT:
+ case VIDIOC_G_INPUT:
+ case VIDIOC_G_OUTPUT:
+- err = put_user(((s32)karg.vi), (s32 __user *)up);
++ if (assign_in_user((compat_uint_t __user *)up,
++ ((unsigned int __user *)up_native)))
++ err = -EFAULT;
+ break;
+
+ case VIDIOC_G_FBUF:
+- err = put_v4l2_framebuffer32(&karg.v2fb, up);
++ err = put_v4l2_framebuffer32(up_native, up);
+ break;
+
+ case VIDIOC_DQEVENT:
+- err = put_v4l2_event32(&karg.v2ev, up);
++ err = put_v4l2_event32(up_native, up);
+ break;
+
+ case VIDIOC_G_EDID:
+- case VIDIOC_S_EDID:
+- err = put_v4l2_edid32(&karg.v2edid, up);
++ err = put_v4l2_edid32(up_native, up);
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+- err = put_v4l2_format32(&karg.v2f, up);
++ err = put_v4l2_format32(up_native, up);
+ break;
+
+ case VIDIOC_CREATE_BUFS:
+- err = put_v4l2_create32(&karg.v2crt, up);
++ err = put_v4l2_create32(up_native, up);
+ break;
+
+ case VIDIOC_PREPARE_BUF:
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+- err = put_v4l2_buffer32(&karg.v2b, up);
++ err = put_v4l2_buffer32(up_native, up);
+ break;
+
+ case VIDIOC_ENUMSTD:
+- err = put_v4l2_standard32(&karg.v2s, up);
++ err = put_v4l2_standard32(up_native, up);
+ break;
+
+ case VIDIOC_ENUMINPUT:
+- err = put_v4l2_input32(&karg.v2i, up);
++ err = put_v4l2_input32(up_native, up);
+ break;
+ }
+ return err;
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:27 +0100
+Subject: media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-2-hverkuil@xs4all.nl>
+
+From: Hans Verkuil <hans.verkuil@cisco.com>
+
+commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.
+
+If the ioctl returned -ENOTTY, then don't bother copying
+back the result as there is no point.
+
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-ioctl.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -2783,8 +2783,11 @@ video_usercopy(struct file *file, unsign
+
+ /* Handles IOCTL */
+ err = func(file, cmd, parg);
+- if (err == -ENOIOCTLCMD)
++ if (err == -ENOTTY || err == -ENOIOCTLCMD) {
+ err = -ENOTTY;
++ goto out;
++ }
++
+ if (err == 0) {
+ if (cmd == VIDIOC_DQBUF)
+ trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
--- /dev/null
+From 5a0ec388ef0f6e33841aeb810d7fa23f049ec4cd Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Tue, 2 Jan 2018 11:39:47 -0800
+Subject: pktcdvd: Fix pkt_setup_dev() error path
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit 5a0ec388ef0f6e33841aeb810d7fa23f049ec4cd upstream.
+
+Commit 523e1d399ce0 ("block: make gendisk hold a reference to its queue")
+modified add_disk() and disk_release() but did not update any of the
+error paths that trigger a put_disk() call after disk->queue has been
+assigned. That introduced the following behavior in the pktcdvd driver
+if pkt_new_dev() fails:
+
+Kernel BUG at 00000000e98fd882 [verbose debug info unavailable]
+
+Since disk_release() calls blk_put_queue() anyway if disk->queue != NULL,
+fix this by removing the blk_cleanup_queue() call from the pkt_setup_dev()
+error path.
+
+Fixes: commit 523e1d399ce0 ("block: make gendisk hold a reference to its queue")
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/pktcdvd.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/block/pktcdvd.c
++++ b/drivers/block/pktcdvd.c
+@@ -2779,7 +2779,7 @@ static int pkt_setup_dev(dev_t dev, dev_
+ pd->pkt_dev = MKDEV(pktdev_major, idx);
+ ret = pkt_new_dev(pd, dev);
+ if (ret)
+- goto out_new_dev;
++ goto out_mem2;
+
+ /* inherit events of the host device */
+ disk->events = pd->bdev->bd_disk->events;
+@@ -2797,8 +2797,6 @@ static int pkt_setup_dev(dev_t dev, dev_
+ mutex_unlock(&ctl_mutex);
+ return 0;
+
+-out_new_dev:
+- blk_cleanup_queue(disk->queue);
+ out_mem2:
+ put_disk(disk);
+ out_mem:
--- /dev/null
+From 7d06d5895c159f64c46560dc258e553ad8670fe0 Mon Sep 17 00:00:00 2001
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Date: Wed, 20 Dec 2017 19:00:07 +0800
+Subject: Revert "Bluetooth: btusb: fix QCA Rome suspend/resume"
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+commit 7d06d5895c159f64c46560dc258e553ad8670fe0 upstream.
+
+This reverts commit fd865802c66bc451dc515ed89360f84376ce1a56.
+
+This commit causes a regression on some QCA ROME chips. The USB device
+reset happens in btusb_open(), hence firmware loading gets interrupted.
+
+Furthermore, this commit stops working after commit
+("a0085f2510e8976614ad8f766b209448b385492f Bluetooth: btusb: driver to
+enable the usb-wakeup feature"). Reset-resume quirk only gets enabled in
+btusb_suspend() when it's not a wakeup source.
+
+If we really want to reset the USB device, we need to do it before
+btusb_open(). Let's handle it in drivers/usb/core/quirks.c.
+
+Cc: Leif Liddy <leif.linux@gmail.com>
+Cc: Matthias Kaehlcke <mka@chromium.org>
+Cc: Brian Norris <briannorris@chromium.org>
+Cc: Daniel Drake <drake@endlessm.com>
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Tested-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/bluetooth/btusb.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -2969,12 +2969,6 @@ static int btusb_probe(struct usb_interf
+ if (id->driver_info & BTUSB_QCA_ROME) {
+ data->setup_on_usb = btusb_setup_qca;
+ hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
+-
+- /* QCA Rome devices lose their updated firmware over suspend,
+- * but the USB hub doesn't notice any status change.
+- * Explicitly request a device reset on resume.
+- */
+- set_bit(BTUSB_RESET_RESUME, &data->flags);
+ }
+
+ #ifdef CONFIG_BT_HCIBTUSB_RTL
crypto-cryptd-pass-through-absence-of-setkey.patch
crypto-poly1305-remove-setkey-method.patch
nsfs-mark-dentry-with-dcache_rcuaccess.patch
+media-v4l2-ioctl.c-don-t-copy-back-the-result-for-enotty.patch
+vb2-v4l2_buf_flag_done-is-set-after-dqbuf.patch
+media-v4l2-compat-ioctl32.c-add-missing-vidioc_prepare_buf.patch
+media-v4l2-compat-ioctl32.c-fix-the-indentation.patch
+media-v4l2-compat-ioctl32.c-move-helper-functions-to-__get-put_v4l2_format32.patch
+media-v4l2-compat-ioctl32.c-avoid-sizeof-type.patch
+media-v4l2-compat-ioctl32.c-copy-m.userptr-in-put_v4l2_plane32.patch
+media-v4l2-compat-ioctl32.c-fix-ctrl_is_pointer.patch
+media-v4l2-compat-ioctl32.c-make-ctrl_is_pointer-work-for-subdevs.patch
+media-v4l2-compat-ioctl32-copy-v4l2_window-global_alpha.patch
+media-v4l2-compat-ioctl32.c-copy-clip-list-in-put_v4l2_window32.patch
+media-v4l2-compat-ioctl32.c-drop-pr_info-for-unknown-buffer-type.patch
+media-v4l2-compat-ioctl32.c-don-t-copy-back-the-result-for-certain-errors.patch
+media-v4l2-compat-ioctl32.c-refactor-compat-ioctl32-logic.patch
+crypto-caam-fix-endless-loop-when-deco-acquire-fails.patch
+arm-kvm-fix-smccc-handling-of-unimplemented-smc-hvc-calls.patch
+kvm-nvmx-fix-races-when-sending-nested-pi-while-dest-enters-leaves-l2.patch
+watchdog-imx2_wdt-restore-previous-timeout-after-suspend-resume.patch
+media-ts2020-avoid-integer-overflows-on-32-bit-machines.patch
+media-cxusb-dib0700-ignore-xc2028_i2c_flush.patch
+kernel-async.c-revert-async-simplify-lowest_in_progress.patch
+hid-quirks-fix-keyboard-touchpad-on-toshiba-click-mini-not-working.patch
+bluetooth-btsdio-do-not-bind-to-non-removable-bcm43341.patch
+revert-bluetooth-btusb-fix-qca-rome-suspend-resume.patch
+bluetooth-btusb-restore-qca-rome-suspend-resume-fix-with-a-rewritten-version.patch
+signal-openrisc-fix-do_unaligned_access-to-send-the-proper-signal.patch
+signal-sh-ensure-si_signo-is-initialized-in-do_divide_error.patch
+alpha-fix-crash-if-pthread_create-races-with-signal-delivery.patch
+alpha-fix-reboot-on-avanti-platform.patch
+xtensa-fix-futex_atomic_cmpxchg_inatomic.patch
+edac-octeon-fix-an-uninitialized-variable-warning.patch
+pktcdvd-fix-pkt_setup_dev-error-path.patch
+blk-mq-quiesce-queue-before-freeing-queue.patch
--- /dev/null
+From 500d58300571b6602341b041f97c082a461ef994 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 1 Aug 2017 04:16:47 -0500
+Subject: signal/openrisc: Fix do_unaligned_access to send the proper signal
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 500d58300571b6602341b041f97c082a461ef994 upstream.
+
+While reviewing the signal sending on openrisc the do_unaligned_access
+function stood out because it is obviously wrong. A comment about an
+si_code set above when actually si_code is never set. Leading to a
+random si_code being sent to userspace in the event of an unaligned
+access.
+
+Looking further SIGBUS BUS_ADRALN is the proper pair of signal and
+si_code to send for an unaligned access. That is what other
+architectures do and what is required by posix.
+
+Given that do_unaligned_access is broken in a way that no one can be
+relying on it on openrisc fix the code to just do the right thing.
+
+Fixes: 769a8a96229e ("OpenRISC: Traps")
+Cc: Jonas Bonn <jonas@southpole.se>
+Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+Cc: Stafford Horne <shorne@gmail.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: openrisc@lists.librecores.org
+Acked-by: Stafford Horne <shorne@gmail.com>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/openrisc/kernel/traps.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/openrisc/kernel/traps.c
++++ b/arch/openrisc/kernel/traps.c
+@@ -302,12 +302,12 @@ asmlinkage void do_unaligned_access(stru
+ siginfo_t info;
+
+ if (user_mode(regs)) {
+- /* Send a SIGSEGV */
+- info.si_signo = SIGSEGV;
++ /* Send a SIGBUS */
++ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+- /* info.si_code has been set above */
+- info.si_addr = (void *)address;
+- force_sig_info(SIGSEGV, &info, current);
++ info.si_code = BUS_ADRALN;
++ info.si_addr = (void __user *)address;
++ force_sig_info(SIGBUS, &info, current);
+ } else {
+ printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
+ show_registers(regs);
--- /dev/null
+From 0e88bb002a9b2ee8cc3cc9478ce2dc126f849696 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Mon, 24 Jul 2017 17:30:30 -0500
+Subject: signal/sh: Ensure si_signo is initialized in do_divide_error
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 0e88bb002a9b2ee8cc3cc9478ce2dc126f849696 upstream.
+
+Set si_signo.
+
+Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
+Cc: Rich Felker <dalias@libc.org>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: linux-sh@vger.kernel.org
+Fixes: 0983b31849bb ("sh: Wire up division and address error exceptions on SH-2A.")
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/sh/kernel/traps_32.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/sh/kernel/traps_32.c
++++ b/arch/sh/kernel/traps_32.c
+@@ -607,7 +607,8 @@ asmlinkage void do_divide_error(unsigned
+ break;
+ }
+
+- force_sig_info(SIGFPE, &info, current);
++ info.si_signo = SIGFPE;
++ force_sig_info(info.si_signo, &info, current);
+ }
+ #endif
+
--- /dev/null
+From foo@baz Thu Feb 15 08:44:17 CET 2018
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 14 Feb 2018 12:52:28 +0100
+Subject: vb2: V4L2_BUF_FLAG_DONE is set after DQBUF
+To: stable@vger.kernel.org
+Cc: linux-media@vger.kernel.org, Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>, Hans Verkuil <hans.verkuil@cisco.com>, Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Message-ID: <20180214115240.27650-3-hverkuil@xs4all.nl>
+
+From: Ricardo Ribalda <ricardo.ribalda@gmail.com>
+
+commit 3171cc2b4eb9831ab4df1d80d0410a945b8bc84e upstream.
+
+According to the doc, V4L2_BUF_FLAG_DONE is cleared after DQBUF:
+
+V4L2_BUF_FLAG_DONE 0x00000004 ... After calling the VIDIOC_QBUF or
+VIDIOC_DQBUF it is always cleared ...
+
+Unfortunately, it seems that videobuf2 keeps it set after DQBUF. This
+can be tested with vivid and dev_debug:
+
+[257604.338082] video1: VIDIOC_DQBUF: 71:33:25.00260479 index=3,
+type=vid-cap, flags=0x00002004, field=none, sequence=163,
+memory=userptr, bytesused=460800, offset/userptr=0x344b000,
+length=460800
+
+This patch forces FLAG_DONE to 0 after calling DQBUF.
+
+Reported-by: Dimitrios Katsaros <patcherwork@gmail.com>
+Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/videobuf2-v4l2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
++++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
+@@ -593,6 +593,12 @@ static int vb2_internal_dqbuf(struct vb2
+ b->flags & V4L2_BUF_FLAG_LAST)
+ q->last_buffer_dequeued = true;
+
++ /*
++ * After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
++ * cleared.
++ */
++ b->flags &= ~V4L2_BUF_FLAG_DONE;
++
+ return ret;
+ }
+
--- /dev/null
+From 0be267255cef64e1c58475baa7b25568355a3816 Mon Sep 17 00:00:00 2001
+From: Martin Kaiser <martin@kaiser.cx>
+Date: Mon, 1 Jan 2018 18:26:47 +0100
+Subject: watchdog: imx2_wdt: restore previous timeout after suspend+resume
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+commit 0be267255cef64e1c58475baa7b25568355a3816 upstream.
+
+When the watchdog device is suspended, its timeout is set to the maximum
+value. During resume, the previously set timeout should be restored.
+This does not work at the moment.
+
+The suspend function calls
+
+imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
+
+and resume reverts this by calling
+
+imx2_wdt_set_timeout(wdog, wdog->timeout);
+
+However, imx2_wdt_set_timeout() updates wdog->timeout. Therefore,
+wdog->timeout is set to IMX2_WDT_MAX_TIME when we enter the resume
+function.
+
+Fix this by adding a new function __imx2_wdt_set_timeout() which
+only updates the hardware settings. imx2_wdt_set_timeout() now calls
+__imx2_wdt_set_timeout() and then saves the new timeout to
+wdog->timeout.
+
+During suspend, we call __imx2_wdt_set_timeout() directly so that
+wdog->timeout won't be updated and we can restore the previous value
+during resume. This approach makes wdog->timeout different from the
+actual setting in the hardware which is usually not a good thing.
+However, the two differ only while we're suspended and no kernel code is
+running, so it should be ok in this case.
+
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/watchdog/imx2_wdt.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+--- a/drivers/watchdog/imx2_wdt.c
++++ b/drivers/watchdog/imx2_wdt.c
+@@ -161,15 +161,21 @@ static void imx2_wdt_timer_ping(unsigned
+ mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2);
+ }
+
+-static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
+- unsigned int new_timeout)
++static void __imx2_wdt_set_timeout(struct watchdog_device *wdog,
++ unsigned int new_timeout)
+ {
+ struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
+
+- wdog->timeout = new_timeout;
+-
+ regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
+ WDOG_SEC_TO_COUNT(new_timeout));
++}
++
++static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
++ unsigned int new_timeout)
++{
++ __imx2_wdt_set_timeout(wdog, new_timeout);
++
++ wdog->timeout = new_timeout;
+ return 0;
+ }
+
+@@ -353,7 +359,11 @@ static int imx2_wdt_suspend(struct devic
+
+ /* The watchdog IP block is running */
+ if (imx2_wdt_is_running(wdev)) {
+- imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
++ /*
++ * Don't update wdog->timeout, we'll restore the current value
++ * during resume.
++ */
++ __imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
+ imx2_wdt_ping(wdog);
+
+ /* The watchdog is not active */
--- /dev/null
+From ca47480921587ae30417dd234a9f79af188e3666 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Fri, 5 Jan 2018 14:27:58 -0800
+Subject: xtensa: fix futex_atomic_cmpxchg_inatomic
+
+From: Max Filippov <jcmvbkbc@gmail.com>
+
+commit ca47480921587ae30417dd234a9f79af188e3666 upstream.
+
+Return 0 if the operation was successful, not the userspace memory
+value. Check that userspace value equals passed oldval, not itself.
+Don't update *uval if the value wasn't read from userspace memory.
+
+This fixes process hang due to infinite loop in futex_lock_pi.
+It also fixes a bunch of glibc tests nptl/tst-mutexpi*.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/xtensa/include/asm/futex.h | 23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+--- a/arch/xtensa/include/asm/futex.h
++++ b/arch/xtensa/include/asm/futex.h
+@@ -109,7 +109,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
+ u32 oldval, u32 newval)
+ {
+ int ret = 0;
+- u32 prev;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+@@ -120,26 +119,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
+
+ __asm__ __volatile__ (
+ " # futex_atomic_cmpxchg_inatomic\n"
+- "1: l32i %1, %3, 0\n"
+- " mov %0, %5\n"
+- " wsr %1, scompare1\n"
+- "2: s32c1i %0, %3, 0\n"
+- "3:\n"
++ " wsr %5, scompare1\n"
++ "1: s32c1i %1, %4, 0\n"
++ " s32i %1, %6, 0\n"
++ "2:\n"
+ " .section .fixup,\"ax\"\n"
+ " .align 4\n"
+- "4: .long 3b\n"
+- "5: l32r %1, 4b\n"
+- " movi %0, %6\n"
++ "3: .long 2b\n"
++ "4: l32r %1, 3b\n"
++ " movi %0, %7\n"
+ " jx %1\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+- " .long 1b,5b,2b,5b\n"
++ " .long 1b,4b\n"
+ " .previous\n"
+- : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+- : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT)
++ : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval)
++ : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT)
+ : "memory");
+
+- *uval = prev;
+ return ret;
+ }
+