]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 May 2019 15:27:19 +0000 (17:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 May 2019 15:27:19 +0000 (17:27 +0200)
added patches:
bcache-fix-a-race-between-cache-register-and-cacheset-unregister.patch
bcache-never-set-key_ptrs-of-journal-key-to-0-in-journal_reclaim.patch
btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch
ext4-actually-request-zeroing-of-inode-table-after-grow.patch
ext4-fix-ext4_show_options-for-file-systems-w-o-journal.patch
ipmi-ssif-compare-block-number-correctly-for-multi-part-return-messages.patch
mfd-da9063-fix-otp-control-register-names-to-match-datasheets-for-da9063-63l.patch
mm-mincore.c-make-mincore-more-conservative.patch
ocfs2-fix-ocfs2-read-inode-data-panic-in-ocfs2_iget.patch
tty-vt-fix-write-write-race-in-ioctl-kdskbsent-handler.patch

queue-4.4/bcache-fix-a-race-between-cache-register-and-cacheset-unregister.patch [new file with mode: 0644]
queue-4.4/bcache-never-set-key_ptrs-of-journal-key-to-0-in-journal_reclaim.patch [new file with mode: 0644]
queue-4.4/btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch [new file with mode: 0644]
queue-4.4/ext4-actually-request-zeroing-of-inode-table-after-grow.patch [new file with mode: 0644]
queue-4.4/ext4-fix-ext4_show_options-for-file-systems-w-o-journal.patch [new file with mode: 0644]
queue-4.4/ipmi-ssif-compare-block-number-correctly-for-multi-part-return-messages.patch [new file with mode: 0644]
queue-4.4/mfd-da9063-fix-otp-control-register-names-to-match-datasheets-for-da9063-63l.patch [new file with mode: 0644]
queue-4.4/mm-mincore.c-make-mincore-more-conservative.patch [new file with mode: 0644]
queue-4.4/ocfs2-fix-ocfs2-read-inode-data-panic-in-ocfs2_iget.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tty-vt-fix-write-write-race-in-ioctl-kdskbsent-handler.patch [new file with mode: 0644]

diff --git a/queue-4.4/bcache-fix-a-race-between-cache-register-and-cacheset-unregister.patch b/queue-4.4/bcache-fix-a-race-between-cache-register-and-cacheset-unregister.patch
new file mode 100644 (file)
index 0000000..5d8ef5c
--- /dev/null
@@ -0,0 +1,81 @@
+From a4b732a248d12cbdb46999daf0bf288c011335eb Mon Sep 17 00:00:00 2001
+From: Liang Chen <liangchen.linux@gmail.com>
+Date: Thu, 25 Apr 2019 00:48:31 +0800
+Subject: bcache: fix a race between cache register and cacheset unregister
+
+From: Liang Chen <liangchen.linux@gmail.com>
+
+commit a4b732a248d12cbdb46999daf0bf288c011335eb upstream.
+
+There is a race between cache device register and cache set unregister.
+For an already registered cache device, register_bcache will call
+bch_is_open to iterate through all cachesets and check every cache
+there. The race occurs if cache_set_free executes at the same time and
+clears the caches right before ca is dereferenced in bch_is_open_cache.
+To close the race, let's make sure the clean up work is protected by
+the bch_register_lock as well.
+
+This issue can be reproduced as follows,
+while true; do echo /dev/XXX> /sys/fs/bcache/register ; done&
+while true; do echo 1> /sys/block/XXX/bcache/set/unregister ; done &
+
+and results in the following oops,
+
+[  +0.000053] BUG: unable to handle kernel NULL pointer dereference at 0000000000000998
+[  +0.000457] #PF error: [normal kernel read fault]
+[  +0.000464] PGD 800000003ca9d067 P4D 800000003ca9d067 PUD 3ca9c067 PMD 0
+[  +0.000388] Oops: 0000 [#1] SMP PTI
+[  +0.000269] CPU: 1 PID: 3266 Comm: bash Not tainted 5.0.0+ #6
+[  +0.000346] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.fc28 04/01/2014
+[  +0.000472] RIP: 0010:register_bcache+0x1829/0x1990 [bcache]
+[  +0.000344] Code: b0 48 83 e8 50 48 81 fa e0 e1 10 c0 0f 84 a9 00 00 00 48 89 c6 48 89 ca 0f b7 ba 54 04 00 00 4c 8b 82 60 0c 00 00 85 ff 74 2f <49> 3b a8 98 09 00 00 74 4e 44 8d 47 ff 31 ff 49 c1 e0 03 eb 0d
+[  +0.000839] RSP: 0018:ffff92ee804cbd88 EFLAGS: 00010202
+[  +0.000328] RAX: ffffffffc010e190 RBX: ffff918b5c6b5000 RCX: ffff918b7d8e0000
+[  +0.000399] RDX: ffff918b7d8e0000 RSI: ffffffffc010e190 RDI: 0000000000000001
+[  +0.000398] RBP: ffff918b7d318340 R08: 0000000000000000 R09: ffffffffb9bd2d7a
+[  +0.000385] R10: ffff918b7eb253c0 R11: ffffb95980f51200 R12: ffffffffc010e1a0
+[  +0.000411] R13: fffffffffffffff2 R14: 000000000000000b R15: ffff918b7e232620
+[  +0.000384] FS:  00007f955bec2740(0000) GS:ffff918b7eb00000(0000) knlGS:0000000000000000
+[  +0.000420] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  +0.000801] CR2: 0000000000000998 CR3: 000000003cad6000 CR4: 00000000001406e0
+[  +0.000837] Call Trace:
+[  +0.000682]  ? _cond_resched+0x10/0x20
+[  +0.000691]  ? __kmalloc+0x131/0x1b0
+[  +0.000710]  kernfs_fop_write+0xfa/0x170
+[  +0.000733]  __vfs_write+0x2e/0x190
+[  +0.000688]  ? inode_security+0x10/0x30
+[  +0.000698]  ? selinux_file_permission+0xd2/0x120
+[  +0.000752]  ? security_file_permission+0x2b/0x100
+[  +0.000753]  vfs_write+0xa8/0x1a0
+[  +0.000676]  ksys_write+0x4d/0xb0
+[  +0.000699]  do_syscall_64+0x3a/0xf0
+[  +0.000692]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+Signed-off-by: Liang Chen <liangchen.linux@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Coly Li <colyli@suse.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bcache/super.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1355,6 +1355,7 @@ static void cache_set_free(struct closur
+       bch_btree_cache_free(c);
+       bch_journal_free(c);
++      mutex_lock(&bch_register_lock);
+       for_each_cache(ca, c, i)
+               if (ca) {
+                       ca->set = NULL;
+@@ -1377,7 +1378,6 @@ static void cache_set_free(struct closur
+               mempool_destroy(c->search);
+       kfree(c->devices);
+-      mutex_lock(&bch_register_lock);
+       list_del(&c->list);
+       mutex_unlock(&bch_register_lock);
diff --git a/queue-4.4/bcache-never-set-key_ptrs-of-journal-key-to-0-in-journal_reclaim.patch b/queue-4.4/bcache-never-set-key_ptrs-of-journal-key-to-0-in-journal_reclaim.patch
new file mode 100644 (file)
index 0000000..4ed4ba7
--- /dev/null
@@ -0,0 +1,96 @@
+From 1bee2addc0c8470c8aaa65ef0599eeae96dd88bc Mon Sep 17 00:00:00 2001
+From: Coly Li <colyli@suse.de>
+Date: Thu, 25 Apr 2019 00:48:33 +0800
+Subject: bcache: never set KEY_PTRS of journal key to 0 in journal_reclaim()
+
+From: Coly Li <colyli@suse.de>
+
+commit 1bee2addc0c8470c8aaa65ef0599eeae96dd88bc upstream.
+
+In journal_reclaim() ja->cur_idx of each cache will be update to
+reclaim available journal buckets. Variable 'int n' is used to count how
+many cache is successfully reclaimed, then n is set to c->journal.key
+by SET_KEY_PTRS(). Later in journal_write_unlocked(), a for_each_cache()
+loop will write the jset data onto each cache.
+
+The problem is, if all jouranl buckets on each cache is full, the
+following code in journal_reclaim(),
+
+529 for_each_cache(ca, c, iter) {
+530       struct journal_device *ja = &ca->journal;
+531       unsigned int next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
+532
+533       /* No space available on this device */
+534       if (next == ja->discard_idx)
+535               continue;
+536
+537       ja->cur_idx = next;
+538       k->ptr[n++] = MAKE_PTR(0,
+539                         bucket_to_sector(c, ca->sb.d[ja->cur_idx]),
+540                         ca->sb.nr_this_dev);
+541 }
+542
+543 bkey_init(k);
+544 SET_KEY_PTRS(k, n);
+
+If there is no available bucket to reclaim, the if() condition at line
+534 will always true, and n remains 0. Then at line 544, SET_KEY_PTRS()
+will set KEY_PTRS field of c->journal.key to 0.
+
+Setting KEY_PTRS field of c->journal.key to 0 is wrong. Because in
+journal_write_unlocked() the journal data is written in following loop,
+
+649    for (i = 0; i < KEY_PTRS(k); i++) {
+650-671                submit journal data to cache device
+672    }
+
+If KEY_PTRS field is set to 0 in jouranl_reclaim(), the journal data
+won't be written to cache device here. If system crahed or rebooted
+before bkeys of the lost journal entries written into btree nodes, data
+corruption will be reported during bcache reload after rebooting the
+system.
+
+Indeed there is only one cache in a cache set, there is no need to set
+KEY_PTRS field in journal_reclaim() at all. But in order to keep the
+for_each_cache() logic consistent for now, this patch fixes the above
+problem by not setting 0 KEY_PTRS of journal key, if there is no bucket
+available to reclaim.
+
+Signed-off-by: Coly Li <colyli@suse.de>
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bcache/journal.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/md/bcache/journal.c
++++ b/drivers/md/bcache/journal.c
+@@ -513,11 +513,11 @@ static void journal_reclaim(struct cache
+                                 ca->sb.nr_this_dev);
+       }
+-      bkey_init(k);
+-      SET_KEY_PTRS(k, n);
+-
+-      if (n)
++      if (n) {
++              bkey_init(k);
++              SET_KEY_PTRS(k, n);
+               c->journal.blocks_free = c->sb.bucket_size >> c->block_bits;
++      }
+ out:
+       if (!journal_full(&c->journal))
+               __closure_wake_up(&c->journal.wait);
+@@ -641,6 +641,9 @@ static void journal_write_unlocked(struc
+               ca->journal.seq[ca->journal.cur_idx] = w->data->seq;
+       }
++      /* If KEY_PTRS(k) == 0, this jset gets lost in air */
++      BUG_ON(i == 0);
++
+       atomic_dec_bug(&fifo_back(&c->journal.pin));
+       bch_journal_next(&c->journal);
+       journal_reclaim(c);
diff --git a/queue-4.4/btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch b/queue-4.4/btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch
new file mode 100644 (file)
index 0000000..110651f
--- /dev/null
@@ -0,0 +1,116 @@
+From bfc61c36260ca990937539cd648ede3cd749bc10 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 17 Apr 2019 11:30:30 +0100
+Subject: Btrfs: do not start a transaction at iterate_extent_inodes()
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit bfc61c36260ca990937539cd648ede3cd749bc10 upstream.
+
+When finding out which inodes have references on a particular extent, done
+by backref.c:iterate_extent_inodes(), from the BTRFS_IOC_LOGICAL_INO (both
+v1 and v2) ioctl and from scrub we use the transaction join API to grab a
+reference on the currently running transaction, since in order to give
+accurate results we need to inspect the delayed references of the currently
+running transaction.
+
+However, if there is currently no running transaction, the join operation
+will create a new transaction. This is inefficient as the transaction will
+eventually be committed, doing unnecessary IO and introducing a potential
+point of failure that will lead to a transaction abort due to -ENOSPC, as
+recently reported [1].
+
+That's because the join, creates the transaction but does not reserve any
+space, so when attempting to update the root item of the root passed to
+btrfs_join_transaction(), during the transaction commit, we can end up
+failling with -ENOSPC. Users of a join operation are supposed to actually
+do some filesystem changes and reserve space by some means, which is not
+the case of iterate_extent_inodes(), it is a read-only operation for all
+contextes from which it is called.
+
+The reported [1] -ENOSPC failure stack trace is the following:
+
+ heisenberg kernel: ------------[ cut here ]------------
+ heisenberg kernel: BTRFS: Transaction aborted (error -28)
+ heisenberg kernel: WARNING: CPU: 0 PID: 7137 at fs/btrfs/root-tree.c:136 btrfs_update_root+0x22b/0x320 [btrfs]
+(...)
+ heisenberg kernel: CPU: 0 PID: 7137 Comm: btrfs-transacti Not tainted 4.19.0-4-amd64 #1 Debian 4.19.28-2
+ heisenberg kernel: Hardware name: FUJITSU LIFEBOOK U757/FJNB2A5, BIOS Version 1.21 03/19/2018
+ heisenberg kernel: RIP: 0010:btrfs_update_root+0x22b/0x320 [btrfs]
+(...)
+ heisenberg kernel: RSP: 0018:ffffb5448828bd40 EFLAGS: 00010286
+ heisenberg kernel: RAX: 0000000000000000 RBX: ffff8ed56bccef50 RCX: 0000000000000006
+ heisenberg kernel: RDX: 0000000000000007 RSI: 0000000000000092 RDI: ffff8ed6bda166a0
+ heisenberg kernel: RBP: 00000000ffffffe4 R08: 00000000000003df R09: 0000000000000007
+ heisenberg kernel: R10: 0000000000000000 R11: 0000000000000001 R12: ffff8ed63396a078
+ heisenberg kernel: R13: ffff8ed092d7c800 R14: ffff8ed64f5db028 R15: ffff8ed6bd03d068
+ heisenberg kernel: FS:  0000000000000000(0000) GS:ffff8ed6bda00000(0000) knlGS:0000000000000000
+ heisenberg kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ heisenberg kernel: CR2: 00007f46f75f8000 CR3: 0000000310a0a002 CR4: 00000000003606f0
+ heisenberg kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ heisenberg kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+ heisenberg kernel: Call Trace:
+ heisenberg kernel:  commit_fs_roots+0x166/0x1d0 [btrfs]
+ heisenberg kernel:  ? _cond_resched+0x15/0x30
+ heisenberg kernel:  ? btrfs_run_delayed_refs+0xac/0x180 [btrfs]
+ heisenberg kernel:  btrfs_commit_transaction+0x2bd/0x870 [btrfs]
+ heisenberg kernel:  ? start_transaction+0x9d/0x3f0 [btrfs]
+ heisenberg kernel:  transaction_kthread+0x147/0x180 [btrfs]
+ heisenberg kernel:  ? btrfs_cleanup_transaction+0x530/0x530 [btrfs]
+ heisenberg kernel:  kthread+0x112/0x130
+ heisenberg kernel:  ? kthread_bind+0x30/0x30
+ heisenberg kernel:  ret_from_fork+0x35/0x40
+ heisenberg kernel: ---[ end trace 05de912e30e012d9 ]---
+
+So fix that by using the attach API, which does not create a transaction
+when there is currently no running transaction.
+
+[1] https://lore.kernel.org/linux-btrfs/b2a668d7124f1d3e410367f587926f622b3f03a4.camel@scientia.net/
+
+Reported-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/backref.c |   18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -1685,13 +1685,19 @@ int iterate_extent_inodes(struct btrfs_f
+                       extent_item_objectid);
+       if (!search_commit_root) {
+-              trans = btrfs_join_transaction(fs_info->extent_root);
+-              if (IS_ERR(trans))
+-                      return PTR_ERR(trans);
++              trans = btrfs_attach_transaction(fs_info->extent_root);
++              if (IS_ERR(trans)) {
++                      if (PTR_ERR(trans) != -ENOENT &&
++                          PTR_ERR(trans) != -EROFS)
++                              return PTR_ERR(trans);
++                      trans = NULL;
++              }
++      }
++
++      if (trans)
+               btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem);
+-      } else {
++      else
+               down_read(&fs_info->commit_root_sem);
+-      }
+       ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
+                                  tree_mod_seq_elem.seq, &refs,
+@@ -1721,7 +1727,7 @@ int iterate_extent_inodes(struct btrfs_f
+       free_leaf_list(refs);
+ out:
+-      if (!search_commit_root) {
++      if (trans) {
+               btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem);
+               btrfs_end_transaction(trans, fs_info->extent_root);
+       } else {
diff --git a/queue-4.4/ext4-actually-request-zeroing-of-inode-table-after-grow.patch b/queue-4.4/ext4-actually-request-zeroing-of-inode-table-after-grow.patch
new file mode 100644 (file)
index 0000000..73740fc
--- /dev/null
@@ -0,0 +1,37 @@
+From 310a997fd74de778b9a4848a64be9cda9f18764a Mon Sep 17 00:00:00 2001
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+Date: Thu, 25 Apr 2019 13:06:18 -0400
+Subject: ext4: actually request zeroing of inode table after grow
+
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+
+commit 310a997fd74de778b9a4848a64be9cda9f18764a upstream.
+
+It is never possible, that number of block groups decreases,
+since only online grow is supported.
+
+But after a growing occured, we have to zero inode tables
+for just created new block groups.
+
+Fixes: 19c5246d2516 ("ext4: add new online resize interface")
+Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ioctl.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -577,7 +577,7 @@ group_add_out:
+               if (err == 0)
+                       err = err2;
+               mnt_drop_write_file(filp);
+-              if (!err && (o_group > EXT4_SB(sb)->s_groups_count) &&
++              if (!err && (o_group < EXT4_SB(sb)->s_groups_count) &&
+                   ext4_has_group_desc_csum(sb) &&
+                   test_opt(sb, INIT_INODE_TABLE))
+                       err = ext4_register_li_request(sb, o_group);
diff --git a/queue-4.4/ext4-fix-ext4_show_options-for-file-systems-w-o-journal.patch b/queue-4.4/ext4-fix-ext4_show_options-for-file-systems-w-o-journal.patch
new file mode 100644 (file)
index 0000000..cf98f96
--- /dev/null
@@ -0,0 +1,35 @@
+From 50b29d8f033a7c88c5bc011abc2068b1691ab755 Mon Sep 17 00:00:00 2001
+From: Debabrata Banerjee <dbanerje@akamai.com>
+Date: Tue, 30 Apr 2019 23:08:15 -0400
+Subject: ext4: fix ext4_show_options for file systems w/o journal
+
+From: Debabrata Banerjee <dbanerje@akamai.com>
+
+commit 50b29d8f033a7c88c5bc011abc2068b1691ab755 upstream.
+
+Instead of removing EXT4_MOUNT_JOURNAL_CHECKSUM from s_def_mount_opt as
+I assume was intended, all other options were blown away leading to
+_ext4_show_options() output being incorrect.
+
+Fixes: 1e381f60dad9 ("ext4: do not allow journal_opts for fs w/o journal")
+Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3867,7 +3867,7 @@ static int ext4_fill_super(struct super_
+                                "data=, fs mounted w/o journal");
+                       goto failed_mount_wq;
+               }
+-              sbi->s_def_mount_opt &= EXT4_MOUNT_JOURNAL_CHECKSUM;
++              sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM;
+               clear_opt(sb, JOURNAL_CHECKSUM);
+               clear_opt(sb, DATA_FLAGS);
+               sbi->s_journal = NULL;
diff --git a/queue-4.4/ipmi-ssif-compare-block-number-correctly-for-multi-part-return-messages.patch b/queue-4.4/ipmi-ssif-compare-block-number-correctly-for-multi-part-return-messages.patch
new file mode 100644 (file)
index 0000000..52a1456
--- /dev/null
@@ -0,0 +1,50 @@
+From 55be8658c7e2feb11a5b5b33ee031791dbd23a69 Mon Sep 17 00:00:00 2001
+From: Kamlakant Patel <kamlakantp@marvell.com>
+Date: Wed, 24 Apr 2019 11:50:43 +0000
+Subject: ipmi:ssif: compare block number correctly for multi-part return messages
+
+From: Kamlakant Patel <kamlakantp@marvell.com>
+
+commit 55be8658c7e2feb11a5b5b33ee031791dbd23a69 upstream.
+
+According to ipmi spec, block number is a number that is incremented,
+starting with 0, for each new block of message data returned using the
+middle transaction.
+
+Here, the 'blocknum' is data[0] which always starts from zero(0) and
+'ssif_info->multi_pos' starts from 1.
+So, we need to add +1 to blocknum while comparing with multi_pos.
+
+Fixes: 7d6380cd40f79 ("ipmi:ssif: Fix handling of multi-part return messages").
+Reported-by: Kiran Kolukuluru <kirank@ami.com>
+Signed-off-by: Kamlakant Patel <kamlakantp@marvell.com>
+Message-Id: <1556106615-18722-1-git-send-email-kamlakantp@marvell.com>
+[Also added a debug log if the block numbers don't match.]
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Cc: stable@vger.kernel.org # 4.4
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_ssif.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/ipmi/ipmi_ssif.c
++++ b/drivers/char/ipmi/ipmi_ssif.c
+@@ -695,12 +695,16 @@ static void msg_done_handler(struct ssif
+                       /* End of read */
+                       len = ssif_info->multi_len;
+                       data = ssif_info->data;
+-              } else if (blocknum != ssif_info->multi_pos) {
++              } else if (blocknum + 1 != ssif_info->multi_pos) {
+                       /*
+                        * Out of sequence block, just abort.  Block
+                        * numbers start at zero for the second block,
+                        * but multi_pos starts at one, so the +1.
+                        */
++                      if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
++                              dev_dbg(&ssif_info->client->dev,
++                                      "Received message out of sequence, expected %u, got %u\n",
++                                      ssif_info->multi_pos - 1, blocknum);
+                       result = -EIO;
+               } else {
+                       ssif_inc_stat(ssif_info, received_message_parts);
diff --git a/queue-4.4/mfd-da9063-fix-otp-control-register-names-to-match-datasheets-for-da9063-63l.patch b/queue-4.4/mfd-da9063-fix-otp-control-register-names-to-match-datasheets-for-da9063-63l.patch
new file mode 100644 (file)
index 0000000..e35cb17
--- /dev/null
@@ -0,0 +1,39 @@
+From 6b4814a9451add06d457e198be418bf6a3e6a990 Mon Sep 17 00:00:00 2001
+From: Steve Twiss <stwiss.opensource@diasemi.com>
+Date: Fri, 26 Apr 2019 14:33:35 +0100
+Subject: mfd: da9063: Fix OTP control register names to match datasheets for DA9063/63L
+
+From: Steve Twiss <stwiss.opensource@diasemi.com>
+
+commit 6b4814a9451add06d457e198be418bf6a3e6a990 upstream.
+
+Mismatch between what is found in the Datasheets for DA9063 and DA9063L
+provided by Dialog Semiconductor, and the register names provided in the
+MFD registers file. The changes are for the OTP (one-time-programming)
+control registers. The two naming errors are OPT instead of OTP, and
+COUNT instead of CONT (i.e. control).
+
+Cc: Stable <stable@vger.kernel.org>
+Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/mfd/da9063/registers.h |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/include/linux/mfd/da9063/registers.h
++++ b/include/linux/mfd/da9063/registers.h
+@@ -215,9 +215,9 @@
+ /* DA9063 Configuration registers */
+ /* OTP */
+-#define       DA9063_REG_OPT_COUNT            0x101
+-#define       DA9063_REG_OPT_ADDR             0x102
+-#define       DA9063_REG_OPT_DATA             0x103
++#define       DA9063_REG_OTP_CONT             0x101
++#define       DA9063_REG_OTP_ADDR             0x102
++#define       DA9063_REG_OTP_DATA             0x103
+ /* Customer Trim and Configuration */
+ #define       DA9063_REG_T_OFFSET             0x104
diff --git a/queue-4.4/mm-mincore.c-make-mincore-more-conservative.patch b/queue-4.4/mm-mincore.c-make-mincore-more-conservative.patch
new file mode 100644 (file)
index 0000000..c47448f
--- /dev/null
@@ -0,0 +1,95 @@
+From 134fca9063ad4851de767d1768180e5dede9a881 Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Tue, 14 May 2019 15:41:38 -0700
+Subject: mm/mincore.c: make mincore() more conservative
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit 134fca9063ad4851de767d1768180e5dede9a881 upstream.
+
+The semantics of what mincore() considers to be resident is not
+completely clear, but Linux has always (since 2.3.52, which is when
+mincore() was initially done) treated it as "page is available in page
+cache".
+
+That's potentially a problem, as that [in]directly exposes
+meta-information about pagecache / memory mapping state even about
+memory not strictly belonging to the process executing the syscall,
+opening possibilities for sidechannel attacks.
+
+Change the semantics of mincore() so that it only reveals pagecache
+information for non-anonymous mappings that belog to files that the
+calling process could (if it tried to) successfully open for writing;
+otherwise we'd be including shared non-exclusive mappings, which
+
+ - is the sidechannel
+
+ - is not the usecase for mincore(), as that's primarily used for data,
+   not (shared) text
+
+[jkosina@suse.cz: v2]
+  Link: http://lkml.kernel.org/r/20190312141708.6652-2-vbabka@suse.cz
+[mhocko@suse.com: restructure can_do_mincore() conditions]
+Link: http://lkml.kernel.org/r/nycvar.YFH.7.76.1903062342020.19912@cbobk.fhfr.pm
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Acked-by: Josh Snyder <joshs@netflix.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Originally-by: Linus Torvalds <torvalds@linux-foundation.org>
+Originally-by: Dominique Martinet <asmadeus@codewreck.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Dave Chinner <david@fromorbit.com>
+Cc: Kevin Easton <kevin@guarana.org>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Cyril Hrubis <chrubis@suse.cz>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Kirill A. Shutemov <kirill@shutemov.name>
+Cc: Daniel Gruss <daniel@gruss.cc>
+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>
+
+---
+ mm/mincore.c |   23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+--- a/mm/mincore.c
++++ b/mm/mincore.c
+@@ -165,6 +165,22 @@ out:
+       return 0;
+ }
++static inline bool can_do_mincore(struct vm_area_struct *vma)
++{
++      if (vma_is_anonymous(vma))
++              return true;
++      if (!vma->vm_file)
++              return false;
++      /*
++       * Reveal pagecache information only for non-anonymous mappings that
++       * correspond to the files the calling process could (if tried) open
++       * for writing; otherwise we'd be including shared non-exclusive
++       * mappings, which opens a side channel.
++       */
++      return inode_owner_or_capable(file_inode(vma->vm_file)) ||
++              inode_permission(file_inode(vma->vm_file), MAY_WRITE) == 0;
++}
++
+ /*
+  * Do a chunk of "sys_mincore()". We've already checked
+  * all the arguments, we hold the mmap semaphore: we should
+@@ -185,8 +201,13 @@ static long do_mincore(unsigned long add
+       vma = find_vma(current->mm, addr);
+       if (!vma || addr < vma->vm_start)
+               return -ENOMEM;
+-      mincore_walk.mm = vma->vm_mm;
+       end = min(vma->vm_end, addr + (pages << PAGE_SHIFT));
++      if (!can_do_mincore(vma)) {
++              unsigned long pages = DIV_ROUND_UP(end - addr, PAGE_SIZE);
++              memset(vec, 1, pages);
++              return pages;
++      }
++      mincore_walk.mm = vma->vm_mm;
+       err = walk_page_range(addr, end, &mincore_walk);
+       if (err < 0)
+               return err;
diff --git a/queue-4.4/ocfs2-fix-ocfs2-read-inode-data-panic-in-ocfs2_iget.patch b/queue-4.4/ocfs2-fix-ocfs2-read-inode-data-panic-in-ocfs2_iget.patch
new file mode 100644 (file)
index 0000000..9338af4
--- /dev/null
@@ -0,0 +1,180 @@
+From e091eab028f9253eac5c04f9141bbc9d170acab3 Mon Sep 17 00:00:00 2001
+From: Shuning Zhang <sunny.s.zhang@oracle.com>
+Date: Mon, 13 May 2019 17:15:56 -0700
+Subject: ocfs2: fix ocfs2 read inode data panic in ocfs2_iget
+
+From: Shuning Zhang <sunny.s.zhang@oracle.com>
+
+commit e091eab028f9253eac5c04f9141bbc9d170acab3 upstream.
+
+In some cases, ocfs2_iget() reads the data of inode, which has been
+deleted for some reason.  That will make the system panic.  So We should
+judge whether this inode has been deleted, and tell the caller that the
+inode is a bad inode.
+
+For example, the ocfs2 is used as the backed of nfs, and the client is
+nfsv3.  This issue can be reproduced by the following steps.
+
+on the nfs server side,
+..../patha/pathb
+
+Step 1: The process A was scheduled before calling the function fh_verify.
+
+Step 2: The process B is removing the 'pathb', and just completed the call
+to function dput.  Then the dentry of 'pathb' has been deleted from the
+dcache, and all ancestors have been deleted also.  The relationship of
+dentry and inode was deleted through the function hlist_del_init.  The
+following is the call stack.
+dentry_iput->hlist_del_init(&dentry->d_u.d_alias)
+
+At this time, the inode is still in the dcache.
+
+Step 3: The process A call the function ocfs2_get_dentry, which get the
+inode from dcache.  Then the refcount of inode is 1.  The following is the
+call stack.
+nfsd3_proc_getacl->fh_verify->exportfs_decode_fh->fh_to_dentry(ocfs2_get_dentry)
+
+Step 4: Dirty pages are flushed by bdi threads.  So the inode of 'patha'
+is evicted, and this directory was deleted.  But the inode of 'pathb'
+can't be evicted, because the refcount of the inode was 1.
+
+Step 5: The process A keep running, and call the function
+reconnect_path(in exportfs_decode_fh), which call function
+ocfs2_get_parent of ocfs2.  Get the block number of parent
+directory(patha) by the name of ...  Then read the data from disk by the
+block number.  But this inode has been deleted, so the system panic.
+
+Process A                                             Process B
+1. in nfsd3_proc_getacl                   |
+2.                                        |        dput
+3. fh_to_dentry(ocfs2_get_dentry)         |
+4. bdi flush dirty cache                  |
+5. ocfs2_iget                             |
+
+[283465.542049] OCFS2: ERROR (device sdp): ocfs2_validate_inode_block:
+Invalid dinode #580640: OCFS2_VALID_FL not set
+
+[283465.545490] Kernel panic - not syncing: OCFS2: (device sdp): panic forced
+after error
+
+[283465.546889] CPU: 5 PID: 12416 Comm: nfsd Tainted: G        W
+4.1.12-124.18.6.el6uek.bug28762940v3.x86_64 #2
+[283465.548382] Hardware name: VMware, Inc. VMware Virtual Platform/440BX
+Desktop Reference Platform, BIOS 6.00 09/21/2015
+[283465.549657]  0000000000000000 ffff8800a56fb7b8 ffffffff816e839c
+ffffffffa0514758
+[283465.550392]  000000000008dc20 ffff8800a56fb838 ffffffff816e62d3
+0000000000000008
+[283465.551056]  ffff880000000010 ffff8800a56fb848 ffff8800a56fb7e8
+ffff88005df9f000
+[283465.551710] Call Trace:
+[283465.552516]  [<ffffffff816e839c>] dump_stack+0x63/0x81
+[283465.553291]  [<ffffffff816e62d3>] panic+0xcb/0x21b
+[283465.554037]  [<ffffffffa04e66b0>] ocfs2_handle_error+0xf0/0xf0 [ocfs2]
+[283465.554882]  [<ffffffffa04e7737>] __ocfs2_error+0x67/0x70 [ocfs2]
+[283465.555768]  [<ffffffffa049c0f9>] ocfs2_validate_inode_block+0x229/0x230
+[ocfs2]
+[283465.556683]  [<ffffffffa047bcbc>] ocfs2_read_blocks+0x46c/0x7b0 [ocfs2]
+[283465.557408]  [<ffffffffa049bed0>] ? ocfs2_inode_cache_io_unlock+0x20/0x20
+[ocfs2]
+[283465.557973]  [<ffffffffa049f0eb>] ocfs2_read_inode_block_full+0x3b/0x60
+[ocfs2]
+[283465.558525]  [<ffffffffa049f5ba>] ocfs2_iget+0x4aa/0x880 [ocfs2]
+[283465.559082]  [<ffffffffa049146e>] ocfs2_get_parent+0x9e/0x220 [ocfs2]
+[283465.559622]  [<ffffffff81297c05>] reconnect_path+0xb5/0x300
+[283465.560156]  [<ffffffff81297f46>] exportfs_decode_fh+0xf6/0x2b0
+[283465.560708]  [<ffffffffa062faf0>] ? nfsd_proc_getattr+0xa0/0xa0 [nfsd]
+[283465.561262]  [<ffffffff810a8196>] ? prepare_creds+0x26/0x110
+[283465.561932]  [<ffffffffa0630860>] fh_verify+0x350/0x660 [nfsd]
+[283465.562862]  [<ffffffffa0637804>] ? nfsd_cache_lookup+0x44/0x630 [nfsd]
+[283465.563697]  [<ffffffffa063a8b9>] nfsd3_proc_getattr+0x69/0xf0 [nfsd]
+[283465.564510]  [<ffffffffa062cf60>] nfsd_dispatch+0xe0/0x290 [nfsd]
+[283465.565358]  [<ffffffffa05eb892>] ? svc_tcp_adjust_wspace+0x12/0x30
+[sunrpc]
+[283465.566272]  [<ffffffffa05ea652>] svc_process_common+0x412/0x6a0 [sunrpc]
+[283465.567155]  [<ffffffffa05eaa03>] svc_process+0x123/0x210 [sunrpc]
+[283465.568020]  [<ffffffffa062c90f>] nfsd+0xff/0x170 [nfsd]
+[283465.568962]  [<ffffffffa062c810>] ? nfsd_destroy+0x80/0x80 [nfsd]
+[283465.570112]  [<ffffffff810a622b>] kthread+0xcb/0xf0
+[283465.571099]  [<ffffffff810a6160>] ? kthread_create_on_node+0x180/0x180
+[283465.572114]  [<ffffffff816f11b8>] ret_from_fork+0x58/0x90
+[283465.573156]  [<ffffffff810a6160>] ? kthread_create_on_node+0x180/0x180
+
+Link: http://lkml.kernel.org/r/1554185919-3010-1-git-send-email-sunny.s.zhang@oracle.com
+Signed-off-by: Shuning Zhang <sunny.s.zhang@oracle.com>
+Reviewed-by: Joseph Qi <jiangqi903@gmail.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: piaojun <piaojun@huawei.com>
+Cc: "Gang He" <ghe@suse.com>
+Cc: <stable@vger.kernel.org>
+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>
+
+---
+ fs/ocfs2/export.c |   30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+--- a/fs/ocfs2/export.c
++++ b/fs/ocfs2/export.c
+@@ -148,16 +148,24 @@ static struct dentry *ocfs2_get_parent(s
+       u64 blkno;
+       struct dentry *parent;
+       struct inode *dir = d_inode(child);
++      int set;
+       trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
+                              (unsigned long long)OCFS2_I(dir)->ip_blkno);
++      status = ocfs2_nfs_sync_lock(OCFS2_SB(dir->i_sb), 1);
++      if (status < 0) {
++              mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d\n", status);
++              parent = ERR_PTR(status);
++              goto bail;
++      }
++
+       status = ocfs2_inode_lock(dir, NULL, 0);
+       if (status < 0) {
+               if (status != -ENOENT)
+                       mlog_errno(status);
+               parent = ERR_PTR(status);
+-              goto bail;
++              goto unlock_nfs_sync;
+       }
+       status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno);
+@@ -166,11 +174,31 @@ static struct dentry *ocfs2_get_parent(s
+               goto bail_unlock;
+       }
++      status = ocfs2_test_inode_bit(OCFS2_SB(dir->i_sb), blkno, &set);
++      if (status < 0) {
++              if (status == -EINVAL) {
++                      status = -ESTALE;
++              } else
++                      mlog(ML_ERROR, "test inode bit failed %d\n", status);
++              parent = ERR_PTR(status);
++              goto bail_unlock;
++      }
++
++      trace_ocfs2_get_dentry_test_bit(status, set);
++      if (!set) {
++              status = -ESTALE;
++              parent = ERR_PTR(status);
++              goto bail_unlock;
++      }
++
+       parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0));
+ bail_unlock:
+       ocfs2_inode_unlock(dir, 0);
++unlock_nfs_sync:
++      ocfs2_nfs_sync_unlock(OCFS2_SB(dir->i_sb), 1);
++
+ bail:
+       trace_ocfs2_get_parent_end(parent);
index cab370fe99c94f93565dbd7889886167238d1e89..dcead326239be1820b8de725de88a690be61391d 100644 (file)
@@ -9,3 +9,13 @@ alsa-hda-hdmi-consider-eld_valid-when-reporting-jack-event.patch
 alsa-hda-realtek-eapd-turn-on-later.patch
 asoc-max98090-fix-restore-of-dapm-muxes.patch
 asoc-rt5677-spi-disable-16bit-spi-transfers.patch
+mm-mincore.c-make-mincore-more-conservative.patch
+ocfs2-fix-ocfs2-read-inode-data-panic-in-ocfs2_iget.patch
+mfd-da9063-fix-otp-control-register-names-to-match-datasheets-for-da9063-63l.patch
+tty-vt-fix-write-write-race-in-ioctl-kdskbsent-handler.patch
+ext4-actually-request-zeroing-of-inode-table-after-grow.patch
+ext4-fix-ext4_show_options-for-file-systems-w-o-journal.patch
+btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch
+bcache-fix-a-race-between-cache-register-and-cacheset-unregister.patch
+bcache-never-set-key_ptrs-of-journal-key-to-0-in-journal_reclaim.patch
+ipmi-ssif-compare-block-number-correctly-for-multi-part-return-messages.patch
diff --git a/queue-4.4/tty-vt-fix-write-write-race-in-ioctl-kdskbsent-handler.patch b/queue-4.4/tty-vt-fix-write-write-race-in-ioctl-kdskbsent-handler.patch
new file mode 100644 (file)
index 0000000..3c483ae
--- /dev/null
@@ -0,0 +1,183 @@
+From 46ca3f735f345c9d87383dd3a09fa5d43870770e Mon Sep 17 00:00:00 2001
+From: Sergei Trofimovich <slyfox@gentoo.org>
+Date: Sun, 10 Mar 2019 21:24:15 +0000
+Subject: tty/vt: fix write/write race in ioctl(KDSKBSENT) handler
+
+From: Sergei Trofimovich <slyfox@gentoo.org>
+
+commit 46ca3f735f345c9d87383dd3a09fa5d43870770e upstream.
+
+The bug manifests as an attempt to access deallocated memory:
+
+    BUG: unable to handle kernel paging request at ffff9c8735448000
+    #PF error: [PROT] [WRITE]
+    PGD 288a05067 P4D 288a05067 PUD 288a07067 PMD 7f60c2063 PTE 80000007f5448161
+    Oops: 0003 [#1] PREEMPT SMP
+    CPU: 6 PID: 388 Comm: loadkeys Tainted: G         C        5.0.0-rc6-00153-g5ded5871030e #91
+    Hardware name: Gigabyte Technology Co., Ltd. To be filled by O.E.M./H77M-D3H, BIOS F12 11/14/2013
+    RIP: 0010:__memmove+0x81/0x1a0
+    Code: 4c 89 4f 10 4c 89 47 18 48 8d 7f 20 73 d4 48 83 c2 20 e9 a2 00 00 00 66 90 48 89 d1 4c 8b 5c 16 f8 4c 8d 54 17 f8 48 c1 e9 03 <f3> 48 a5 4d 89 1a e9 0c 01 00 00 0f 1f 40 00 48 89 d1 4c 8b 1e 49
+    RSP: 0018:ffffa1b9002d7d08 EFLAGS: 00010203
+    RAX: ffff9c873541af43 RBX: ffff9c873541af43 RCX: 00000c6f105cd6bf
+    RDX: 0000637882e986b6 RSI: ffff9c8735447ffb RDI: ffff9c8735447ffb
+    RBP: ffff9c8739cd3800 R08: ffff9c873b802f00 R09: 00000000fffff73b
+    R10: ffffffffb82b35f1 R11: 00505b1b004d5b1b R12: 0000000000000000
+    R13: ffff9c873541af3d R14: 000000000000000b R15: 000000000000000c
+    FS:  00007f450c390580(0000) GS:ffff9c873f180000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: ffff9c8735448000 CR3: 00000007e213c002 CR4: 00000000000606e0
+    Call Trace:
+     vt_do_kdgkb_ioctl+0x34d/0x440
+     vt_ioctl+0xba3/0x1190
+     ? __bpf_prog_run32+0x39/0x60
+     ? mem_cgroup_commit_charge+0x7b/0x4e0
+     tty_ioctl+0x23f/0x920
+     ? preempt_count_sub+0x98/0xe0
+     ? __seccomp_filter+0x67/0x600
+     do_vfs_ioctl+0xa2/0x6a0
+     ? syscall_trace_enter+0x192/0x2d0
+     ksys_ioctl+0x3a/0x70
+     __x64_sys_ioctl+0x16/0x20
+     do_syscall_64+0x54/0xe0
+     entry_SYSCALL_64_after_hwframe+0x49/0xbe
+
+The bug manifests on systemd systems with multiple vtcon devices:
+  # cat /sys/devices/virtual/vtconsole/vtcon0/name
+  (S) dummy device
+  # cat /sys/devices/virtual/vtconsole/vtcon1/name
+  (M) frame buffer device
+
+There systemd runs 'loadkeys' tool in tapallel for each vtcon
+instance. This causes two parallel ioctl(KDSKBSENT) calls to
+race into adding the same entry into 'func_table' array at:
+
+    drivers/tty/vt/keyboard.c:vt_do_kdgkb_ioctl()
+
+The function has no locking around writes to 'func_table'.
+
+The simplest reproducer is to have initrams with the following
+init on a 8-CPU machine x86_64:
+
+    #!/bin/sh
+
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+    loadkeys -q windowkeys ru4 &
+    wait
+
+The change adds lock on write path only. Reads are still racy.
+
+CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+CC: Jiri Slaby <jslaby@suse.com>
+Link: https://lkml.org/lkml/2019/2/17/256
+Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/keyboard.c |   33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -121,6 +121,7 @@ static const int NR_TYPES = ARRAY_SIZE(m
+ static struct input_handler kbd_handler;
+ static DEFINE_SPINLOCK(kbd_event_lock);
+ static DEFINE_SPINLOCK(led_lock);
++static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf'  and friends */
+ static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];        /* keyboard key bitmap */
+ static unsigned char shift_down[NR_SHIFT];            /* shift state counters.. */
+ static bool dead_key_next;
+@@ -1969,11 +1970,12 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+       char *p;
+       u_char *q;
+       u_char __user *up;
+-      int sz;
++      int sz, fnw_sz;
+       int delta;
+       char *first_free, *fj, *fnw;
+       int i, j, k;
+       int ret;
++      unsigned long flags;
+       if (!capable(CAP_SYS_TTY_CONFIG))
+               perm = 0;
+@@ -2016,7 +2018,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+                       goto reterr;
+               }
++              fnw = NULL;
++              fnw_sz = 0;
++              /* race aginst other writers */
++              again:
++              spin_lock_irqsave(&func_buf_lock, flags);
+               q = func_table[i];
++
++              /* fj pointer to next entry after 'q' */
+               first_free = funcbufptr + (funcbufsize - funcbufleft);
+               for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
+                       ;
+@@ -2024,10 +2033,12 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+                       fj = func_table[j];
+               else
+                       fj = first_free;
+-
++              /* buffer usage increase by new entry */
+               delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
++
+               if (delta <= funcbufleft) {     /* it fits in current buf */
+                   if (j < MAX_NR_FUNC) {
++                      /* make enough space for new entry at 'fj' */
+                       memmove(fj + delta, fj, first_free - fj);
+                       for (k = j; k < MAX_NR_FUNC; k++)
+                           if (func_table[k])
+@@ -2040,20 +2051,28 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+                   sz = 256;
+                   while (sz < funcbufsize - funcbufleft + delta)
+                     sz <<= 1;
+-                  fnw = kmalloc(sz, GFP_KERNEL);
+-                  if(!fnw) {
+-                    ret = -ENOMEM;
+-                    goto reterr;
++                  if (fnw_sz != sz) {
++                    spin_unlock_irqrestore(&func_buf_lock, flags);
++                    kfree(fnw);
++                    fnw = kmalloc(sz, GFP_KERNEL);
++                    fnw_sz = sz;
++                    if (!fnw) {
++                      ret = -ENOMEM;
++                      goto reterr;
++                    }
++                    goto again;
+                   }
+                   if (!q)
+                     func_table[i] = fj;
++                  /* copy data before insertion point to new location */
+                   if (fj > funcbufptr)
+                       memmove(fnw, funcbufptr, fj - funcbufptr);
+                   for (k = 0; k < j; k++)
+                     if (func_table[k])
+                       func_table[k] = fnw + (func_table[k] - funcbufptr);
++                  /* copy data after insertion point to new location */
+                   if (first_free > fj) {
+                       memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
+                       for (k = j; k < MAX_NR_FUNC; k++)
+@@ -2066,7 +2085,9 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+                   funcbufleft = funcbufleft - delta + sz - funcbufsize;
+                   funcbufsize = sz;
+               }
++              /* finally insert item itself */
+               strcpy(func_table[i], kbs->kb_string);
++              spin_unlock_irqrestore(&func_buf_lock, flags);
+               break;
+       }
+       ret = 0;