summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2020-04-21 23:20:17 +0100
committerBen Hutchings <ben@decadent.org.uk>2020-04-21 23:29:34 +0100
commitc53be8ef0c3d3bcf3c92c0e932eb0a7332b07b99 (patch)
treec161ca27351ad368a60193f69b9862189accf053
parent11f7beeb240e9e4e55251d06c11c22730729000c (diff)
downloadlinux-stable-queue-c53be8ef0c3d3bcf3c92c0e932eb0a7332b07b99.tar.gz
Add various security fixes
-rw-r--r--queue-3.16/blktrace-fix-dereference-after-null-check.patch61
-rw-r--r--queue-3.16/blktrace-protect-q-blk_trace-with-rcu.patch390
-rw-r--r--queue-3.16/blktrace-re-write-setting-q-blk_trace.patch82
-rw-r--r--queue-3.16/floppy-check-fdc-index-for-errors-before-assigning-it.patch61
-rw-r--r--queue-3.16/input-add-safety-guards-to-input_set_keycode.patch65
-rw-r--r--queue-3.16/kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch30
-rw-r--r--queue-3.16/media-ov519-add-missing-endpoint-sanity-checks.patch50
-rw-r--r--queue-3.16/media-stv06xx-add-missing-descriptor-sanity-checks.patch88
-rw-r--r--queue-3.16/media-xirlink_cit-add-missing-descriptor-sanity-checks.patch77
-rw-r--r--queue-3.16/mm-mempolicy-require-at-least-one-nodeid-for-mpol_preferred.patch52
-rw-r--r--queue-3.16/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6_dst_lookup.patch67
-rw-r--r--queue-3.16/series19
-rw-r--r--queue-3.16/staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch69
-rw-r--r--queue-3.16/tty-vt-fix-task_running-diagnostic-warning-from-paste_selection.patch70
-rw-r--r--queue-3.16/vgacon-fix-a-uaf-in-vgacon_invert_region.patch125
-rw-r--r--queue-3.16/vhost-check-docket-sk_family-instead-of-call-getname.patch54
-rw-r--r--queue-3.16/vt-selection-close-sel_buffer-race.patch152
-rw-r--r--queue-3.16/vt-selection-handle-pending-signals-in-paste_selection.patch59
-rw-r--r--queue-3.16/vt-selection-push-console-lock-down.patch63
-rw-r--r--queue-3.16/vt-selection-push-sel_lock-up.patch141
20 files changed, 1775 insertions, 0 deletions
diff --git a/queue-3.16/blktrace-fix-dereference-after-null-check.patch b/queue-3.16/blktrace-fix-dereference-after-null-check.patch
new file mode 100644
index 00000000..f415e20a
--- /dev/null
+++ b/queue-3.16/blktrace-fix-dereference-after-null-check.patch
@@ -0,0 +1,61 @@
+From: Cengiz Can <cengiz@kernel.wtf>
+Date: Wed, 4 Mar 2020 13:58:19 +0300
+Subject: blktrace: fix dereference after null check
+
+commit 153031a301bb07194e9c37466cfce8eacb977621 upstream.
+
+There was a recent change in blktrace.c that added a RCU protection to
+`q->blk_trace` in order to fix a use-after-free issue during access.
+
+However the change missed an edge case that can lead to dereferencing of
+`bt` pointer even when it's NULL:
+
+Coverity static analyzer marked this as a FORWARD_NULL issue with CID
+1460458.
+
+```
+/kernel/trace/blktrace.c: 1904 in sysfs_blk_trace_attr_store()
+1898 ret = 0;
+1899 if (bt == NULL)
+1900 ret = blk_trace_setup_queue(q, bdev);
+1901
+1902 if (ret == 0) {
+1903 if (attr == &dev_attr_act_mask)
+>>> CID 1460458: Null pointer dereferences (FORWARD_NULL)
+>>> Dereferencing null pointer "bt".
+1904 bt->act_mask = value;
+1905 else if (attr == &dev_attr_pid)
+1906 bt->pid = value;
+1907 else if (attr == &dev_attr_start_lba)
+1908 bt->start_lba = value;
+1909 else if (attr == &dev_attr_end_lba)
+```
+
+Added a reassignment with RCU annotation to fix the issue.
+
+Fixes: c780e86dd48 ("blktrace: Protect q->blk_trace with RCU")
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Reviewed-by: Bob Liu <bob.liu@oracle.com>
+Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Cengiz Can <cengiz@kernel.wtf>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/trace/blktrace.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/blktrace.c
++++ b/kernel/trace/blktrace.c
+@@ -1834,8 +1834,11 @@ static ssize_t sysfs_blk_trace_attr_stor
+ }
+
+ ret = 0;
+- if (bt == NULL)
++ if (bt == NULL) {
+ ret = blk_trace_setup_queue(q, bdev);
++ bt = rcu_dereference_protected(q->blk_trace,
++ lockdep_is_held(&q->blk_trace_mutex));
++ }
+
+ if (ret == 0) {
+ if (attr == &dev_attr_act_mask)
diff --git a/queue-3.16/blktrace-protect-q-blk_trace-with-rcu.patch b/queue-3.16/blktrace-protect-q-blk_trace-with-rcu.patch
new file mode 100644
index 00000000..0ee6009c
--- /dev/null
+++ b/queue-3.16/blktrace-protect-q-blk_trace-with-rcu.patch
@@ -0,0 +1,390 @@
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 6 Feb 2020 15:28:12 +0100
+Subject: blktrace: Protect q->blk_trace with RCU
+
+commit c780e86dd48ef6467a1146cf7d0fe1e05a635039 upstream.
+
+KASAN is reporting that __blk_add_trace() has a use-after-free issue
+when accessing q->blk_trace. Indeed the switching of block tracing (and
+thus eventual freeing of q->blk_trace) is completely unsynchronized with
+the currently running tracing and thus it can happen that the blk_trace
+structure is being freed just while __blk_add_trace() works on it.
+Protect accesses to q->blk_trace by RCU during tracing and make sure we
+wait for the end of RCU grace period when shutting down tracing. Luckily
+that is rare enough event that we can afford that. Note that postponing
+the freeing of blk_trace to an RCU callback should better be avoided as
+it could have unexpected user visible side-effects as debugfs files
+would be still existing for a short while block tracing has been shut
+down.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=205711
+Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Tested-by: Ming Lei <ming.lei@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reported-by: Tristan Madani <tristmd@gmail.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+[bwh: Backported to 3.16:
+ - Drop changes in blk_trace_note_message_enabled(), blk_trace_bio_get_cgid()
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -447,7 +447,7 @@ struct request_queue {
+ unsigned int sg_reserved_size;
+ int node;
+ #ifdef CONFIG_BLK_DEV_IO_TRACE
+- struct blk_trace *blk_trace;
++ struct blk_trace __rcu *blk_trace;
+ struct mutex blk_trace_mutex;
+ #endif
+ /*
+--- a/include/linux/blktrace_api.h
++++ b/include/linux/blktrace_api.h
+@@ -51,9 +51,13 @@ void __trace_note_message(struct blk_tra
+ **/
+ #define blk_add_trace_msg(q, fmt, ...) \
+ do { \
+- struct blk_trace *bt = (q)->blk_trace; \
++ struct blk_trace *bt; \
++ \
++ rcu_read_lock(); \
++ bt = rcu_dereference((q)->blk_trace); \
+ if (unlikely(bt)) \
+ __trace_note_message(bt, fmt, ##__VA_ARGS__); \
++ rcu_read_unlock(); \
+ } while (0)
+ #define BLK_TN_MAX_MSG 128
+
+--- a/kernel/trace/blktrace.c
++++ b/kernel/trace/blktrace.c
+@@ -302,6 +302,7 @@ static void blk_trace_free(struct blk_tr
+
+ static void blk_trace_cleanup(struct blk_trace *bt)
+ {
++ synchronize_rcu();
+ blk_trace_free(bt);
+ if (atomic_dec_and_test(&blk_probes_ref))
+ blk_unregister_tracepoints();
+@@ -616,8 +617,10 @@ static int compat_blk_trace_setup(struct
+ static int __blk_trace_startstop(struct request_queue *q, int start)
+ {
+ int ret;
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ bt = rcu_dereference_protected(q->blk_trace,
++ lockdep_is_held(&q->blk_trace_mutex));
+ if (bt == NULL)
+ return -EINVAL;
+
+@@ -726,8 +729,8 @@ int blk_trace_ioctl(struct block_device
+ void blk_trace_shutdown(struct request_queue *q)
+ {
+ mutex_lock(&q->blk_trace_mutex);
+-
+- if (q->blk_trace) {
++ if (rcu_dereference_protected(q->blk_trace,
++ lockdep_is_held(&q->blk_trace_mutex))) {
+ __blk_trace_startstop(q, 0);
+ __blk_trace_remove(q);
+ }
+@@ -753,10 +756,14 @@ void blk_trace_shutdown(struct request_q
+ static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
+ unsigned int nr_bytes, u32 what)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
+- if (likely(!bt))
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
++ if (likely(!bt)) {
++ rcu_read_unlock();
+ return;
++ }
+
+ if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
+ what |= BLK_TC_ACT(BLK_TC_PC);
+@@ -767,6 +774,7 @@ static void blk_add_trace_rq(struct requ
+ __blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
+ rq->cmd_flags, what, rq->errors, 0, NULL);
+ }
++ rcu_read_unlock();
+ }
+
+ static void blk_add_trace_rq_abort(void *ignore,
+@@ -816,16 +824,21 @@ static void blk_add_trace_rq_complete(vo
+ static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
+ u32 what, int error)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
+- if (likely(!bt))
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
++ if (likely(!bt)) {
++ rcu_read_unlock();
+ return;
++ }
+
+ if (!error && !bio_flagged(bio, BIO_UPTODATE))
+ error = EIO;
+
+ __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
+ bio->bi_rw, what, error, 0, NULL);
++ rcu_read_unlock();
+ }
+
+ static void blk_add_trace_bio_bounce(void *ignore,
+@@ -870,10 +883,13 @@ static void blk_add_trace_getrq(void *ig
+ if (bio)
+ blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
+ else {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
+ if (bt)
+ __blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL);
++ rcu_read_unlock();
+ }
+ }
+
+@@ -885,27 +901,35 @@ static void blk_add_trace_sleeprq(void *
+ if (bio)
+ blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
+ else {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
+ if (bt)
+ __blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
+ 0, 0, NULL);
++ rcu_read_unlock();
+ }
+ }
+
+ static void blk_add_trace_plug(void *ignore, struct request_queue *q)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
+ if (bt)
+ __blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
++ rcu_read_unlock();
+ }
+
+ static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
+ unsigned int depth, bool explicit)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
+ if (bt) {
+ __be64 rpdu = cpu_to_be64(depth);
+ u32 what;
+@@ -917,14 +941,17 @@ static void blk_add_trace_unplug(void *i
+
+ __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
+ }
++ rcu_read_unlock();
+ }
+
+ static void blk_add_trace_split(void *ignore,
+ struct request_queue *q, struct bio *bio,
+ unsigned int pdu)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
+ if (bt) {
+ __be64 rpdu = cpu_to_be64(pdu);
+
+@@ -933,6 +960,7 @@ static void blk_add_trace_split(void *ig
+ !bio_flagged(bio, BIO_UPTODATE),
+ sizeof(rpdu), &rpdu);
+ }
++ rcu_read_unlock();
+ }
+
+ /**
+@@ -952,11 +980,15 @@ static void blk_add_trace_bio_remap(void
+ struct request_queue *q, struct bio *bio,
+ dev_t dev, sector_t from)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+ struct blk_io_trace_remap r;
+
+- if (likely(!bt))
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
++ if (likely(!bt)) {
++ rcu_read_unlock();
+ return;
++ }
+
+ r.device_from = cpu_to_be32(dev);
+ r.device_to = cpu_to_be32(bio->bi_bdev->bd_dev);
+@@ -965,6 +997,7 @@ static void blk_add_trace_bio_remap(void
+ __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
+ bio->bi_rw, BLK_TA_REMAP,
+ !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
++ rcu_read_unlock();
+ }
+
+ /**
+@@ -985,11 +1018,15 @@ static void blk_add_trace_rq_remap(void
+ struct request *rq, dev_t dev,
+ sector_t from)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+ struct blk_io_trace_remap r;
+
+- if (likely(!bt))
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
++ if (likely(!bt)) {
++ rcu_read_unlock();
+ return;
++ }
+
+ r.device_from = cpu_to_be32(dev);
+ r.device_to = cpu_to_be32(disk_devt(rq->rq_disk));
+@@ -998,6 +1035,7 @@ static void blk_add_trace_rq_remap(void
+ __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
+ rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors,
+ sizeof(r), &r);
++ rcu_read_unlock();
+ }
+
+ /**
+@@ -1015,10 +1053,14 @@ void blk_add_driver_data(struct request_
+ struct request *rq,
+ void *data, size_t len)
+ {
+- struct blk_trace *bt = q->blk_trace;
++ struct blk_trace *bt;
+
+- if (likely(!bt))
++ rcu_read_lock();
++ bt = rcu_dereference(q->blk_trace);
++ if (likely(!bt)) {
++ rcu_read_unlock();
+ return;
++ }
+
+ if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
+ __blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
+@@ -1026,6 +1068,7 @@ void blk_add_driver_data(struct request_
+ else
+ __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
+ BLK_TA_DRV_DATA, rq->errors, len, data);
++ rcu_read_unlock();
+ }
+ EXPORT_SYMBOL_GPL(blk_add_driver_data);
+
+@@ -1537,6 +1580,7 @@ static int blk_trace_remove_queue(struct
+ spin_lock_irq(&running_trace_lock);
+ list_del(&bt->running_list);
+ spin_unlock_irq(&running_trace_lock);
++ synchronize_rcu();
+ blk_trace_free(bt);
+ return 0;
+ }
+@@ -1698,6 +1742,7 @@ static ssize_t sysfs_blk_trace_attr_show
+ struct hd_struct *p = dev_to_part(dev);
+ struct request_queue *q;
+ struct block_device *bdev;
++ struct blk_trace *bt;
+ ssize_t ret = -ENXIO;
+
+ bdev = bdget(part_devt(p));
+@@ -1710,21 +1755,23 @@ static ssize_t sysfs_blk_trace_attr_show
+
+ mutex_lock(&q->blk_trace_mutex);
+
++ bt = rcu_dereference_protected(q->blk_trace,
++ lockdep_is_held(&q->blk_trace_mutex));
+ if (attr == &dev_attr_enable) {
+- ret = sprintf(buf, "%u\n", !!q->blk_trace);
++ ret = sprintf(buf, "%u\n", !!bt);
+ goto out_unlock_bdev;
+ }
+
+- if (q->blk_trace == NULL)
++ if (bt == NULL)
+ ret = sprintf(buf, "disabled\n");
+ else if (attr == &dev_attr_act_mask)
+- ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
++ ret = blk_trace_mask2str(buf, bt->act_mask);
+ else if (attr == &dev_attr_pid)
+- ret = sprintf(buf, "%u\n", q->blk_trace->pid);
++ ret = sprintf(buf, "%u\n", bt->pid);
+ else if (attr == &dev_attr_start_lba)
+- ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
++ ret = sprintf(buf, "%llu\n", bt->start_lba);
+ else if (attr == &dev_attr_end_lba)
+- ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
++ ret = sprintf(buf, "%llu\n", bt->end_lba);
+
+ out_unlock_bdev:
+ mutex_unlock(&q->blk_trace_mutex);
+@@ -1741,6 +1788,7 @@ static ssize_t sysfs_blk_trace_attr_stor
+ struct block_device *bdev;
+ struct request_queue *q;
+ struct hd_struct *p;
++ struct blk_trace *bt;
+ u64 value;
+ ssize_t ret = -EINVAL;
+
+@@ -1771,8 +1819,10 @@ static ssize_t sysfs_blk_trace_attr_stor
+
+ mutex_lock(&q->blk_trace_mutex);
+
++ bt = rcu_dereference_protected(q->blk_trace,
++ lockdep_is_held(&q->blk_trace_mutex));
+ if (attr == &dev_attr_enable) {
+- if (!!value == !!q->blk_trace) {
++ if (!!value == !!bt) {
+ ret = 0;
+ goto out_unlock_bdev;
+ }
+@@ -1784,18 +1834,18 @@ static ssize_t sysfs_blk_trace_attr_stor
+ }
+
+ ret = 0;
+- if (q->blk_trace == NULL)
++ if (bt == NULL)
+ ret = blk_trace_setup_queue(q, bdev);
+
+ if (ret == 0) {
+ if (attr == &dev_attr_act_mask)
+- q->blk_trace->act_mask = value;
++ bt->act_mask = value;
+ else if (attr == &dev_attr_pid)
+- q->blk_trace->pid = value;
++ bt->pid = value;
+ else if (attr == &dev_attr_start_lba)
+- q->blk_trace->start_lba = value;
++ bt->start_lba = value;
+ else if (attr == &dev_attr_end_lba)
+- q->blk_trace->end_lba = value;
++ bt->end_lba = value;
+ }
+
+ out_unlock_bdev:
diff --git a/queue-3.16/blktrace-re-write-setting-q-blk_trace.patch b/queue-3.16/blktrace-re-write-setting-q-blk_trace.patch
new file mode 100644
index 00000000..dd28d9e5
--- /dev/null
+++ b/queue-3.16/blktrace-re-write-setting-q-blk_trace.patch
@@ -0,0 +1,82 @@
+From: Davidlohr Bueso <dave@stgolabs.ne>
+Date: Fri, 30 Oct 2015 05:25:59 +0900
+Subject: blktrace: re-write setting q->blk_trace
+
+commit cdea01b2bf98affb7e9c44530108a4a28535eee8 upstream.
+
+This is really about simplifying the double xchg patterns into
+a single cmpxchg, with the same logic. Other than the immediate
+cleanup, there are some subtleties this change deals with:
+
+(i) While the load of the old bt is fully ordered wrt everything,
+ie:
+
+ old_bt = xchg(&q->blk_trace, bt); [barrier]
+ if (old_bt)
+ (void) xchg(&q->blk_trace, old_bt); [barrier]
+
+blk_trace could still be changed between the xchg and the old_bt
+load. Note that this description is merely theoretical and afaict
+very small, but doing everything in a single context with cmpxchg
+closes this potential race.
+
+(ii) Ordering guarantees are obviously kept with cmpxchg.
+
+(iii) Gets rid of the hacky-by-nature (void)xchg pattern.
+
+Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
+eviewed-by: Jeff Moyer <jmoyer@redhat.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/trace/blktrace.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+--- a/kernel/trace/blktrace.c
++++ b/kernel/trace/blktrace.c
+@@ -448,7 +448,7 @@ int do_blk_trace_setup(struct request_qu
+ struct block_device *bdev,
+ struct blk_user_trace_setup *buts)
+ {
+- struct blk_trace *old_bt, *bt = NULL;
++ struct blk_trace *bt = NULL;
+ struct dentry *dir = NULL;
+ int ret, i;
+
+@@ -532,11 +532,8 @@ int do_blk_trace_setup(struct request_qu
+ bt->trace_state = Blktrace_setup;
+
+ ret = -EBUSY;
+- old_bt = xchg(&q->blk_trace, bt);
+- if (old_bt) {
+- (void) xchg(&q->blk_trace, old_bt);
++ if (cmpxchg(&q->blk_trace, NULL, bt))
+ goto err;
+- }
+
+ if (atomic_inc_return(&blk_probes_ref) == 1)
+ blk_register_tracepoints();
+@@ -1550,7 +1547,7 @@ static int blk_trace_remove_queue(struct
+ static int blk_trace_setup_queue(struct request_queue *q,
+ struct block_device *bdev)
+ {
+- struct blk_trace *old_bt, *bt = NULL;
++ struct blk_trace *bt = NULL;
+ int ret = -ENOMEM;
+
+ bt = kzalloc(sizeof(*bt), GFP_KERNEL);
+@@ -1566,12 +1563,9 @@ static int blk_trace_setup_queue(struct
+
+ blk_trace_setup_lba(bt, bdev);
+
+- old_bt = xchg(&q->blk_trace, bt);
+- if (old_bt != NULL) {
+- (void)xchg(&q->blk_trace, old_bt);
+- ret = -EBUSY;
++ ret = -EBUSY;
++ if (cmpxchg(&q->blk_trace, NULL, bt))
+ goto free_bt;
+- }
+
+ if (atomic_inc_return(&blk_probes_ref) == 1)
+ blk_register_tracepoints();
diff --git a/queue-3.16/floppy-check-fdc-index-for-errors-before-assigning-it.patch b/queue-3.16/floppy-check-fdc-index-for-errors-before-assigning-it.patch
new file mode 100644
index 00000000..9285c89b
--- /dev/null
+++ b/queue-3.16/floppy-check-fdc-index-for-errors-before-assigning-it.patch
@@ -0,0 +1,61 @@
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 21 Feb 2020 12:43:35 -0800
+Subject: floppy: check FDC index for errors before assigning it
+
+commit 2e90ca68b0d2f5548804f22f0dd61145516171e3 upstream.
+
+Jordy Zomer reported a KASAN out-of-bounds read in the floppy driver in
+wait_til_ready().
+
+Which on the face of it can't happen, since as Willy Tarreau points out,
+the function does no particular memory access. Except through the FDCS
+macro, which just indexes a static allocation through teh current fdc,
+which is always checked against N_FDC.
+
+Except the checking happens after we've already assigned the value.
+
+The floppy driver is a disgrace (a lot of it going back to my original
+horrd "design"), and has no real maintainer. Nobody has the hardware,
+and nobody really cares. But it still gets used in virtual environment
+because it's one of those things that everybody supports.
+
+The whole thing should be re-written, or at least parts of it should be
+seriously cleaned up. The 'current fdc' index, which is used by the
+FDCS macro, and which is often shadowed by a local 'fdc' variable, is a
+prime example of how not to write code.
+
+But because nobody has the hardware or the motivation, let's just fix up
+the immediate problem with a nasty band-aid: test the fdc index before
+actually assigning it to the static 'fdc' variable.
+
+Reported-by: Jordy Zomer <jordy@simplyhacker.com>
+Cc: Willy Tarreau <w@1wt.eu>
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/block/floppy.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -847,14 +847,17 @@ static void reset_fdc_info(int mode)
+ /* selects the fdc and drive, and enables the fdc's input/dma. */
+ static void set_fdc(int drive)
+ {
++ unsigned int new_fdc = fdc;
++
+ if (drive >= 0 && drive < N_DRIVE) {
+- fdc = FDC(drive);
++ new_fdc = FDC(drive);
+ current_drive = drive;
+ }
+- if (fdc != 1 && fdc != 0) {
++ if (new_fdc >= N_FDC) {
+ pr_info("bad fdc value\n");
+ return;
+ }
++ fdc = new_fdc;
+ set_dor(fdc, ~0, 8);
+ #if N_FDC > 1
+ set_dor(1 - fdc, ~8, 0);
diff --git a/queue-3.16/input-add-safety-guards-to-input_set_keycode.patch b/queue-3.16/input-add-safety-guards-to-input_set_keycode.patch
new file mode 100644
index 00000000..2ea0fdae
--- /dev/null
+++ b/queue-3.16/input-add-safety-guards-to-input_set_keycode.patch
@@ -0,0 +1,65 @@
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Fri, 13 Dec 2019 14:56:16 -0800
+Subject: Input: add safety guards to input_set_keycode()
+
+commit cb222aed03d798fc074be55e59d9a112338ee784 upstream.
+
+If we happen to have a garbage in input device's keycode table with values
+too big we'll end up doing clear_bit() with offset way outside of our
+bitmaps, damaging other objects within an input device or even outside of
+it. Let's add sanity checks to the returned old keycodes.
+
+Reported-by: syzbot+c769968809f9359b07aa@syzkaller.appspotmail.com
+Reported-by: syzbot+76f3a30e88d256644c78@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/r/20191207212757.GA245964@dtor-ws
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/input/input.c | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -841,16 +841,18 @@ static int input_default_setkeycode(stru
+ }
+ }
+
+- __clear_bit(*old_keycode, dev->keybit);
+- __set_bit(ke->keycode, dev->keybit);
+-
+- for (i = 0; i < dev->keycodemax; i++) {
+- if (input_fetch_keycode(dev, i) == *old_keycode) {
+- __set_bit(*old_keycode, dev->keybit);
+- break; /* Setting the bit twice is useless, so break */
++ if (*old_keycode <= KEY_MAX) {
++ __clear_bit(*old_keycode, dev->keybit);
++ for (i = 0; i < dev->keycodemax; i++) {
++ if (input_fetch_keycode(dev, i) == *old_keycode) {
++ __set_bit(*old_keycode, dev->keybit);
++ /* Setting the bit twice is useless, so break */
++ break;
++ }
+ }
+ }
+
++ __set_bit(ke->keycode, dev->keybit);
+ return 0;
+ }
+
+@@ -906,9 +908,13 @@ int input_set_keycode(struct input_dev *
+ * Simulate keyup event if keycode is not present
+ * in the keymap anymore
+ */
+- if (test_bit(EV_KEY, dev->evbit) &&
+- !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+- __test_and_clear_bit(old_keycode, dev->key)) {
++ if (old_keycode > KEY_MAX) {
++ dev_warn(dev->dev.parent ?: &dev->dev,
++ "%s: got too big old keycode %#x\n",
++ __func__, old_keycode);
++ } else if (test_bit(EV_KEY, dev->evbit) &&
++ !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
++ __test_and_clear_bit(old_keycode, dev->key)) {
+ struct input_value vals[] = {
+ { EV_KEY, old_keycode, 0 },
+ input_value_sync
diff --git a/queue-3.16/kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch b/queue-3.16/kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch
new file mode 100644
index 00000000..98d774bc
--- /dev/null
+++ b/queue-3.16/kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch
@@ -0,0 +1,30 @@
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 4 Feb 2020 15:26:29 -0800
+Subject: KVM: nVMX: Don't emulate instructions in guest mode
+
+commit 07721feee46b4b248402133228235318199b05ec upstream.
+
+vmx_check_intercept is not yet fully implemented. To avoid emulating
+instructions disallowed by the L1 hypervisor, refuse to emulate
+instructions by default.
+
+[Made commit, added commit msg - Oliver]
+Signed-off-by: Oliver Upton <oupton@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[bwh: Backported to 3.16: adjust filename, context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/x86/kvm/vmx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -8938,7 +8938,7 @@ static int vmx_check_intercept(struct kv
+ struct x86_instruction_info *info,
+ enum x86_intercept_stage stage)
+ {
+- return X86EMUL_CONTINUE;
++ return X86EMUL_UNHANDLEABLE;
+ }
+
+ static struct kvm_x86_ops vmx_x86_ops = {
diff --git a/queue-3.16/media-ov519-add-missing-endpoint-sanity-checks.patch b/queue-3.16/media-ov519-add-missing-endpoint-sanity-checks.patch
new file mode 100644
index 00000000..bc90ab42
--- /dev/null
+++ b/queue-3.16/media-ov519-add-missing-endpoint-sanity-checks.patch
@@ -0,0 +1,50 @@
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 3 Jan 2020 17:35:09 +0100
+Subject: media: ov519: add missing endpoint sanity checks
+
+commit 998912346c0da53a6dbb71fab3a138586b596b30 upstream.
+
+Make sure to check that we have at least one endpoint before accessing
+the endpoint array to avoid dereferencing a NULL-pointer on stream
+start.
+
+Note that these sanity checks are not redundant as the driver is mixing
+looking up altsettings by index and by number, which need not coincide.
+
+Fixes: 1876bb923c98 ("V4L/DVB (12079): gspca_ov519: add support for the ov511 bridge")
+Fixes: b282d87332f5 ("V4L/DVB (12080): gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320)")
+Cc: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/media/usb/gspca/ov519.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/media/usb/gspca/ov519.c
++++ b/drivers/media/usb/gspca/ov519.c
+@@ -3497,6 +3497,11 @@ static void ov511_mode_init_regs(struct
+ return;
+ }
+
++ if (alt->desc.bNumEndpoints < 1) {
++ sd->gspca_dev.usb_err = -ENODEV;
++ return;
++ }
++
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
+
+@@ -3622,6 +3627,11 @@ static void ov518_mode_init_regs(struct
+ return;
+ }
+
++ if (alt->desc.bNumEndpoints < 1) {
++ sd->gspca_dev.usb_err = -ENODEV;
++ return;
++ }
++
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
+
diff --git a/queue-3.16/media-stv06xx-add-missing-descriptor-sanity-checks.patch b/queue-3.16/media-stv06xx-add-missing-descriptor-sanity-checks.patch
new file mode 100644
index 00000000..331ad4e2
--- /dev/null
+++ b/queue-3.16/media-stv06xx-add-missing-descriptor-sanity-checks.patch
@@ -0,0 +1,88 @@
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 3 Jan 2020 17:35:10 +0100
+Subject: media: stv06xx: add missing descriptor sanity checks
+
+commit 485b06aadb933190f4bc44e006076bc27a23f205 upstream.
+
+Make sure to check that we have two alternate settings and at least one
+endpoint before accessing the second altsetting structure and
+dereferencing the endpoint arrays.
+
+This specifically avoids dereferencing NULL-pointers or corrupting
+memory when a device does not have the expected descriptors.
+
+Note that the sanity checks in stv06xx_start() and pb0100_start() are
+not redundant as the driver is mixing looking up altsettings by index
+and by number, which may not coincide.
+
+Fixes: 8668d504d72c ("V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor")
+Fixes: c0b33bdc5b8d ("[media] gspca-stv06xx: support bandwidth changing")
+Cc: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 ++++++++++++++++++-
+ .../media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 ++++
+ 2 files changed, 22 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
+@@ -293,6 +293,9 @@ static int stv06xx_start(struct gspca_de
+ return -EIO;
+ }
+
++ if (alt->desc.bNumEndpoints < 1)
++ return -ENODEV;
++
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
+ if (err < 0)
+@@ -317,11 +320,21 @@ out:
+
+ static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
+ {
++ struct usb_interface_cache *intfc;
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
++ intfc = gspca_dev->dev->actconfig->intf_cache[0];
++
++ if (intfc->num_altsetting < 2)
++ return -ENODEV;
++
++ alt = &intfc->altsetting[1];
++
++ if (alt->desc.bNumEndpoints < 1)
++ return -ENODEV;
++
+ /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+ alt->endpoint[0].desc.wMaxPacketSize =
+ cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
+
+@@ -334,6 +347,10 @@ static int stv06xx_isoc_nego(struct gspc
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
++ /*
++ * Existence of altsetting and endpoint was verified in
++ * stv06xx_isoc_init()
++ */
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+@@ -198,6 +198,10 @@ static int pb0100_start(struct sd *sd)
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt)
+ return -ENODEV;
++
++ if (alt->desc.bNumEndpoints < 1)
++ return -ENODEV;
++
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+ /* If we don't have enough bandwidth use a lower framerate */
diff --git a/queue-3.16/media-xirlink_cit-add-missing-descriptor-sanity-checks.patch b/queue-3.16/media-xirlink_cit-add-missing-descriptor-sanity-checks.patch
new file mode 100644
index 00000000..42593a74
--- /dev/null
+++ b/queue-3.16/media-xirlink_cit-add-missing-descriptor-sanity-checks.patch
@@ -0,0 +1,77 @@
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 3 Jan 2020 17:35:11 +0100
+Subject: media: xirlink_cit: add missing descriptor sanity checks
+
+commit a246b4d547708f33ff4d4b9a7a5dbac741dc89d8 upstream.
+
+Make sure to check that we have two alternate settings and at least one
+endpoint before accessing the second altsetting structure and
+dereferencing the endpoint arrays.
+
+This specifically avoids dereferencing NULL-pointers or corrupting
+memory when a device does not have the expected descriptors.
+
+Note that the sanity check in cit_get_packet_size() is not redundant as
+the driver is mixing looking up altsettings by index and by number,
+which may not coincide.
+
+Fixes: 659fefa0eb17 ("V4L/DVB: gspca_xirlink_cit: Add support for camera with a bcd version of 0.01")
+Fixes: 59f8b0bf3c12 ("V4L/DVB: gspca_xirlink_cit: support bandwidth changing for devices with 1 alt setting")
+Cc: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/media/usb/gspca/xirlink_cit.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/usb/gspca/xirlink_cit.c
++++ b/drivers/media/usb/gspca/xirlink_cit.c
+@@ -1455,6 +1455,9 @@ static int cit_get_packet_size(struct gs
+ return -EIO;
+ }
+
++ if (alt->desc.bNumEndpoints < 1)
++ return -ENODEV;
++
+ return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ }
+
+@@ -2632,6 +2635,7 @@ static int sd_start(struct gspca_dev *gs
+
+ static int sd_isoc_init(struct gspca_dev *gspca_dev)
+ {
++ struct usb_interface_cache *intfc;
+ struct usb_host_interface *alt;
+ int max_packet_size;
+
+@@ -2647,8 +2651,17 @@ static int sd_isoc_init(struct gspca_dev
+ break;
+ }
+
++ intfc = gspca_dev->dev->actconfig->intf_cache[0];
++
++ if (intfc->num_altsetting < 2)
++ return -ENODEV;
++
++ alt = &intfc->altsetting[1];
++
++ if (alt->desc.bNumEndpoints < 1)
++ return -ENODEV;
++
+ /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+ alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
+
+ return 0;
+@@ -2671,6 +2684,9 @@ static int sd_isoc_nego(struct gspca_dev
+ break;
+ }
+
++ /*
++ * Existence of altsetting and endpoint was verified in sd_isoc_init()
++ */
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ if (packet_size <= min_packet_size)
diff --git a/queue-3.16/mm-mempolicy-require-at-least-one-nodeid-for-mpol_preferred.patch b/queue-3.16/mm-mempolicy-require-at-least-one-nodeid-for-mpol_preferred.patch
new file mode 100644
index 00000000..121a8f26
--- /dev/null
+++ b/queue-3.16/mm-mempolicy-require-at-least-one-nodeid-for-mpol_preferred.patch
@@ -0,0 +1,52 @@
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Wed, 1 Apr 2020 21:10:58 -0700
+Subject: mm: mempolicy: require at least one nodeid for MPOL_PREFERRED
+
+commit aa9f7d5172fac9bf1f09e678c35e287a40a7b7dd upstream.
+
+Using an empty (malformed) nodelist that is not caught during mount option
+parsing leads to a stack-out-of-bounds access.
+
+The option string that was used was: "mpol=prefer:,". However,
+MPOL_PREFERRED requires a single node number, which is not being provided
+here.
+
+Add a check that 'nodes' is not empty after parsing for MPOL_PREFERRED's
+nodeid.
+
+Fixes: 095f1fc4ebf3 ("mempolicy: rework shmem mpol parsing and display")
+Reported-by: Entropy Moe <3ntr0py1337@gmail.com>
+Reported-by: syzbot+b055b1a6b2b958707a21@syzkaller.appspotmail.com
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Tested-by: syzbot+b055b1a6b2b958707a21@syzkaller.appspotmail.com
+Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
+Link: http://lkml.kernel.org/r/89526377-7eb6-b662-e1d8-4430928abde9@infradead.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ mm/mempolicy.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -2711,7 +2711,9 @@ int mpol_parse_str(char *str, struct mem
+ switch (mode) {
+ case MPOL_PREFERRED:
+ /*
+- * Insist on a nodelist of one node only
++ * Insist on a nodelist of one node only, although later
++ * we use first_node(nodes) to grab a single node, so here
++ * nodelist (or nodes) cannot be empty.
+ */
+ if (nodelist) {
+ char *rest = nodelist;
+@@ -2719,6 +2721,8 @@ int mpol_parse_str(char *str, struct mem
+ rest++;
+ if (*rest)
+ goto out;
++ if (nodes_empty(nodes))
++ goto out;
+ }
+ break;
+ case MPOL_INTERLEAVE:
diff --git a/queue-3.16/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6_dst_lookup.patch b/queue-3.16/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6_dst_lookup.patch
new file mode 100644
index 00000000..00888e58
--- /dev/null
+++ b/queue-3.16/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6_dst_lookup.patch
@@ -0,0 +1,67 @@
+From: Sabrina Dubroca <sd@queasysnail.net>
+Date: Wed, 4 Dec 2019 15:35:53 +0100
+Subject: net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup
+
+commit 6c8991f41546c3c472503dff1ea9daaddf9331c2 upstream.
+
+ipv6_stub uses the ip6_dst_lookup function to allow other modules to
+perform IPv6 lookups. However, this function skips the XFRM layer
+entirely.
+
+All users of ipv6_stub->ip6_dst_lookup use ip_route_output_flow (via the
+ip_route_output_key and ip_route_output helpers) for their IPv4 lookups,
+which calls xfrm_lookup_route(). This patch fixes this inconsistent
+behavior by switching the stub to ip6_dst_lookup_flow, which also calls
+xfrm_lookup_route().
+
+This requires some changes in all the callers, as these two functions
+take different arguments and have different return types.
+
+Fixes: 5f81bd2e5d80 ("ipv6: export a stub for IPv6 symbols used by vxlan")
+Reported-by: Xiumei Mu <xmu@redhat.com>
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.16:
+ - Only vxlan uses this operation
+ - Neither ip6_dst_lookup() nor ip6_dst_lookup_flow() takes a struct net
+ pointer argument here
+ - Adjust filename, context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -1929,7 +1929,8 @@ static void vxlan_xmit_one(struct sk_buf
+ fl6.saddr = vxlan->saddr.sin6.sin6_addr;
+ fl6.flowi6_proto = IPPROTO_UDP;
+
+- if (ipv6_stub->ipv6_dst_lookup(sk, &ndst, &fl6)) {
++ ndst = ipv6_stub->ipv6_dst_lookup_flow(sk, &fl6, NULL);
++ if (unlikely(IS_ERR(ndst))) {
+ netdev_dbg(dev, "no route to %pI6\n",
+ &dst->sin6.sin6_addr);
+ dev->stats.tx_carrier_errors++;
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -156,8 +156,9 @@ struct ipv6_stub {
+ const struct in6_addr *addr);
+ int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
+ const struct in6_addr *addr);
+- int (*ipv6_dst_lookup)(struct sock *sk, struct dst_entry **dst,
+- struct flowi6 *fl6);
++ struct dst_entry *(*ipv6_dst_lookup_flow)(struct sock *sk,
++ struct flowi6 *fl6,
++ const struct in6_addr *final_dst);
+ void (*udpv6_encap_enable)(void);
+ void (*ndisc_send_na)(struct net_device *dev, struct neighbour *neigh,
+ const struct in6_addr *daddr,
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -820,7 +820,7 @@ static struct pernet_operations inet6_ne
+ static const struct ipv6_stub ipv6_stub_impl = {
+ .ipv6_sock_mc_join = ipv6_sock_mc_join,
+ .ipv6_sock_mc_drop = ipv6_sock_mc_drop,
+- .ipv6_dst_lookup = ip6_dst_lookup,
++ .ipv6_dst_lookup_flow = ip6_dst_lookup_flow,
+ .udpv6_encap_enable = udpv6_encap_enable,
+ .ndisc_send_na = ndisc_send_na,
+ .nd_tbl = &nd_tbl,
diff --git a/queue-3.16/series b/queue-3.16/series
index 832f93c0..dab52b70 100644
--- a/queue-3.16/series
+++ b/queue-3.16/series
@@ -208,3 +208,22 @@ net_sched-fix-datalen-for-ematch.patch
namei-allow-restricted-o_creat-of-fifos-and-regular-files.patch
do_last-fetch-directory-i_mode-and-i_uid-before-it-s-too-late.patch
vfs-fix-do_last-regression.patch
+blktrace-re-write-setting-q-blk_trace.patch
+blktrace-protect-q-blk_trace-with-rcu.patch
+blktrace-fix-dereference-after-null-check.patch
+input-add-safety-guards-to-input_set_keycode.patch
+staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch
+net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6_dst_lookup.patch
+kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch
+vgacon-fix-a-uaf-in-vgacon_invert_region.patch
+tty-vt-fix-task_running-diagnostic-warning-from-paste_selection.patch
+vt-selection-handle-pending-signals-in-paste_selection.patch
+vt-selection-close-sel_buffer-race.patch
+vt-selection-push-console-lock-down.patch
+vt-selection-push-sel_lock-up.patch
+floppy-check-fdc-index-for-errors-before-assigning-it.patch
+vhost-check-docket-sk_family-instead-of-call-getname.patch
+mm-mempolicy-require-at-least-one-nodeid-for-mpol_preferred.patch
+media-ov519-add-missing-endpoint-sanity-checks.patch
+media-stv06xx-add-missing-descriptor-sanity-checks.patch
+media-xirlink_cit-add-missing-descriptor-sanity-checks.patch
diff --git a/queue-3.16/staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch b/queue-3.16/staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch
new file mode 100644
index 00000000..99f687eb
--- /dev/null
+++ b/queue-3.16/staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch
@@ -0,0 +1,69 @@
+From: Suren Baghdasaryan <surenb@google.com>
+Date: Mon, 27 Jan 2020 15:56:16 -0800
+Subject: staging: android: ashmem: Disallow ashmem memory from being remapped
+
+commit 6d67b0290b4b84c477e6a2fc6e005e174d3c7786 upstream.
+
+When ashmem file is mmapped, the resulting vma->vm_file points to the
+backing shmem file with the generic fops that do not check ashmem
+permissions like fops of ashmem do. If an mremap is done on the ashmem
+region, then the permission checks will be skipped. Fix that by disallowing
+mapping operation on the backing shmem file.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Suren Baghdasaryan <surenb@google.com>
+Signed-off-by: Todd Kjos <tkjos@google.com>
+Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Link: https://lore.kernel.org/r/20200127235616.48920-1-tkjos@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/staging/android/ashmem.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/drivers/staging/android/ashmem.c
++++ b/drivers/staging/android/ashmem.c
+@@ -351,8 +351,23 @@ static inline vm_flags_t calc_vm_may_fla
+ _calc_vm_trans(prot, PROT_EXEC, VM_MAYEXEC);
+ }
+
++static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ /* do not allow to mmap ashmem backing shmem file directly */
++ return -EPERM;
++}
++
++static unsigned long
++ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
++ unsigned long len, unsigned long pgoff,
++ unsigned long flags)
++{
++ return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
++}
++
+ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
+ {
++ static struct file_operations vmfile_fops;
+ struct ashmem_area *asma = file->private_data;
+ int ret = 0;
+
+@@ -386,6 +401,19 @@ static int ashmem_mmap(struct file *file
+ goto out;
+ }
+ asma->file = vmfile;
++ /*
++ * override mmap operation of the vmfile so that it can't be
++ * remapped which would lead to creation of a new vma with no
++ * asma permission checks. Have to override get_unmapped_area
++ * as well to prevent VM_BUG_ON check for f_ops modification.
++ */
++ if (!vmfile_fops.mmap) {
++ vmfile_fops = *vmfile->f_op;
++ vmfile_fops.mmap = ashmem_vmfile_mmap;
++ vmfile_fops.get_unmapped_area =
++ ashmem_vmfile_get_unmapped_area;
++ }
++ vmfile->f_op = &vmfile_fops;
+ }
+ get_file(asma->file);
+
diff --git a/queue-3.16/tty-vt-fix-task_running-diagnostic-warning-from-paste_selection.patch b/queue-3.16/tty-vt-fix-task_running-diagnostic-warning-from-paste_selection.patch
new file mode 100644
index 00000000..25c0b98e
--- /dev/null
+++ b/queue-3.16/tty-vt-fix-task_running-diagnostic-warning-from-paste_selection.patch
@@ -0,0 +1,70 @@
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Sun, 12 Jul 2015 20:47:35 -0400
+Subject: tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection()
+
+commit 61e86cc90af49cecef9c54ccea1f572fbcb695ac upstream.
+
+Pasting text with gpm on a VC produced warning [1]. Reset task state
+to TASK_RUNNING in the paste_selection() loop, if the loop did not
+sleep.
+
+[1]
+WARNING: CPU: 6 PID: 1960 at /home/peter/src/kernels/mainline/kernel/sched/core.c:7286 __might_sleep+0x7f/0x90()
+do not call blocking ops when !TASK_RUNNING; state=1 set at [<ffffffff8151805e>] paste_selection+0x9e/0x1a0
+Modules linked in: btrfs xor raid6_pq ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs libcrc32c .....
+CPU: 6 PID: 1960 Comm: gpm Not tainted 4.1.0-rc7+tty-xeon+debug #rc7+tty
+Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012
+ ffffffff81c9c0a0 ffff8802b0fd3ac8 ffffffff8185778a 0000000000000001
+ ffff8802b0fd3b18 ffff8802b0fd3b08 ffffffff8108039a ffffffff82ae8510
+ ffffffff81c9ce00 0000000000000015 0000000000000000 0000000000000000
+Call Trace:
+ [<ffffffff8185778a>] dump_stack+0x4f/0x7b
+ [<ffffffff8108039a>] warn_slowpath_common+0x8a/0xc0
+ [<ffffffff81080416>] warn_slowpath_fmt+0x46/0x50
+ [<ffffffff810ddced>] ? __lock_acquire+0xe2d/0x13a0
+ [<ffffffff8151805e>] ? paste_selection+0x9e/0x1a0
+ [<ffffffff8151805e>] ? paste_selection+0x9e/0x1a0
+ [<ffffffff810ad4ff>] __might_sleep+0x7f/0x90
+ [<ffffffff8185f76a>] down_read+0x2a/0xa0
+ [<ffffffff810bb1d8>] ? sched_clock_cpu+0xb8/0xe0
+ [<ffffffff8150d1dc>] n_tty_receive_buf_common+0x4c/0xba0
+ [<ffffffff810dc875>] ? mark_held_locks+0x75/0xa0
+ [<ffffffff81861c95>] ? _raw_spin_unlock_irqrestore+0x65/0x80
+ [<ffffffff810b49a1>] ? get_parent_ip+0x11/0x50
+ [<ffffffff8150dd44>] n_tty_receive_buf2+0x14/0x20
+ [<ffffffff81518117>] paste_selection+0x157/0x1a0
+ [<ffffffff810b77b0>] ? wake_up_state+0x20/0x20
+ [<ffffffff815203f8>] tioclinux+0xb8/0x2c0
+ [<ffffffff81515bfe>] vt_ioctl+0xaee/0x11a0
+ [<ffffffff810baf75>] ? sched_clock_local+0x25/0x90
+ [<ffffffff810bbe11>] ? vtime_account_user+0x91/0xa0
+ [<ffffffff8150810c>] tty_ioctl+0x20c/0xe20
+ [<ffffffff810bbe11>] ? vtime_account_user+0x91/0xa0
+ [<ffffffff810b49a1>] ? get_parent_ip+0x11/0x50
+ [<ffffffff810b4a69>] ? preempt_count_sub+0x49/0x50
+ [<ffffffff811ab71c>] ? context_tracking_exit+0x5c/0x290
+ [<ffffffff811ab71c>] ? context_tracking_exit+0x5c/0x290
+ [<ffffffff81248b98>] do_vfs_ioctl+0x318/0x570
+ [<ffffffff810dca8d>] ? trace_hardirqs_on+0xd/0x10
+ [<ffffffff810dc9b5>] ? trace_hardirqs_on_caller+0x115/0x1e0
+ [<ffffffff81254acc>] ? __fget_light+0x6c/0xa0
+ [<ffffffff81248e71>] SyS_ioctl+0x81/0xa0
+ [<ffffffff81862832>] system_call_fastpath+0x16/0x7a
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/tty/vt/selection.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/tty/vt/selection.c
++++ b/drivers/tty/vt/selection.c
+@@ -356,6 +356,7 @@ int paste_selection(struct tty_struct *t
+ schedule();
+ continue;
+ }
++ __set_current_state(TASK_RUNNING);
+ count = sel_buffer_lth - pasted;
+ count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
+ count);
diff --git a/queue-3.16/vgacon-fix-a-uaf-in-vgacon_invert_region.patch b/queue-3.16/vgacon-fix-a-uaf-in-vgacon_invert_region.patch
new file mode 100644
index 00000000..931b9411
--- /dev/null
+++ b/queue-3.16/vgacon-fix-a-uaf-in-vgacon_invert_region.patch
@@ -0,0 +1,125 @@
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Date: Wed, 4 Mar 2020 10:24:29 +0800
+Subject: vgacon: Fix a UAF in vgacon_invert_region
+
+commit 513dc792d6060d5ef572e43852683097a8420f56 upstream.
+
+When syzkaller tests, there is a UAF:
+ BUG: KASan: use after free in vgacon_invert_region+0x9d/0x110 at addr
+ ffff880000100000
+ Read of size 2 by task syz-executor.1/16489
+ page:ffffea0000004000 count:0 mapcount:-127 mapping: (null)
+ index:0x0
+ page flags: 0xfffff00000000()
+ page dumped because: kasan: bad access detected
+ CPU: 1 PID: 16489 Comm: syz-executor.1 Not tainted
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+ rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
+ Call Trace:
+ [<ffffffffb119f309>] dump_stack+0x1e/0x20
+ [<ffffffffb04af957>] kasan_report+0x577/0x950
+ [<ffffffffb04ae652>] __asan_load2+0x62/0x80
+ [<ffffffffb090f26d>] vgacon_invert_region+0x9d/0x110
+ [<ffffffffb0a39d95>] invert_screen+0xe5/0x470
+ [<ffffffffb0a21dcb>] set_selection+0x44b/0x12f0
+ [<ffffffffb0a3bfae>] tioclinux+0xee/0x490
+ [<ffffffffb0a1d114>] vt_ioctl+0xff4/0x2670
+ [<ffffffffb0a0089a>] tty_ioctl+0x46a/0x1a10
+ [<ffffffffb052db3d>] do_vfs_ioctl+0x5bd/0xc40
+ [<ffffffffb052e2f2>] SyS_ioctl+0x132/0x170
+ [<ffffffffb11c9b1b>] system_call_fastpath+0x22/0x27
+ Memory state around the buggy address:
+ ffff8800000fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00
+ ffff8800000fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00
+ >ffff880000100000: ff ff ff ff ff ff ff ff ff ff ff ff ff
+ ff ff ff
+
+It can be reproduce in the linux mainline by the program:
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/ioctl.h>
+ #include <linux/vt.h>
+
+ struct tiocl_selection {
+ unsigned short xs; /* X start */
+ unsigned short ys; /* Y start */
+ unsigned short xe; /* X end */
+ unsigned short ye; /* Y end */
+ unsigned short sel_mode; /* selection mode */
+ };
+
+ #define TIOCL_SETSEL 2
+ struct tiocl {
+ unsigned char type;
+ unsigned char pad;
+ struct tiocl_selection sel;
+ };
+
+ int main()
+ {
+ int fd = 0;
+ const char *dev = "/dev/char/4:1";
+
+ struct vt_consize v = {0};
+ struct tiocl tioc = {0};
+
+ fd = open(dev, O_RDWR, 0);
+
+ v.v_rows = 3346;
+ ioctl(fd, VT_RESIZEX, &v);
+
+ tioc.type = TIOCL_SETSEL;
+ ioctl(fd, TIOCLINUX, &tioc);
+
+ return 0;
+ }
+
+When resize the screen, update the 'vc->vc_size_row' to the new_row_size,
+but when 'set_origin' in 'vgacon_set_origin', vgacon use 'vga_vram_base'
+for 'vc_origin' and 'vc_visible_origin', not 'vc_screenbuf'. It maybe
+smaller than 'vc_screenbuf'. When TIOCLINUX, use the new_row_size to calc
+the offset, it maybe larger than the vga_vram_size in vgacon driver, then
+bad access.
+Also, if set an larger screenbuf firstly, then set an more larger
+screenbuf, when copy old_origin to new_origin, a bad access may happen.
+
+So, If the screen size larger than vga_vram, resize screen should be
+failed. This alse fix CVE-2020-8649 and CVE-2020-8647.
+
+Linus pointed out that overflow checking seems absent. We're saved by
+the existing bounds checks in vc_do_resize() with rather strict
+limits:
+
+ if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
+ return -EINVAL;
+
+Fixes: 0aec4867dca14 ("[PATCH] SVGATextMode fix")
+Reference: CVE-2020-8647 and CVE-2020-8649
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+[danvet: augment commit message to point out overflow safety]
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20200304022429.37738-1-zhangxiaoxu5@huawei.com
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/video/console/vgacon.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -1312,6 +1312,9 @@ static int vgacon_font_get(struct vc_dat
+ static int vgacon_resize(struct vc_data *c, unsigned int width,
+ unsigned int height, unsigned int user)
+ {
++ if ((width << 1) * height > vga_vram_size)
++ return -EINVAL;
++
+ if (width % 2 || width > screen_info.orig_video_cols ||
+ height > (screen_info.orig_video_lines * vga_default_font_height)/
+ c->vc_font.height)
diff --git a/queue-3.16/vhost-check-docket-sk_family-instead-of-call-getname.patch b/queue-3.16/vhost-check-docket-sk_family-instead-of-call-getname.patch
new file mode 100644
index 00000000..3b21a915
--- /dev/null
+++ b/queue-3.16/vhost-check-docket-sk_family-instead-of-call-getname.patch
@@ -0,0 +1,54 @@
+From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= <eperezma@redhat.com>
+Date: Fri, 21 Feb 2020 12:06:56 +0100
+Subject: vhost: Check docket sk_family instead of call getname
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 42d84c8490f9f0931786f1623191fcab397c3d64 upstream.
+
+Doing so, we save one call to get data we already have in the struct.
+
+Also, since there is no guarantee that getname use sockaddr_ll
+parameter beyond its size, we add a little bit of security here.
+It should do not do beyond MAX_ADDR_LEN, but syzbot found that
+ax25_getname writes more (72 bytes, the size of full_sockaddr_ax25,
+versus 20 + 32 bytes of sockaddr_ll + MAX_ADDR_LEN in syzbot repro).
+
+Fixes: 3a4d5c94e9593 ("vhost_net: a kernel-level virtio server")
+Reported-by: syzbot+f2a62d07a5198c819c7b@syzkaller.appspotmail.com
+Signed-off-by: Eugenio PĂ©rez <eperezma@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.16: Also delete "uaddr_len" variable]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/vhost/net.c
++++ b/drivers/vhost/net.c
+@@ -843,11 +843,7 @@ static int vhost_net_release(struct inod
+
+ static struct socket *get_raw_socket(int fd)
+ {
+- struct {
+- struct sockaddr_ll sa;
+- char buf[MAX_ADDR_LEN];
+- } uaddr;
+- int uaddr_len = sizeof uaddr, r;
++ int r;
+ struct socket *sock = sockfd_lookup(fd, &r);
+
+ if (!sock)
+@@ -859,12 +855,7 @@ static struct socket *get_raw_socket(int
+ goto err;
+ }
+
+- r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
+- &uaddr_len, 0);
+- if (r)
+- goto err;
+-
+- if (uaddr.sa.sll_family != AF_PACKET) {
++ if (sock->sk->sk_family != AF_PACKET) {
+ r = -EPFNOSUPPORT;
+ goto err;
+ }
diff --git a/queue-3.16/vt-selection-close-sel_buffer-race.patch b/queue-3.16/vt-selection-close-sel_buffer-race.patch
new file mode 100644
index 00000000..95c5825c
--- /dev/null
+++ b/queue-3.16/vt-selection-close-sel_buffer-race.patch
@@ -0,0 +1,152 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Mon, 10 Feb 2020 09:11:31 +0100
+Subject: vt: selection, close sel_buffer race
+
+commit 07e6124a1a46b4b5a9b3cacc0c306b50da87abf5 upstream.
+
+syzkaller reported this UAF:
+BUG: KASAN: use-after-free in n_tty_receive_buf_common+0x2481/0x2940 drivers/tty/n_tty.c:1741
+Read of size 1 at addr ffff8880089e40e9 by task syz-executor.1/13184
+
+CPU: 0 PID: 13184 Comm: syz-executor.1 Not tainted 5.4.7 #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
+Call Trace:
+...
+ kasan_report+0xe/0x20 mm/kasan/common.c:634
+ n_tty_receive_buf_common+0x2481/0x2940 drivers/tty/n_tty.c:1741
+ tty_ldisc_receive_buf+0xac/0x190 drivers/tty/tty_buffer.c:461
+ paste_selection+0x297/0x400 drivers/tty/vt/selection.c:372
+ tioclinux+0x20d/0x4e0 drivers/tty/vt/vt.c:3044
+ vt_ioctl+0x1bcf/0x28d0 drivers/tty/vt/vt_ioctl.c:364
+ tty_ioctl+0x525/0x15a0 drivers/tty/tty_io.c:2657
+ vfs_ioctl fs/ioctl.c:47 [inline]
+
+It is due to a race between parallel paste_selection (TIOCL_PASTESEL)
+and set_selection_user (TIOCL_SETSEL) invocations. One uses sel_buffer,
+while the other frees it and reallocates a new one for another
+selection. Add a mutex to close this race.
+
+The mutex takes care properly of sel_buffer and sel_buffer_lth only. The
+other selection global variables (like sel_start, sel_end, and sel_cons)
+are protected only in set_selection_user. The other functions need quite
+some more work to close the races of the variables there. This is going
+to happen later.
+
+This likely fixes (I am unsure as there is no reproducer provided) bug
+206361 too. It was marked as CVE-2020-8648.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Reported-by: syzbot+59997e8d5cbdc486e6f6@syzkaller.appspotmail.com
+References: https://bugzilla.kernel.org/show_bug.cgi?id=206361
+Link: https://lore.kernel.org/r/20200210081131.23572-2-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[bwh: Backported to 3.16: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/tty/vt/selection.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/vt/selection.c
++++ b/drivers/tty/vt/selection.c
+@@ -13,6 +13,7 @@
+ #include <linux/tty.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
++#include <linux/mutex.h>
+ #include <linux/slab.h>
+ #include <linux/types.h>
+
+@@ -40,6 +41,7 @@ static volatile int sel_start = -1; /*
+ static int sel_end;
+ static int sel_buffer_lth;
+ static char *sel_buffer;
++static DEFINE_MUTEX(sel_lock);
+
+ /* clear_selection, highlight and highlight_pointer can be called
+ from interrupt (via scrollback/front) */
+@@ -163,7 +165,7 @@ int set_selection(const struct tiocl_sel
+ char *bp, *obp;
+ int i, ps, pe, multiplier;
+ u16 c;
+- int mode;
++ int mode, ret = 0;
+
+ poke_blanked_console();
+
+@@ -203,6 +205,7 @@ int set_selection(const struct tiocl_sel
+ pe = tmp;
+ }
+
++ mutex_lock(&sel_lock);
+ if (sel_cons != vc_cons[fg_console].d) {
+ clear_selection();
+ sel_cons = vc_cons[fg_console].d;
+@@ -248,9 +251,10 @@ int set_selection(const struct tiocl_sel
+ break;
+ case TIOCL_SELPOINTER:
+ highlight_pointer(pe);
+- return 0;
++ goto unlock;
+ default:
+- return -EINVAL;
++ ret = -EINVAL;
++ goto unlock;
+ }
+
+ /* remove the pointer */
+@@ -272,7 +276,7 @@ int set_selection(const struct tiocl_sel
+ else if (new_sel_start == sel_start)
+ {
+ if (new_sel_end == sel_end) /* no action required */
+- return 0;
++ goto unlock;
+ else if (new_sel_end > sel_end) /* extend to right */
+ highlight(sel_end + 2, new_sel_end);
+ else /* contract from right */
+@@ -299,7 +303,8 @@ int set_selection(const struct tiocl_sel
+ if (!bp) {
+ printk(KERN_WARNING "selection: kmalloc() failed\n");
+ clear_selection();
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto unlock;
+ }
+ kfree(sel_buffer);
+ sel_buffer = bp;
+@@ -324,7 +329,9 @@ int set_selection(const struct tiocl_sel
+ }
+ }
+ sel_buffer_lth = bp - sel_buffer;
+- return 0;
++unlock:
++ mutex_unlock(&sel_lock);
++ return ret;
+ }
+
+ /* Insert the contents of the selection buffer into the
+@@ -351,6 +358,7 @@ int paste_selection(struct tty_struct *t
+ tty_buffer_lock_exclusive(&vc->port);
+
+ add_wait_queue(&vc->paste_wait, &wait);
++ mutex_lock(&sel_lock);
+ while (sel_buffer && sel_buffer_lth > pasted) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current)) {
+@@ -358,7 +366,9 @@ int paste_selection(struct tty_struct *t
+ break;
+ }
+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
++ mutex_unlock(&sel_lock);
+ schedule();
++ mutex_lock(&sel_lock);
+ continue;
+ }
+ __set_current_state(TASK_RUNNING);
+@@ -367,6 +377,7 @@ int paste_selection(struct tty_struct *t
+ count);
+ pasted += count;
+ }
++ mutex_unlock(&sel_lock);
+ remove_wait_queue(&vc->paste_wait, &wait);
+ __set_current_state(TASK_RUNNING);
+
diff --git a/queue-3.16/vt-selection-handle-pending-signals-in-paste_selection.patch b/queue-3.16/vt-selection-handle-pending-signals-in-paste_selection.patch
new file mode 100644
index 00000000..90949cce
--- /dev/null
+++ b/queue-3.16/vt-selection-handle-pending-signals-in-paste_selection.patch
@@ -0,0 +1,59 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Mon, 10 Feb 2020 09:11:30 +0100
+Subject: vt: selection, handle pending signals in paste_selection
+
+commit 687bff0cd08f790d540cfb7b2349f0d876cdddec upstream.
+
+When pasting a selection to a vt, the task is set as INTERRUPTIBLE while
+waiting for a tty to unthrottle. But signals are not handled at all.
+Normally, this is not a problem as tty_ldisc_receive_buf receives all
+the goods and a user has no reason to interrupt the task.
+
+There are two scenarios where this matters:
+1) when the tty is throttled and a signal is sent to the process, it
+ spins on a CPU until the tty is unthrottled. schedule() does not
+ really echedule, but returns immediately, of course.
+2) when the sel_buffer becomes invalid, KASAN prevents any reads from it
+ and the loop simply does not proceed and spins forever (causing the
+ tty to throttle, but the code never sleeps, the same as above). This
+ sometimes happens as there is a race in the sel_buffer handling code.
+
+So add signal handling to this ioctl (TIOCL_PASTESEL) and return -EINTR
+in case a signal is pending.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20200210081131.23572-1-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[bwh: Backported to 3.16:
+ - No need to include <linux/sched/signal.h>
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/tty/vt/selection.c
++++ b/drivers/tty/vt/selection.c
+@@ -341,6 +341,7 @@ int paste_selection(struct tty_struct *t
+ unsigned int count;
+ struct tty_ldisc *ld;
+ DECLARE_WAITQUEUE(wait, current);
++ int ret = 0;
+
+ console_lock();
+ poke_blanked_console();
+@@ -352,6 +353,10 @@ int paste_selection(struct tty_struct *t
+ add_wait_queue(&vc->paste_wait, &wait);
+ while (sel_buffer && sel_buffer_lth > pasted) {
+ set_current_state(TASK_INTERRUPTIBLE);
++ if (signal_pending(current)) {
++ ret = -EINTR;
++ break;
++ }
+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
+ schedule();
+ continue;
+@@ -367,5 +372,5 @@ int paste_selection(struct tty_struct *t
+
+ tty_buffer_unlock_exclusive(&vc->port);
+ tty_ldisc_deref(ld);
+- return 0;
++ return ret;
+ }
diff --git a/queue-3.16/vt-selection-push-console-lock-down.patch b/queue-3.16/vt-selection-push-console-lock-down.patch
new file mode 100644
index 00000000..79eb6551
--- /dev/null
+++ b/queue-3.16/vt-selection-push-console-lock-down.patch
@@ -0,0 +1,63 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Fri, 28 Feb 2020 12:54:05 +0100
+Subject: vt: selection, push console lock down
+
+commit 4b70dd57a15d2f4685ac6e38056bad93e81e982f upstream.
+
+We need to nest the console lock in sel_lock, so we have to push it down
+a bit. Fortunately, the callers of set_selection_* just lock the console
+lock around the function call. So moving it down is easy.
+
+In the next patch, we switch the order.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
+Link: https://lore.kernel.org/r/20200228115406.5735-1-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/tty/vt/selection.c | 13 ++++++++++++-
+ drivers/tty/vt/vt.c | 2 --
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/vt/selection.c
++++ b/drivers/tty/vt/selection.c
+@@ -158,7 +158,7 @@ static int store_utf8(u16 c, char *p)
+ * The entire selection process is managed under the console_lock. It's
+ * a lot under the lock but its hardly a performance path
+ */
+-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
++static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
+ {
+ struct vc_data *vc = vc_cons[fg_console].d;
+ int sel_mode, new_sel_start, new_sel_end, spc;
+@@ -334,6 +334,17 @@ unlock:
+ return ret;
+ }
+
++int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty)
++{
++ int ret;
++
++ console_lock();
++ ret = __set_selection(v, tty);
++ console_unlock();
++
++ return ret;
++}
++
+ /* Insert the contents of the selection buffer into the
+ * queue of the tty associated with the current console.
+ * Invoked by ioctl().
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -2670,9 +2670,7 @@ int tioclinux(struct tty_struct *tty, un
+ switch (type)
+ {
+ case TIOCL_SETSEL:
+- console_lock();
+ ret = set_selection((struct tiocl_selection __user *)(p+1), tty);
+- console_unlock();
+ break;
+ case TIOCL_PASTESEL:
+ ret = paste_selection(tty);
diff --git a/queue-3.16/vt-selection-push-sel_lock-up.patch b/queue-3.16/vt-selection-push-sel_lock-up.patch
new file mode 100644
index 00000000..553b257d
--- /dev/null
+++ b/queue-3.16/vt-selection-push-sel_lock-up.patch
@@ -0,0 +1,141 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Fri, 28 Feb 2020 12:54:06 +0100
+Subject: vt: selection, push sel_lock up
+
+commit e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2 upstream.
+
+sel_lock cannot nest in the console lock. Thanks to syzkaller, the
+kernel states firmly:
+
+> WARNING: possible circular locking dependency detected
+> 5.6.0-rc3-syzkaller #0 Not tainted
+> ------------------------------------------------------
+> syz-executor.4/20336 is trying to acquire lock:
+> ffff8880a2e952a0 (&tty->termios_rwsem){++++}, at: tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
+>
+> but task is already holding lock:
+> ffffffff89462e70 (sel_lock){+.+.}, at: paste_selection+0x118/0x470 drivers/tty/vt/selection.c:374
+>
+> which lock already depends on the new lock.
+>
+> the existing dependency chain (in reverse order) is:
+>
+> -> #2 (sel_lock){+.+.}:
+> mutex_lock_nested+0x1b/0x30 kernel/locking/mutex.c:1118
+> set_selection_kernel+0x3b8/0x18a0 drivers/tty/vt/selection.c:217
+> set_selection_user+0x63/0x80 drivers/tty/vt/selection.c:181
+> tioclinux+0x103/0x530 drivers/tty/vt/vt.c:3050
+> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364
+
+This is ioctl(TIOCL_SETSEL).
+Locks held on the path: console_lock -> sel_lock
+
+> -> #1 (console_lock){+.+.}:
+> console_lock+0x46/0x70 kernel/printk/printk.c:2289
+> con_flush_chars+0x50/0x650 drivers/tty/vt/vt.c:3223
+> n_tty_write+0xeae/0x1200 drivers/tty/n_tty.c:2350
+> do_tty_write drivers/tty/tty_io.c:962 [inline]
+> tty_write+0x5a1/0x950 drivers/tty/tty_io.c:1046
+
+This is write().
+Locks held on the path: termios_rwsem -> console_lock
+
+> -> #0 (&tty->termios_rwsem){++++}:
+> down_write+0x57/0x140 kernel/locking/rwsem.c:1534
+> tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
+> mkiss_receive_buf+0x12aa/0x1340 drivers/net/hamradio/mkiss.c:902
+> tty_ldisc_receive_buf+0x12f/0x170 drivers/tty/tty_buffer.c:465
+> paste_selection+0x346/0x470 drivers/tty/vt/selection.c:389
+> tioclinux+0x121/0x530 drivers/tty/vt/vt.c:3055
+> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364
+
+This is ioctl(TIOCL_PASTESEL).
+Locks held on the path: sel_lock -> termios_rwsem
+
+> other info that might help us debug this:
+>
+> Chain exists of:
+> &tty->termios_rwsem --> console_lock --> sel_lock
+
+Clearly. From the above, we have:
+ console_lock -> sel_lock
+ sel_lock -> termios_rwsem
+ termios_rwsem -> console_lock
+
+Fix this by reversing the console_lock -> sel_lock dependency in
+ioctl(TIOCL_SETSEL). First, lock sel_lock, then console_lock.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Reported-by: syzbot+26183d9746e62da329b8@syzkaller.appspotmail.com
+Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
+Link: https://lore.kernel.org/r/20200228115406.5735-2-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/tty/vt/selection.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+--- a/drivers/tty/vt/selection.c
++++ b/drivers/tty/vt/selection.c
+@@ -205,7 +205,6 @@ static int __set_selection(const struct
+ pe = tmp;
+ }
+
+- mutex_lock(&sel_lock);
+ if (sel_cons != vc_cons[fg_console].d) {
+ clear_selection();
+ sel_cons = vc_cons[fg_console].d;
+@@ -251,10 +250,9 @@ static int __set_selection(const struct
+ break;
+ case TIOCL_SELPOINTER:
+ highlight_pointer(pe);
+- goto unlock;
++ return 0;
+ default:
+- ret = -EINVAL;
+- goto unlock;
++ return -EINVAL;
+ }
+
+ /* remove the pointer */
+@@ -276,7 +274,7 @@ static int __set_selection(const struct
+ else if (new_sel_start == sel_start)
+ {
+ if (new_sel_end == sel_end) /* no action required */
+- goto unlock;
++ return 0;
+ else if (new_sel_end > sel_end) /* extend to right */
+ highlight(sel_end + 2, new_sel_end);
+ else /* contract from right */
+@@ -303,8 +301,7 @@ static int __set_selection(const struct
+ if (!bp) {
+ printk(KERN_WARNING "selection: kmalloc() failed\n");
+ clear_selection();
+- ret = -ENOMEM;
+- goto unlock;
++ return -ENOMEM;
+ }
+ kfree(sel_buffer);
+ sel_buffer = bp;
+@@ -329,8 +326,7 @@ static int __set_selection(const struct
+ }
+ }
+ sel_buffer_lth = bp - sel_buffer;
+-unlock:
+- mutex_unlock(&sel_lock);
++
+ return ret;
+ }
+
+@@ -338,9 +334,11 @@ int set_selection(const struct tiocl_sel
+ {
+ int ret;
+
++ mutex_lock(&sel_lock);
+ console_lock();
+ ret = __set_selection(v, tty);
+ console_unlock();
++ mutex_unlock(&sel_lock);
+
+ return ret;
+ }