From: Greg Kroah-Hartman Date: Tue, 21 Apr 2020 17:26:19 +0000 (+0200) Subject: 5.6-stable patches X-Git-Tag: v4.19.118~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d5b79a1547af87f529430701dbf1025587aaa9d2;p=thirdparty%2Fkernel%2Fstable-queue.git 5.6-stable patches added patches: afs-fix-afs_d_validate-to-set-the-right-directory-version.patch afs-fix-decoding-of-inline-abort-codes-from-version-1-status-records.patch afs-fix-missing-xdr-advance-in-xdr_decode_-afs-yfs-fsfetchstatus.patch afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch afs-fix-rename-operation-status-delivery.patch alsa-hda-don-t-release-card-at-firmware-loading-error.patch arm-dts-imx6-use-gpc-for-fec-interrupt-controller-to-fix-wake-on-lan.patch irqchip-mbigen-free-msi_desc-on-device-teardown.patch kbuild-btf-fix-dependencies-for-debug_info_btf.patch netfilter-nf_tables-report-eopnotsupp-on-unsupported-flags-object-type.patch of-overlay-kmemleak-in-dup_and_fixup_symbol_prop.patch of-unittest-kmemleak-in-of_unittest_overlay_high_level.patch of-unittest-kmemleak-in-of_unittest_platform_populate.patch of-unittest-kmemleak-on-changeset-destroy.patch rbd-avoid-a-deadlock-on-header_rwsem-when-flushing-notifies.patch rbd-call-rbd_dev_unprobe-after-unwatching-and-flushing-notifies.patch rbd-don-t-test-rbd_dev-opts-in-rbd_dev_image_release.patch x86-hyper-v-free-hv_panic_page-when-fail-to-register-kmsg-dump.patch x86-hyper-v-report-crash-data-in-die-when-panic_on_oops-is-set.patch x86-hyper-v-report-crash-register-data-or-kmsg-before-running-crash-kernel.patch x86-hyper-v-report-crash-register-data-when-sysctl_record_panic_msg-is-not-set.patch x86-hyper-v-trigger-crash-enlightenment-only-once-during-system-crash.patch x86-hyper-v-unload-vmbus-channel-in-hv-panic-callback.patch xsk-add-missing-check-on-user-supplied-headroom-size.patch --- diff --git a/queue-5.6/afs-fix-afs_d_validate-to-set-the-right-directory-version.patch b/queue-5.6/afs-fix-afs_d_validate-to-set-the-right-directory-version.patch new file mode 100644 index 00000000000..b783f88353a --- /dev/null +++ b/queue-5.6/afs-fix-afs_d_validate-to-set-the-right-directory-version.patch @@ -0,0 +1,47 @@ +From 40fc81027f892284ce31f8b6de1e497f5b47e71f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Sat, 11 Apr 2020 08:50:45 +0100 +Subject: afs: Fix afs_d_validate() to set the right directory version + +From: David Howells + +commit 40fc81027f892284ce31f8b6de1e497f5b47e71f upstream. + +If a dentry's version is somewhere between invalid_before and the current +directory version, we should be setting it forward to the current version, +not backwards to the invalid_before version. Note that we're only doing +this at all because dentry::d_fsdata isn't large enough on a 32-bit system. + +Fix this by using a separate variable for invalid_before so that we don't +accidentally clobber the current dir version. + +Fixes: a4ff7401fbfa ("afs: Keep track of invalid-before version for dentry coherency") +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + fs/afs/dir.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/afs/dir.c ++++ b/fs/afs/dir.c +@@ -1032,7 +1032,7 @@ static int afs_d_revalidate(struct dentr + struct dentry *parent; + struct inode *inode; + struct key *key; +- afs_dataversion_t dir_version; ++ afs_dataversion_t dir_version, invalid_before; + long de_version; + int ret; + +@@ -1084,8 +1084,8 @@ static int afs_d_revalidate(struct dentr + if (de_version == (long)dir_version) + goto out_valid_noupdate; + +- dir_version = dir->invalid_before; +- if (de_version - (long)dir_version >= 0) ++ invalid_before = dir->invalid_before; ++ if (de_version - (long)invalid_before >= 0) + goto out_valid; + + _debug("dir modified"); diff --git a/queue-5.6/afs-fix-decoding-of-inline-abort-codes-from-version-1-status-records.patch b/queue-5.6/afs-fix-decoding-of-inline-abort-codes-from-version-1-status-records.patch new file mode 100644 index 00000000000..fc0ba3a71ff --- /dev/null +++ b/queue-5.6/afs-fix-decoding-of-inline-abort-codes-from-version-1-status-records.patch @@ -0,0 +1,38 @@ +From 3e0d9892c0e7fa426ca6bf921cb4b543ca265714 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 8 Apr 2020 17:32:10 +0100 +Subject: afs: Fix decoding of inline abort codes from version 1 status records + +From: David Howells + +commit 3e0d9892c0e7fa426ca6bf921cb4b543ca265714 upstream. + +If we're decoding an AFSFetchStatus record and we see that the version is 1 +and the abort code is set and we're expecting inline errors, then we store +the abort code and ignore the remaining status record (which is correct), +but we don't set the flag to say we got a valid abort code. + +This can affect operation of YFS.RemoveFile2 when removing a file and the +operation of {,Y}FS.InlineBulkStatus when prospectively constructing or +updating of a set of inodes during a lookup. + +Fix this to indicate the reception of a valid abort code. + +Fixes: a38a75581e6e ("afs: Fix unlink to handle YFS.RemoveFile2 better") +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + fs/afs/fsclient.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/afs/fsclient.c ++++ b/fs/afs/fsclient.c +@@ -88,6 +88,7 @@ static int xdr_decode_AFSFetchStatus(con + + if (abort_code != 0 && inline_error) { + status->abort_code = abort_code; ++ scb->have_error = true; + goto good; + } + diff --git a/queue-5.6/afs-fix-missing-xdr-advance-in-xdr_decode_-afs-yfs-fsfetchstatus.patch b/queue-5.6/afs-fix-missing-xdr-advance-in-xdr_decode_-afs-yfs-fsfetchstatus.patch new file mode 100644 index 00000000000..d08716b9aae --- /dev/null +++ b/queue-5.6/afs-fix-missing-xdr-advance-in-xdr_decode_-afs-yfs-fsfetchstatus.patch @@ -0,0 +1,122 @@ +From c72057b56f7e24865840a6961d801a7f21d30a5f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 8 Apr 2020 16:13:20 +0100 +Subject: afs: Fix missing XDR advance in xdr_decode_{AFS,YFS}FSFetchStatus() + +From: David Howells + +commit c72057b56f7e24865840a6961d801a7f21d30a5f upstream. + +If we receive a status record that has VNOVNODE set in the abort field, +xdr_decode_AFSFetchStatus() and xdr_decode_YFSFetchStatus() don't advance +the XDR pointer, thereby corrupting anything subsequent decodes from the +same block of data. + +This has the potential to affect AFS.InlineBulkStatus and +YFS.InlineBulkStatus operation, but probably doesn't since the status +records are extracted as individual blocks of data and the buffer pointer +is reset between blocks. + +It does affect YFS.RemoveFile2 operation, corrupting the volsync record - +though that is not currently used. + +Other operations abort the entire operation rather than returning an error +inline, in which case there is no decoding to be done. + +Fix this by unconditionally advancing the xdr pointer. + +Fixes: 684b0f68cf1c ("afs: Fix AFSFetchStatus decoder to provide OpenAFS compatibility") +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + fs/afs/fsclient.c | 14 +++++++++----- + fs/afs/yfsclient.c | 12 ++++++++---- + 2 files changed, 17 insertions(+), 9 deletions(-) + +--- a/fs/afs/fsclient.c ++++ b/fs/afs/fsclient.c +@@ -65,6 +65,7 @@ static int xdr_decode_AFSFetchStatus(con + bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); + u64 data_version, size; + u32 type, abort_code; ++ int ret; + + abort_code = ntohl(xdr->abort_code); + +@@ -78,7 +79,7 @@ static int xdr_decode_AFSFetchStatus(con + */ + status->abort_code = abort_code; + scb->have_error = true; +- return 0; ++ goto good; + } + + pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); +@@ -87,7 +88,7 @@ static int xdr_decode_AFSFetchStatus(con + + if (abort_code != 0 && inline_error) { + status->abort_code = abort_code; +- return 0; ++ goto good; + } + + type = ntohl(xdr->type); +@@ -123,13 +124,16 @@ static int xdr_decode_AFSFetchStatus(con + data_version |= (u64)ntohl(xdr->data_version_hi) << 32; + status->data_version = data_version; + scb->have_status = true; +- ++good: ++ ret = 0; ++advance: + *_bp = (const void *)*_bp + sizeof(*xdr); +- return 0; ++ return ret; + + bad: + xdr_dump_bad(*_bp); +- return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); ++ ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); ++ goto advance; + } + + static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) +--- a/fs/afs/yfsclient.c ++++ b/fs/afs/yfsclient.c +@@ -186,13 +186,14 @@ static int xdr_decode_YFSFetchStatus(con + const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp; + struct afs_file_status *status = &scb->status; + u32 type; ++ int ret; + + status->abort_code = ntohl(xdr->abort_code); + if (status->abort_code != 0) { + if (status->abort_code == VNOVNODE) + status->nlink = 0; + scb->have_error = true; +- return 0; ++ goto good; + } + + type = ntohl(xdr->type); +@@ -220,13 +221,16 @@ static int xdr_decode_YFSFetchStatus(con + status->size = xdr_to_u64(xdr->size); + status->data_version = xdr_to_u64(xdr->data_version); + scb->have_status = true; +- ++good: ++ ret = 0; ++advance: + *_bp += xdr_size(xdr); +- return 0; ++ return ret; + + bad: + xdr_dump_bad(*_bp); +- return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); ++ ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); ++ goto advance; + } + + /* diff --git a/queue-5.6/afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch b/queue-5.6/afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch new file mode 100644 index 00000000000..9f7c9cf9b68 --- /dev/null +++ b/queue-5.6/afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch @@ -0,0 +1,351 @@ +From 2105c2820d366b76f38e6ad61c75771881ecc532 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 10 Apr 2020 15:23:27 +0100 +Subject: afs: Fix race between post-modification dir edit and readdir/d_revalidate + +From: David Howells + +commit 2105c2820d366b76f38e6ad61c75771881ecc532 upstream. + +AFS directories are retained locally as a structured file, with lookup +being effected by a local search of the file contents. When a modification +(such as mkdir) happens, the dir file content is modified locally rather +than redownloading the directory. + +The directory contents are accessed in a number of ways, with a number of +different locks schemes: + + (1) Download of contents - dvnode->validate_lock/write in afs_read_dir(). + + (2) Lookup and readdir - dvnode->validate_lock/read in afs_dir_iterate(), + downgrading from (1) if necessary. + + (3) d_revalidate of child dentry - dvnode->validate_lock/read in + afs_do_lookup_one() downgrading from (1) if necessary. + + (4) Edit of dir after modification - page locks on individual dir pages. + +Unfortunately, because (4) uses different locking scheme to (1) - (3), +nothing protects against the page being scanned whilst the edit is +underway. Even download is not safe as it doesn't lock the pages - relying +instead on the validate_lock to serialise as a whole (the theory being that +directory contents are treated as a block and always downloaded as a +block). + +Fix this by write-locking dvnode->validate_lock around the edits. Care +must be taken in the rename case as there may be two different dirs - but +they need not be locked at the same time. In any case, once the lock is +taken, the directory version must be rechecked, and the edit skipped if a +later version has been downloaded by revalidation (there can't have been +any local changes because the VFS holds the inode lock, but there can have +been remote changes). + +Fixes: 63a4681ff39c ("afs: Locally edit directory data for mkdir/create/unlink/...") +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + fs/afs/dir.c | 91 ++++++++++++++++++++++++++++++++++++----------------- + fs/afs/dir_silly.c | 22 ++++++++---- + 2 files changed, 77 insertions(+), 36 deletions(-) + +--- a/fs/afs/dir.c ++++ b/fs/afs/dir.c +@@ -1275,6 +1275,7 @@ static int afs_mkdir(struct inode *dir, + struct afs_fs_cursor fc; + struct afs_vnode *dvnode = AFS_FS_I(dir); + struct key *key; ++ afs_dataversion_t data_version; + int ret; + + mode |= S_IFDIR; +@@ -1295,7 +1296,7 @@ static int afs_mkdir(struct inode *dir, + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t data_version = dvnode->status.data_version + 1; ++ data_version = dvnode->status.data_version + 1; + + while (afs_select_fileserver(&fc)) { + fc.cb_break = afs_calc_vnode_cb_break(dvnode); +@@ -1316,10 +1317,14 @@ static int afs_mkdir(struct inode *dir, + goto error_key; + } + +- if (ret == 0 && +- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) +- afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, +- afs_edit_dir_for_create); ++ if (ret == 0) { ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) ++ afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, ++ afs_edit_dir_for_create); ++ up_write(&dvnode->validate_lock); ++ } + + key_put(key); + kfree(scb); +@@ -1360,6 +1365,7 @@ static int afs_rmdir(struct inode *dir, + struct afs_fs_cursor fc; + struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; + struct key *key; ++ afs_dataversion_t data_version; + int ret; + + _enter("{%llx:%llu},{%pd}", +@@ -1391,7 +1397,7 @@ static int afs_rmdir(struct inode *dir, + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t data_version = dvnode->status.data_version + 1; ++ data_version = dvnode->status.data_version + 1; + + while (afs_select_fileserver(&fc)) { + fc.cb_break = afs_calc_vnode_cb_break(dvnode); +@@ -1404,9 +1410,12 @@ static int afs_rmdir(struct inode *dir, + ret = afs_end_vnode_operation(&fc); + if (ret == 0) { + afs_dir_remove_subdir(dentry); +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) + afs_edit_dir_remove(dvnode, &dentry->d_name, + afs_edit_dir_for_rmdir); ++ up_write(&dvnode->validate_lock); + } + } + +@@ -1544,10 +1553,15 @@ static int afs_unlink(struct inode *dir, + ret = afs_end_vnode_operation(&fc); + if (ret == 0 && !(scb[1].have_status || scb[1].have_error)) + ret = afs_dir_remove_link(dvnode, dentry, key); +- if (ret == 0 && +- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) +- afs_edit_dir_remove(dvnode, &dentry->d_name, +- afs_edit_dir_for_unlink); ++ ++ if (ret == 0) { ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) ++ afs_edit_dir_remove(dvnode, &dentry->d_name, ++ afs_edit_dir_for_unlink); ++ up_write(&dvnode->validate_lock); ++ } + } + + if (need_rehash && ret < 0 && ret != -ENOENT) +@@ -1573,6 +1587,7 @@ static int afs_create(struct inode *dir, + struct afs_status_cb *scb; + struct afs_vnode *dvnode = AFS_FS_I(dir); + struct key *key; ++ afs_dataversion_t data_version; + int ret; + + mode |= S_IFREG; +@@ -1597,7 +1612,7 @@ static int afs_create(struct inode *dir, + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t data_version = dvnode->status.data_version + 1; ++ data_version = dvnode->status.data_version + 1; + + while (afs_select_fileserver(&fc)) { + fc.cb_break = afs_calc_vnode_cb_break(dvnode); +@@ -1618,9 +1633,12 @@ static int afs_create(struct inode *dir, + goto error_key; + } + +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) + afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, + afs_edit_dir_for_create); ++ up_write(&dvnode->validate_lock); + + kfree(scb); + key_put(key); +@@ -1648,6 +1666,7 @@ static int afs_link(struct dentry *from, + struct afs_vnode *dvnode = AFS_FS_I(dir); + struct afs_vnode *vnode = AFS_FS_I(d_inode(from)); + struct key *key; ++ afs_dataversion_t data_version; + int ret; + + _enter("{%llx:%llu},{%llx:%llu},{%pd}", +@@ -1672,7 +1691,7 @@ static int afs_link(struct dentry *from, + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t data_version = dvnode->status.data_version + 1; ++ data_version = dvnode->status.data_version + 1; + + if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) { + afs_end_vnode_operation(&fc); +@@ -1702,9 +1721,12 @@ static int afs_link(struct dentry *from, + goto error_key; + } + +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) + afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid, + afs_edit_dir_for_link); ++ up_write(&dvnode->validate_lock); + + key_put(key); + kfree(scb); +@@ -1732,6 +1754,7 @@ static int afs_symlink(struct inode *dir + struct afs_status_cb *scb; + struct afs_vnode *dvnode = AFS_FS_I(dir); + struct key *key; ++ afs_dataversion_t data_version; + int ret; + + _enter("{%llx:%llu},{%pd},%s", +@@ -1759,7 +1782,7 @@ static int afs_symlink(struct inode *dir + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t data_version = dvnode->status.data_version + 1; ++ data_version = dvnode->status.data_version + 1; + + while (afs_select_fileserver(&fc)) { + fc.cb_break = afs_calc_vnode_cb_break(dvnode); +@@ -1780,9 +1803,12 @@ static int afs_symlink(struct inode *dir + goto error_key; + } + +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == data_version) + afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, + afs_edit_dir_for_symlink); ++ up_write(&dvnode->validate_lock); + + key_put(key); + kfree(scb); +@@ -1812,6 +1838,8 @@ static int afs_rename(struct inode *old_ + struct dentry *tmp = NULL, *rehash = NULL; + struct inode *new_inode; + struct key *key; ++ afs_dataversion_t orig_data_version; ++ afs_dataversion_t new_data_version; + bool new_negative = d_is_negative(new_dentry); + int ret; + +@@ -1890,9 +1918,6 @@ static int afs_rename(struct inode *old_ + + ret = -ERESTARTSYS; + if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) { +- afs_dataversion_t orig_data_version; +- afs_dataversion_t new_data_version; +- + orig_data_version = orig_dvnode->status.data_version + 1; + + if (orig_dvnode != new_dvnode) { +@@ -1928,18 +1953,25 @@ static int afs_rename(struct inode *old_ + if (ret == 0) { + if (rehash) + d_rehash(rehash); +- if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags)) +- afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name, +- afs_edit_dir_for_rename_0); +- +- if (!new_negative && +- test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags)) +- afs_edit_dir_remove(new_dvnode, &new_dentry->d_name, +- afs_edit_dir_for_rename_1); ++ down_write(&orig_dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) && ++ orig_dvnode->status.data_version == orig_data_version) ++ afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name, ++ afs_edit_dir_for_rename_0); ++ if (orig_dvnode != new_dvnode) { ++ up_write(&orig_dvnode->validate_lock); ++ ++ down_write(&new_dvnode->validate_lock); ++ } ++ if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) && ++ orig_dvnode->status.data_version == new_data_version) { ++ if (!new_negative) ++ afs_edit_dir_remove(new_dvnode, &new_dentry->d_name, ++ afs_edit_dir_for_rename_1); + +- if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags)) + afs_edit_dir_add(new_dvnode, &new_dentry->d_name, + &vnode->fid, afs_edit_dir_for_rename_2); ++ } + + new_inode = d_inode(new_dentry); + if (new_inode) { +@@ -1958,6 +1990,7 @@ static int afs_rename(struct inode *old_ + afs_update_dentry_version(&fc, old_dentry, &scb[1]); + afs_update_dentry_version(&fc, new_dentry, &scb[1]); + d_move(old_dentry, new_dentry); ++ up_write(&new_dvnode->validate_lock); + goto error_tmp; + } + +--- a/fs/afs/dir_silly.c ++++ b/fs/afs/dir_silly.c +@@ -21,6 +21,7 @@ static int afs_do_silly_rename(struct af + { + struct afs_fs_cursor fc; + struct afs_status_cb *scb; ++ afs_dataversion_t dir_data_version; + int ret = -ERESTARTSYS; + + _enter("%pd,%pd", old, new); +@@ -31,7 +32,7 @@ static int afs_do_silly_rename(struct af + + trace_afs_silly_rename(vnode, false); + if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { +- afs_dataversion_t dir_data_version = dvnode->status.data_version + 1; ++ dir_data_version = dvnode->status.data_version + 1; + + while (afs_select_fileserver(&fc)) { + fc.cb_break = afs_calc_vnode_cb_break(dvnode); +@@ -54,12 +55,15 @@ static int afs_do_silly_rename(struct af + dvnode->silly_key = key_get(key); + } + +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == dir_data_version) { + afs_edit_dir_remove(dvnode, &old->d_name, + afs_edit_dir_for_silly_0); +- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) + afs_edit_dir_add(dvnode, &new->d_name, + &vnode->fid, afs_edit_dir_for_silly_1); ++ } ++ up_write(&dvnode->validate_lock); + } + + kfree(scb); +@@ -181,10 +185,14 @@ static int afs_do_silly_unlink(struct af + clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); + } + } +- if (ret == 0 && +- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) +- afs_edit_dir_remove(dvnode, &dentry->d_name, +- afs_edit_dir_for_unlink); ++ if (ret == 0) { ++ down_write(&dvnode->validate_lock); ++ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) && ++ dvnode->status.data_version == dir_data_version) ++ afs_edit_dir_remove(dvnode, &dentry->d_name, ++ afs_edit_dir_for_unlink); ++ up_write(&dvnode->validate_lock); ++ } + } + + kfree(scb); diff --git a/queue-5.6/afs-fix-rename-operation-status-delivery.patch b/queue-5.6/afs-fix-rename-operation-status-delivery.patch new file mode 100644 index 00000000000..48026f5690f --- /dev/null +++ b/queue-5.6/afs-fix-rename-operation-status-delivery.patch @@ -0,0 +1,119 @@ +From b98f0ec91c42d87a70da42726b852ac8d78a3257 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 8 Apr 2020 20:56:20 +0100 +Subject: afs: Fix rename operation status delivery + +From: David Howells + +commit b98f0ec91c42d87a70da42726b852ac8d78a3257 upstream. + +The afs_deliver_fs_rename() and yfs_deliver_fs_rename() functions both only +decode the second file status returned unless the parent directories are +different - unfortunately, this means that the xdr pointer isn't advanced +and the volsync record will be read incorrectly in such an instance. + +Fix this by always decoding the second status into the second +status/callback block which wasn't being used if the dirs were the same. + +The afs_update_dentry_version() calls that update the directory data +version numbers on the dentries can then unconditionally use the second +status record as this will always reflect the state of the destination dir +(the two records will be identical if the destination dir is the same as +the source dir) + +Fixes: 260a980317da ("[AFS]: Add "directory write" support.") +Fixes: 30062bd13e36 ("afs: Implement YFS support in the fs client") +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + fs/afs/dir.c | 13 +++---------- + fs/afs/fsclient.c | 12 ++++++------ + fs/afs/yfsclient.c | 8 +++----- + 3 files changed, 12 insertions(+), 21 deletions(-) + +--- a/fs/afs/dir.c ++++ b/fs/afs/dir.c +@@ -1892,7 +1892,6 @@ static int afs_rename(struct inode *old_ + if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) { + afs_dataversion_t orig_data_version; + afs_dataversion_t new_data_version; +- struct afs_status_cb *new_scb = &scb[1]; + + orig_data_version = orig_dvnode->status.data_version + 1; + +@@ -1904,7 +1903,6 @@ static int afs_rename(struct inode *old_ + new_data_version = new_dvnode->status.data_version + 1; + } else { + new_data_version = orig_data_version; +- new_scb = &scb[0]; + } + + while (afs_select_fileserver(&fc)) { +@@ -1912,7 +1910,7 @@ static int afs_rename(struct inode *old_ + fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode); + afs_fs_rename(&fc, old_dentry->d_name.name, + new_dvnode, new_dentry->d_name.name, +- &scb[0], new_scb); ++ &scb[0], &scb[1]); + } + + afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break, +@@ -1957,13 +1955,8 @@ static int afs_rename(struct inode *old_ + * Note that if we ever implement RENAME_EXCHANGE, we'll have + * to update both dentries with opposing dir versions. + */ +- if (new_dvnode != orig_dvnode) { +- afs_update_dentry_version(&fc, old_dentry, &scb[1]); +- afs_update_dentry_version(&fc, new_dentry, &scb[1]); +- } else { +- afs_update_dentry_version(&fc, old_dentry, &scb[0]); +- afs_update_dentry_version(&fc, new_dentry, &scb[0]); +- } ++ afs_update_dentry_version(&fc, old_dentry, &scb[1]); ++ afs_update_dentry_version(&fc, new_dentry, &scb[1]); + d_move(old_dentry, new_dentry); + goto error_tmp; + } +--- a/fs/afs/fsclient.c ++++ b/fs/afs/fsclient.c +@@ -986,16 +986,16 @@ static int afs_deliver_fs_rename(struct + if (ret < 0) + return ret; + +- /* unmarshall the reply once we've received all of it */ ++ /* If the two dirs are the same, we have two copies of the same status ++ * report, so we just decode it twice. ++ */ + bp = call->buffer; + ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); + if (ret < 0) + return ret; +- if (call->out_dir_scb != call->out_scb) { +- ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); +- if (ret < 0) +- return ret; +- } ++ ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); ++ if (ret < 0) ++ return ret; + xdr_decode_AFSVolSync(&bp, call->out_volsync); + + _leave(" = 0 [done]"); +--- a/fs/afs/yfsclient.c ++++ b/fs/afs/yfsclient.c +@@ -1157,11 +1157,9 @@ static int yfs_deliver_fs_rename(struct + ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); + if (ret < 0) + return ret; +- if (call->out_dir_scb != call->out_scb) { +- ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); +- if (ret < 0) +- return ret; +- } ++ ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); ++ if (ret < 0) ++ return ret; + + xdr_decode_YFSVolSync(&bp, call->out_volsync); + _leave(" = 0 [done]"); diff --git a/queue-5.6/alsa-hda-don-t-release-card-at-firmware-loading-error.patch b/queue-5.6/alsa-hda-don-t-release-card-at-firmware-loading-error.patch new file mode 100644 index 00000000000..7f5d65957a8 --- /dev/null +++ b/queue-5.6/alsa-hda-don-t-release-card-at-firmware-loading-error.patch @@ -0,0 +1,59 @@ +From 25faa4bd37c10f19e4b848b9032a17a3d44c6f09 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 13 Apr 2020 10:20:29 +0200 +Subject: ALSA: hda: Don't release card at firmware loading error + +From: Takashi Iwai + +commit 25faa4bd37c10f19e4b848b9032a17a3d44c6f09 upstream. + +At the error path of the firmware loading error, the driver tries to +release the card object and set NULL to drvdata. This may be referred +badly at the possible PM action, as the driver itself is still bound +and the PM callbacks read the card object. + +Instead, we continue the probing as if it were no option set. This is +often a better choice than the forced abort, too. + +Fixes: 5cb543dba986 ("ALSA: hda - Deferred probing with request_firmware_nowait()") +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=207043 +Link: https://lore.kernel.org/r/20200413082034.25166-2-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_intel.c | 19 +++++-------------- + 1 file changed, 5 insertions(+), 14 deletions(-) + +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -2031,24 +2031,15 @@ static void azx_firmware_cb(const struct + { + struct snd_card *card = context; + struct azx *chip = card->private_data; +- struct pci_dev *pci = chip->pci; + +- if (!fw) { +- dev_err(card->dev, "Cannot load firmware, aborting\n"); +- goto error; +- } +- +- chip->fw = fw; ++ if (fw) ++ chip->fw = fw; ++ else ++ dev_err(card->dev, "Cannot load firmware, continue without patching\n"); + if (!chip->disabled) { + /* continue probing */ +- if (azx_probe_continue(chip)) +- goto error; ++ azx_probe_continue(chip); + } +- return; /* OK */ +- +- error: +- snd_card_free(card); +- pci_set_drvdata(pci, NULL); + } + #endif + diff --git a/queue-5.6/arm-dts-imx6-use-gpc-for-fec-interrupt-controller-to-fix-wake-on-lan.patch b/queue-5.6/arm-dts-imx6-use-gpc-for-fec-interrupt-controller-to-fix-wake-on-lan.patch new file mode 100644 index 00000000000..5e669edb0e8 --- /dev/null +++ b/queue-5.6/arm-dts-imx6-use-gpc-for-fec-interrupt-controller-to-fix-wake-on-lan.patch @@ -0,0 +1,56 @@ +From 4141f1a40fc0789f6fd4330e171e1edf155426aa Mon Sep 17 00:00:00 2001 +From: Martin Fuzzey +Date: Thu, 2 Apr 2020 15:51:28 +0200 +Subject: ARM: dts: imx6: Use gpc for FEC interrupt controller to fix wake on LAN. + +From: Martin Fuzzey + +commit 4141f1a40fc0789f6fd4330e171e1edf155426aa upstream. + +In order to wake from suspend by ethernet magic packets the GPC +must be used as intc does not have wakeup functionality. + +But the FEC DT node currently uses interrupt-extended, +specificying intc, thus breaking WoL. + +This problem is probably fallout from the stacked domain conversion +as intc used to chain to GPC. + +So replace "interrupts-extended" by "interrupts" to use the default +parent which is GPC. + +Fixes: b923ff6af0d5 ("ARM: imx6: convert GPC to stacked domains") + +Signed-off-by: Martin Fuzzey +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/boot/dts/imx6qdl.dtsi | 5 ++--- + arch/arm/boot/dts/imx6qp.dtsi | 1 - + 2 files changed, 2 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/imx6qdl.dtsi ++++ b/arch/arm/boot/dts/imx6qdl.dtsi +@@ -1039,9 +1039,8 @@ + compatible = "fsl,imx6q-fec"; + reg = <0x02188000 0x4000>; + interrupt-names = "int0", "pps"; +- interrupts-extended = +- <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>, +- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>, ++ <0 119 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET_REF>; +--- a/arch/arm/boot/dts/imx6qp.dtsi ++++ b/arch/arm/boot/dts/imx6qp.dtsi +@@ -77,7 +77,6 @@ + }; + + &fec { +- /delete-property/interrupts-extended; + interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>, + <0 119 IRQ_TYPE_LEVEL_HIGH>; + }; diff --git a/queue-5.6/irqchip-mbigen-free-msi_desc-on-device-teardown.patch b/queue-5.6/irqchip-mbigen-free-msi_desc-on-device-teardown.patch new file mode 100644 index 00000000000..c32019a06b8 --- /dev/null +++ b/queue-5.6/irqchip-mbigen-free-msi_desc-on-device-teardown.patch @@ -0,0 +1,43 @@ +From edfc23f6f9fdbd7825d50ac1f380243cde19b679 Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Wed, 8 Apr 2020 19:43:52 +0800 +Subject: irqchip/mbigen: Free msi_desc on device teardown + +From: Zenghui Yu + +commit edfc23f6f9fdbd7825d50ac1f380243cde19b679 upstream. + +Using irq_domain_free_irqs_common() on the irqdomain free path will +leave the MSI descriptor unfreed when platform devices get removed. +Properly free it by MSI domain free function. + +Fixes: 9650c60ebfec0 ("irqchip/mbigen: Create irq domain for each mbigen device") +Signed-off-by: Zenghui Yu +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20200408114352.1604-1-yuzenghui@huawei.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/irqchip/irq-mbigen.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-mbigen.c ++++ b/drivers/irqchip/irq-mbigen.c +@@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struc + return 0; + } + ++static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq, ++ unsigned int nr_irqs) ++{ ++ platform_msi_domain_free(domain, virq, nr_irqs); ++} ++ + static const struct irq_domain_ops mbigen_domain_ops = { + .translate = mbigen_domain_translate, + .alloc = mbigen_irq_domain_alloc, +- .free = irq_domain_free_irqs_common, ++ .free = mbigen_irq_domain_free, + }; + + static int mbigen_of_create_domain(struct platform_device *pdev, diff --git a/queue-5.6/kbuild-btf-fix-dependencies-for-debug_info_btf.patch b/queue-5.6/kbuild-btf-fix-dependencies-for-debug_info_btf.patch new file mode 100644 index 00000000000..a820785af29 --- /dev/null +++ b/queue-5.6/kbuild-btf-fix-dependencies-for-debug_info_btf.patch @@ -0,0 +1,42 @@ +From 7d32e69310d67e6b04af04f26193f79dfc2f05c7 Mon Sep 17 00:00:00 2001 +From: Slava Bacherikov +Date: Thu, 2 Apr 2020 23:41:39 +0300 +Subject: kbuild, btf: Fix dependencies for DEBUG_INFO_BTF + +From: Slava Bacherikov + +commit 7d32e69310d67e6b04af04f26193f79dfc2f05c7 upstream. + +Currently turning on DEBUG_INFO_SPLIT when DEBUG_INFO_BTF is also +enabled will produce invalid btf file, since gen_btf function in +link-vmlinux.sh script doesn't handle *.dwo files. + +Enabling DEBUG_INFO_REDUCED will also produce invalid btf file, +and using GCC_PLUGIN_RANDSTRUCT with BTF makes no sense. + +Fixes: e83b9f55448a ("kbuild: add ability to generate BTF type info for vmlinux") +Reported-by: Jann Horn +Reported-by: Liu Yiding +Signed-off-by: Slava Bacherikov +Signed-off-by: Daniel Borkmann +Reviewed-by: Kees Cook +Acked-by: KP Singh +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20200402204138.408021-1-slava@bacher09.org +Signed-off-by: Greg Kroah-Hartman + +--- + lib/Kconfig.debug | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -241,6 +241,8 @@ config DEBUG_INFO_DWARF4 + config DEBUG_INFO_BTF + bool "Generate BTF typeinfo" + depends on DEBUG_INFO ++ depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED ++ depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST + help + Generate deduplicated BTF type information from DWARF debug info. + Turning this on expects presence of pahole tool, which will convert diff --git a/queue-5.6/netfilter-nf_tables-report-eopnotsupp-on-unsupported-flags-object-type.patch b/queue-5.6/netfilter-nf_tables-report-eopnotsupp-on-unsupported-flags-object-type.patch new file mode 100644 index 00000000000..411180c688c --- /dev/null +++ b/queue-5.6/netfilter-nf_tables-report-eopnotsupp-on-unsupported-flags-object-type.patch @@ -0,0 +1,41 @@ +From d9583cdf2f38d0f526d9a8c8564dd2e35e649bc7 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Tue, 7 Apr 2020 14:10:11 +0200 +Subject: netfilter: nf_tables: report EOPNOTSUPP on unsupported flags/object type + +From: Pablo Neira Ayuso + +commit d9583cdf2f38d0f526d9a8c8564dd2e35e649bc7 upstream. + +EINVAL should be used for malformed netlink messages. New userspace +utility and old kernels might easily result in EINVAL when exercising +new set features, which is misleading. + +Fixes: 8aeff920dcc9 ("netfilter: nf_tables: add stateful object reference to set elements") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/nf_tables_api.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -3950,7 +3950,7 @@ static int nf_tables_newset(struct net * + NFT_SET_INTERVAL | NFT_SET_TIMEOUT | + NFT_SET_MAP | NFT_SET_EVAL | + NFT_SET_OBJECT)) +- return -EINVAL; ++ return -EOPNOTSUPP; + /* Only one of these operations is supported */ + if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) == + (NFT_SET_MAP | NFT_SET_OBJECT)) +@@ -3988,7 +3988,7 @@ static int nf_tables_newset(struct net * + objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE])); + if (objtype == NFT_OBJECT_UNSPEC || + objtype > NFT_OBJECT_MAX) +- return -EINVAL; ++ return -EOPNOTSUPP; + } else if (flags & NFT_SET_OBJECT) + return -EINVAL; + else diff --git a/queue-5.6/of-overlay-kmemleak-in-dup_and_fixup_symbol_prop.patch b/queue-5.6/of-overlay-kmemleak-in-dup_and_fixup_symbol_prop.patch new file mode 100644 index 00000000000..9fb37b16294 --- /dev/null +++ b/queue-5.6/of-overlay-kmemleak-in-dup_and_fixup_symbol_prop.patch @@ -0,0 +1,35 @@ +From 478ff649b1c8eb2409b1a54fb75eb46f7c29f140 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 16 Apr 2020 16:42:49 -0500 +Subject: of: overlay: kmemleak in dup_and_fixup_symbol_prop() + +From: Frank Rowand + +commit 478ff649b1c8eb2409b1a54fb75eb46f7c29f140 upstream. + +kmemleak reports several memory leaks from devicetree unittest. +This is the fix for problem 4 of 5. + +target_path was not freed in the non-error path. + +Fixes: e0a58f3e08d4 ("of: overlay: remove a dependency on device node full_name") +Reported-by: Erhard F. +Signed-off-by: Frank Rowand +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/overlay.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -261,6 +261,8 @@ static struct property *dup_and_fixup_sy + + of_property_set_flag(new_prop, OF_DYNAMIC); + ++ kfree(target_path); ++ + return new_prop; + + err_free_new_prop: diff --git a/queue-5.6/of-unittest-kmemleak-in-of_unittest_overlay_high_level.patch b/queue-5.6/of-unittest-kmemleak-in-of_unittest_overlay_high_level.patch new file mode 100644 index 00000000000..474892443d6 --- /dev/null +++ b/queue-5.6/of-unittest-kmemleak-in-of_unittest_overlay_high_level.patch @@ -0,0 +1,40 @@ +From 145fc138f9aae4f9e1331352e301df28e16aed35 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 16 Apr 2020 16:42:48 -0500 +Subject: of: unittest: kmemleak in of_unittest_overlay_high_level() + +From: Frank Rowand + +commit 145fc138f9aae4f9e1331352e301df28e16aed35 upstream. + +kmemleak reports several memory leaks from devicetree unittest. +This is the fix for problem 3 of 5. + +of_unittest_overlay_high_level() failed to kfree the newly created +property when the property named 'name' is skipped. + +Fixes: 39a751a4cb7e ("of: change overlay apply input data from unflattened to FDT") +Reported-by: Erhard F. +Signed-off-by: Frank Rowand +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/unittest.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -2571,8 +2571,11 @@ static __init void of_unittest_overlay_h + goto err_unlock; + } + if (__of_add_property(of_symbols, new_prop)) { ++ kfree(new_prop->name); ++ kfree(new_prop->value); ++ kfree(new_prop); + /* "name" auto-generated by unflatten */ +- if (!strcmp(new_prop->name, "name")) ++ if (!strcmp(prop->name, "name")) + continue; + unittest(0, "duplicate property '%s' in overlay_base node __symbols__", + prop->name); diff --git a/queue-5.6/of-unittest-kmemleak-in-of_unittest_platform_populate.patch b/queue-5.6/of-unittest-kmemleak-in-of_unittest_platform_populate.patch new file mode 100644 index 00000000000..1bf1fbde259 --- /dev/null +++ b/queue-5.6/of-unittest-kmemleak-in-of_unittest_platform_populate.patch @@ -0,0 +1,44 @@ +From 216830d2413cc61be3f76bc02ffd905e47d2439e Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 16 Apr 2020 16:42:47 -0500 +Subject: of: unittest: kmemleak in of_unittest_platform_populate() + +From: Frank Rowand + +commit 216830d2413cc61be3f76bc02ffd905e47d2439e upstream. + +kmemleak reports several memory leaks from devicetree unittest. +This is the fix for problem 2 of 5. + +of_unittest_platform_populate() left an elevated reference count for +grandchild nodes (which are platform devices). Fix the platform +device reference counts so that the memory will be freed. + +Fixes: fb2caa50fbac ("of/selftest: add testcase for nodes with same name and address") +Reported-by: Erhard F. +Signed-off-by: Frank Rowand +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/unittest.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -1155,10 +1155,13 @@ static void __init of_unittest_platform_ + + of_platform_populate(np, match, NULL, &test_bus->dev); + for_each_child_of_node(np, child) { +- for_each_child_of_node(child, grandchild) +- unittest(of_find_device_by_node(grandchild), ++ for_each_child_of_node(child, grandchild) { ++ pdev = of_find_device_by_node(grandchild); ++ unittest(pdev, + "Could not create device for node '%pOFn'\n", + grandchild); ++ of_dev_put(pdev); ++ } + } + + of_platform_depopulate(&test_bus->dev); diff --git a/queue-5.6/of-unittest-kmemleak-on-changeset-destroy.patch b/queue-5.6/of-unittest-kmemleak-on-changeset-destroy.patch new file mode 100644 index 00000000000..0a533110a18 --- /dev/null +++ b/queue-5.6/of-unittest-kmemleak-on-changeset-destroy.patch @@ -0,0 +1,40 @@ +From b3fb36ed694b05738d45218ea72cf7feb10ce2b1 Mon Sep 17 00:00:00 2001 +From: Frank Rowand +Date: Thu, 16 Apr 2020 16:42:46 -0500 +Subject: of: unittest: kmemleak on changeset destroy + +From: Frank Rowand + +commit b3fb36ed694b05738d45218ea72cf7feb10ce2b1 upstream. + +kmemleak reports several memory leaks from devicetree unittest. +This is the fix for problem 1 of 5. + +of_unittest_changeset() reaches deeply into the dynamic devicetree +functions. Several nodes were left with an elevated reference +count and thus were not properly cleaned up. Fix the reference +counts so that the memory will be freed. + +Fixes: 201c910bd689 ("of: Transactional DT support.") +Reported-by: Erhard F. +Signed-off-by: Frank Rowand +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/unittest.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -777,6 +777,10 @@ static void __init of_unittest_changeset + unittest(!of_changeset_revert(&chgset), "revert failed\n"); + + of_changeset_destroy(&chgset); ++ ++ of_node_put(n1); ++ of_node_put(n2); ++ of_node_put(n21); + #endif + } + diff --git a/queue-5.6/rbd-avoid-a-deadlock-on-header_rwsem-when-flushing-notifies.patch b/queue-5.6/rbd-avoid-a-deadlock-on-header_rwsem-when-flushing-notifies.patch new file mode 100644 index 00000000000..abe73dcd991 --- /dev/null +++ b/queue-5.6/rbd-avoid-a-deadlock-on-header_rwsem-when-flushing-notifies.patch @@ -0,0 +1,84 @@ +From 0e4e1de5b63fa423b13593337a27fd2d2b0bcf77 Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Fri, 13 Mar 2020 11:20:51 +0100 +Subject: rbd: avoid a deadlock on header_rwsem when flushing notifies + +From: Ilya Dryomov + +commit 0e4e1de5b63fa423b13593337a27fd2d2b0bcf77 upstream. + +rbd_unregister_watch() flushes notifies and therefore cannot be called +under header_rwsem because a header update notify takes header_rwsem to +synchronize with "rbd map". If mapping an image fails after the watch +is established and a header update notify sneaks in, we deadlock when +erroring out from rbd_dev_image_probe(). + +Move watch registration and unregistration out of the critical section. +The only reason they were put there was to make header_rwsem management +slightly more obvious. + +Fixes: 811c66887746 ("rbd: fix rbd map vs notify races") +Signed-off-by: Ilya Dryomov +Reviewed-by: Jason Dillaman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/rbd.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -4554,6 +4554,10 @@ static void cancel_tasks_sync(struct rbd + cancel_work_sync(&rbd_dev->unlock_work); + } + ++/* ++ * header_rwsem must not be held to avoid a deadlock with ++ * rbd_dev_refresh() when flushing notifies. ++ */ + static void rbd_unregister_watch(struct rbd_device *rbd_dev) + { + cancel_tasks_sync(rbd_dev); +@@ -6964,6 +6968,9 @@ static void rbd_dev_image_release(struct + * device. If this image is the one being mapped (i.e., not a + * parent), initiate a watch on its header object before using that + * object to get detailed information about the rbd image. ++ * ++ * On success, returns with header_rwsem held for write if called ++ * with @depth == 0. + */ + static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) + { +@@ -6993,6 +7000,9 @@ static int rbd_dev_image_probe(struct rb + } + } + ++ if (!depth) ++ down_write(&rbd_dev->header_rwsem); ++ + ret = rbd_dev_header_info(rbd_dev); + if (ret) { + if (ret == -ENOENT && !need_watch) +@@ -7044,6 +7054,8 @@ static int rbd_dev_image_probe(struct rb + err_out_probe: + rbd_dev_unprobe(rbd_dev); + err_out_watch: ++ if (!depth) ++ up_write(&rbd_dev->header_rwsem); + if (need_watch) + rbd_unregister_watch(rbd_dev); + err_out_format: +@@ -7107,12 +7119,9 @@ static ssize_t do_rbd_add(struct bus_typ + goto err_out_rbd_dev; + } + +- down_write(&rbd_dev->header_rwsem); + rc = rbd_dev_image_probe(rbd_dev, 0); +- if (rc < 0) { +- up_write(&rbd_dev->header_rwsem); ++ if (rc < 0) + goto err_out_rbd_dev; +- } + + if (rbd_dev->opts->alloc_size > rbd_dev->layout.object_size) { + rbd_warn(rbd_dev, "alloc_size adjusted to %u", diff --git a/queue-5.6/rbd-call-rbd_dev_unprobe-after-unwatching-and-flushing-notifies.patch b/queue-5.6/rbd-call-rbd_dev_unprobe-after-unwatching-and-flushing-notifies.patch new file mode 100644 index 00000000000..0424be3ed33 --- /dev/null +++ b/queue-5.6/rbd-call-rbd_dev_unprobe-after-unwatching-and-flushing-notifies.patch @@ -0,0 +1,77 @@ +From 952c48b0ed18919bff7528501e9a3fff8a24f8cd Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Mon, 16 Mar 2020 15:52:54 +0100 +Subject: rbd: call rbd_dev_unprobe() after unwatching and flushing notifies + +From: Ilya Dryomov + +commit 952c48b0ed18919bff7528501e9a3fff8a24f8cd upstream. + +rbd_dev_unprobe() is supposed to undo most of rbd_dev_image_probe(), +including rbd_dev_header_info(), which means that rbd_dev_header_info() +isn't supposed to be called after rbd_dev_unprobe(). + +However, rbd_dev_image_release() calls rbd_dev_unprobe() before +rbd_unregister_watch(). This is racy because a header update notify +can sneak in: + + "rbd unmap" thread ceph-watch-notify worker + + rbd_dev_image_release() + rbd_dev_unprobe() + free and zero out header + rbd_watch_cb() + rbd_dev_refresh() + rbd_dev_header_info() + read in header + +The same goes for "rbd map" because rbd_dev_image_probe() calls +rbd_dev_unprobe() on errors. In both cases this results in a memory +leak. + +Fixes: fd22aef8b47c ("rbd: move rbd_unregister_watch() call into rbd_dev_image_release()") +Signed-off-by: Ilya Dryomov +Reviewed-by: Jason Dillaman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/rbd.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -6955,9 +6955,10 @@ static void rbd_print_dne(struct rbd_dev + + static void rbd_dev_image_release(struct rbd_device *rbd_dev) + { +- rbd_dev_unprobe(rbd_dev); + if (rbd_dev->opts) + rbd_unregister_watch(rbd_dev); ++ ++ rbd_dev_unprobe(rbd_dev); + rbd_dev->image_format = 0; + kfree(rbd_dev->spec->image_id); + rbd_dev->spec->image_id = NULL; +@@ -7007,7 +7008,7 @@ static int rbd_dev_image_probe(struct rb + if (ret) { + if (ret == -ENOENT && !need_watch) + rbd_print_dne(rbd_dev, false); +- goto err_out_watch; ++ goto err_out_probe; + } + + /* +@@ -7052,12 +7053,11 @@ static int rbd_dev_image_probe(struct rb + return 0; + + err_out_probe: +- rbd_dev_unprobe(rbd_dev); +-err_out_watch: + if (!depth) + up_write(&rbd_dev->header_rwsem); + if (need_watch) + rbd_unregister_watch(rbd_dev); ++ rbd_dev_unprobe(rbd_dev); + err_out_format: + rbd_dev->image_format = 0; + kfree(rbd_dev->spec->image_id); diff --git a/queue-5.6/rbd-don-t-test-rbd_dev-opts-in-rbd_dev_image_release.patch b/queue-5.6/rbd-don-t-test-rbd_dev-opts-in-rbd_dev_image_release.patch new file mode 100644 index 00000000000..423ce30cc21 --- /dev/null +++ b/queue-5.6/rbd-don-t-test-rbd_dev-opts-in-rbd_dev_image_release.patch @@ -0,0 +1,36 @@ +From b8776051529230f76e464d5ffc5d1cf8465576bf Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Mon, 16 Mar 2020 17:16:28 +0100 +Subject: rbd: don't test rbd_dev->opts in rbd_dev_image_release() + +From: Ilya Dryomov + +commit b8776051529230f76e464d5ffc5d1cf8465576bf upstream. + +rbd_dev->opts is used to distinguish between the image that is being +mapped and a parent. However, because we no longer establish watch for +read-only mappings, this test is imprecise and results in unnecessary +rbd_unregister_watch() calls. + +Make it consistent with need_watch in rbd_dev_image_probe(). + +Fixes: b9ef2b8858a0 ("rbd: don't establish watch for read-only mappings") +Signed-off-by: Ilya Dryomov +Reviewed-by: Jason Dillaman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -6955,7 +6955,7 @@ static void rbd_print_dne(struct rbd_dev + + static void rbd_dev_image_release(struct rbd_device *rbd_dev) + { +- if (rbd_dev->opts) ++ if (!rbd_is_ro(rbd_dev)) + rbd_unregister_watch(rbd_dev); + + rbd_dev_unprobe(rbd_dev); diff --git a/queue-5.6/series b/queue-5.6/series index 8eae10edde6..220299fef7d 100644 --- a/queue-5.6/series +++ b/queue-5.6/series @@ -9,3 +9,27 @@ xsk-fix-out-of-boundary-write-in-__xsk_rcv_memcpy.patch libbpf-fix-bpf_get_link_xdp_id-flags-handling.patch arm-bpf-fix-bugs-with-alu64-rsh-arsh-bpf_k-shift-by-0.patch bpf-prevent-re-mmap-ing-bpf-map-as-writable-for-initially-r-o-mapping.patch +arm-dts-imx6-use-gpc-for-fec-interrupt-controller-to-fix-wake-on-lan.patch +kbuild-btf-fix-dependencies-for-debug_info_btf.patch +netfilter-nf_tables-report-eopnotsupp-on-unsupported-flags-object-type.patch +irqchip-mbigen-free-msi_desc-on-device-teardown.patch +rbd-avoid-a-deadlock-on-header_rwsem-when-flushing-notifies.patch +rbd-call-rbd_dev_unprobe-after-unwatching-and-flushing-notifies.patch +rbd-don-t-test-rbd_dev-opts-in-rbd_dev_image_release.patch +alsa-hda-don-t-release-card-at-firmware-loading-error.patch +xsk-add-missing-check-on-user-supplied-headroom-size.patch +of-unittest-kmemleak-on-changeset-destroy.patch +of-unittest-kmemleak-in-of_unittest_platform_populate.patch +of-unittest-kmemleak-in-of_unittest_overlay_high_level.patch +of-overlay-kmemleak-in-dup_and_fixup_symbol_prop.patch +x86-hyper-v-unload-vmbus-channel-in-hv-panic-callback.patch +x86-hyper-v-free-hv_panic_page-when-fail-to-register-kmsg-dump.patch +x86-hyper-v-trigger-crash-enlightenment-only-once-during-system-crash.patch +x86-hyper-v-report-crash-register-data-or-kmsg-before-running-crash-kernel.patch +x86-hyper-v-report-crash-register-data-when-sysctl_record_panic_msg-is-not-set.patch +x86-hyper-v-report-crash-data-in-die-when-panic_on_oops-is-set.patch +afs-fix-missing-xdr-advance-in-xdr_decode_-afs-yfs-fsfetchstatus.patch +afs-fix-decoding-of-inline-abort-codes-from-version-1-status-records.patch +afs-fix-rename-operation-status-delivery.patch +afs-fix-afs_d_validate-to-set-the-right-directory-version.patch +afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch diff --git a/queue-5.6/x86-hyper-v-free-hv_panic_page-when-fail-to-register-kmsg-dump.patch b/queue-5.6/x86-hyper-v-free-hv_panic_page-when-fail-to-register-kmsg-dump.patch new file mode 100644 index 00000000000..4974fbe9da7 --- /dev/null +++ b/queue-5.6/x86-hyper-v-free-hv_panic_page-when-fail-to-register-kmsg-dump.patch @@ -0,0 +1,48 @@ +From 7f11a2cc10a4ae3a70e2c73361f4a9a33503539b Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:27 -0700 +Subject: x86/Hyper-V: Free hv_panic_page when fail to register kmsg dump + +From: Tianyu Lan + +commit 7f11a2cc10a4ae3a70e2c73361f4a9a33503539b upstream. + +If kmsg_dump_register() fails, hv_panic_page will not be used +anywhere. So free and reset it. + +Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") +Reviewed-by: Michael Kelley +Signed-off-by: Tianyu Lan +Link: https://lore.kernel.org/r/20200406155331.2105-3-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/vmbus_drv.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -1385,9 +1385,13 @@ static int vmbus_bus_init(void) + hv_panic_page = (void *)hv_alloc_hyperv_zeroed_page(); + if (hv_panic_page) { + ret = kmsg_dump_register(&hv_kmsg_dumper); +- if (ret) ++ if (ret) { + pr_err("Hyper-V: kmsg dump register " + "error 0x%x\n", ret); ++ hv_free_hyperv_page( ++ (unsigned long)hv_panic_page); ++ hv_panic_page = NULL; ++ } + } else + pr_err("Hyper-V: panic message page memory " + "allocation failed"); +@@ -1416,7 +1420,6 @@ err_alloc: + hv_remove_vmbus_irq(); + + bus_unregister(&hv_bus); +- hv_free_hyperv_page((unsigned long)hv_panic_page); + unregister_sysctl_table(hv_ctl_table_hdr); + hv_ctl_table_hdr = NULL; + return ret; diff --git a/queue-5.6/x86-hyper-v-report-crash-data-in-die-when-panic_on_oops-is-set.patch b/queue-5.6/x86-hyper-v-report-crash-data-in-die-when-panic_on_oops-is-set.patch new file mode 100644 index 00000000000..374988daacb --- /dev/null +++ b/queue-5.6/x86-hyper-v-report-crash-data-in-die-when-panic_on_oops-is-set.patch @@ -0,0 +1,94 @@ +From f3a99e761efa616028b255b4de58e9b5b87c5545 Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:31 -0700 +Subject: x86/Hyper-V: Report crash data in die() when panic_on_oops is set + +From: Tianyu Lan + +commit f3a99e761efa616028b255b4de58e9b5b87c5545 upstream. + +When oops happens with panic_on_oops unset, the oops +thread is killed by die() and system continues to run. +In such case, guest should not report crash register +data to host since system still runs. Check panic_on_oops +and return directly in hyperv_report_panic() when the function +is called in the die() and panic_on_oops is unset. Fix it. + +Fixes: 7ed4325a44ea ("Drivers: hv: vmbus: Make panic reporting to be more useful") +Signed-off-by: Tianyu Lan +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20200406155331.2105-7-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/hyperv/hv_init.c | 6 +++++- + drivers/hv/vmbus_drv.c | 5 +++-- + include/asm-generic/mshyperv.h | 2 +- + 3 files changed, 9 insertions(+), 4 deletions(-) + +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -419,11 +420,14 @@ void hyperv_cleanup(void) + } + EXPORT_SYMBOL_GPL(hyperv_cleanup); + +-void hyperv_report_panic(struct pt_regs *regs, long err) ++void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die) + { + static bool panic_reported; + u64 guest_id; + ++ if (in_die && !panic_on_oops) ++ return; ++ + /* + * We prefer to report panic on 'die' chain as we have proper + * registers to report, but if we miss it (e.g. on BUG()) we need +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include "hyperv_vmbus.h" +@@ -75,7 +76,7 @@ static int hyperv_panic_event(struct not + if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE + && hyperv_report_reg()) { + regs = current_pt_regs(); +- hyperv_report_panic(regs, val); ++ hyperv_report_panic(regs, val, false); + } + return NOTIFY_DONE; + } +@@ -92,7 +93,7 @@ static int hyperv_die_event(struct notif + * the notification here. + */ + if (hyperv_report_reg()) +- hyperv_report_panic(regs, val); ++ hyperv_report_panic(regs, val, true); + return NOTIFY_DONE; + } + +--- a/include/asm-generic/mshyperv.h ++++ b/include/asm-generic/mshyperv.h +@@ -163,7 +163,7 @@ static inline int cpumask_to_vpset(struc + return nr_bank; + } + +-void hyperv_report_panic(struct pt_regs *regs, long err); ++void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die); + void hyperv_report_panic_msg(phys_addr_t pa, size_t size); + bool hv_is_hyperv_initialized(void); + bool hv_is_hibernation_supported(void); diff --git a/queue-5.6/x86-hyper-v-report-crash-register-data-or-kmsg-before-running-crash-kernel.patch b/queue-5.6/x86-hyper-v-report-crash-register-data-or-kmsg-before-running-crash-kernel.patch new file mode 100644 index 00000000000..192c3921b55 --- /dev/null +++ b/queue-5.6/x86-hyper-v-report-crash-register-data-or-kmsg-before-running-crash-kernel.patch @@ -0,0 +1,45 @@ +From a11589563e96bf262767294b89b25a9d44e7303b Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:29 -0700 +Subject: x86/Hyper-V: Report crash register data or kmsg before running crash kernel + +From: Tianyu Lan + +commit a11589563e96bf262767294b89b25a9d44e7303b upstream. + +We want to notify Hyper-V when a Linux guest VM crash occurs, so +there is a record of the crash even when kdump is enabled. But +crash_kexec_post_notifiers defaults to "false", so the kdump kernel +runs before the notifiers and Hyper-V never gets notified. Fix this by +always setting crash_kexec_post_notifiers to be true for Hyper-V VMs. + +Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") +Reviewed-by: Michael Kelley +Signed-off-by: Tianyu Lan +Link: https://lore.kernel.org/r/20200406155331.2105-5-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/cpu/mshyperv.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -263,6 +263,16 @@ static void __init ms_hyperv_init_platfo + cpuid_eax(HYPERV_CPUID_NESTED_FEATURES); + } + ++ /* ++ * Hyper-V expects to get crash register data or kmsg when ++ * crash enlightment is available and system crashes. Set ++ * crash_kexec_post_notifiers to be true to make sure that ++ * calling crash enlightment interface before running kdump ++ * kernel. ++ */ ++ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) ++ crash_kexec_post_notifiers = true; ++ + #ifdef CONFIG_X86_LOCAL_APIC + if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS && + ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { diff --git a/queue-5.6/x86-hyper-v-report-crash-register-data-when-sysctl_record_panic_msg-is-not-set.patch b/queue-5.6/x86-hyper-v-report-crash-register-data-when-sysctl_record_panic_msg-is-not-set.patch new file mode 100644 index 00000000000..768c7b3252d --- /dev/null +++ b/queue-5.6/x86-hyper-v-report-crash-register-data-when-sysctl_record_panic_msg-is-not-set.patch @@ -0,0 +1,77 @@ +From 040026df7088c56ccbad28f7042308f67bde63df Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:30 -0700 +Subject: x86/Hyper-V: Report crash register data when sysctl_record_panic_msg is not set + +From: Tianyu Lan + +commit 040026df7088c56ccbad28f7042308f67bde63df upstream. + +When sysctl_record_panic_msg is not set, the panic will +not be reported to Hyper-V via hyperv_report_panic_msg(). +So the crash should be reported via hyperv_report_panic(). + +Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") +Reviewed-by: Michael Kelley +Signed-off-by: Tianyu Lan +Link: https://lore.kernel.org/r/20200406155331.2105-6-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/vmbus_drv.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -48,6 +48,18 @@ static int hyperv_cpuhp_online; + + static void *hv_panic_page; + ++/* ++ * Boolean to control whether to report panic messages over Hyper-V. ++ * ++ * It can be set via /proc/sys/kernel/hyperv/record_panic_msg ++ */ ++static int sysctl_record_panic_msg = 1; ++ ++static int hyperv_report_reg(void) ++{ ++ return !sysctl_record_panic_msg || !hv_panic_page; ++} ++ + static int hyperv_panic_event(struct notifier_block *nb, unsigned long val, + void *args) + { +@@ -61,7 +73,7 @@ static int hyperv_panic_event(struct not + * the notification here. + */ + if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE +- && !hv_panic_page) { ++ && hyperv_report_reg()) { + regs = current_pt_regs(); + hyperv_report_panic(regs, val); + } +@@ -79,7 +91,7 @@ static int hyperv_die_event(struct notif + * doing hyperv_report_panic_msg() later with kmsg data, don't do + * the notification here. + */ +- if (!hv_panic_page) ++ if (hyperv_report_reg()) + hyperv_report_panic(regs, val); + return NOTIFY_DONE; + } +@@ -1268,13 +1280,6 @@ static void vmbus_isr(void) + } + + /* +- * Boolean to control whether to report panic messages over Hyper-V. +- * +- * It can be set via /proc/sys/kernel/hyperv/record_panic_msg +- */ +-static int sysctl_record_panic_msg = 1; +- +-/* + * Callback from kmsg_dump. Grab as much as possible from the end of the kmsg + * buffer and call into Hyper-V to transfer the data. + */ diff --git a/queue-5.6/x86-hyper-v-trigger-crash-enlightenment-only-once-during-system-crash.patch b/queue-5.6/x86-hyper-v-trigger-crash-enlightenment-only-once-during-system-crash.patch new file mode 100644 index 00000000000..a09df30e7c5 --- /dev/null +++ b/queue-5.6/x86-hyper-v-trigger-crash-enlightenment-only-once-during-system-crash.patch @@ -0,0 +1,62 @@ +From 73f26e526f19afb3a06b76b970a76bcac2cafd05 Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:28 -0700 +Subject: x86/Hyper-V: Trigger crash enlightenment only once during system crash. + +From: Tianyu Lan + +commit 73f26e526f19afb3a06b76b970a76bcac2cafd05 upstream. + +When a guest VM panics, Hyper-V should be notified only once via the +crash synthetic MSRs. Current Linux code might write these crash MSRs +twice during a system panic: +1) hyperv_panic/die_event() calling hyperv_report_panic() +2) hv_kmsg_dump() calling hyperv_report_panic_msg() + +Fix this by not calling hyperv_report_panic() if a kmsg dump has been +successfully registered. The notification will happen later via +hyperv_report_panic_msg(). + +Fixes: 7ed4325a44ea ("Drivers: hv: vmbus: Make panic reporting to be more useful") +Reviewed-by: Michael Kelley +Signed-off-by: Tianyu Lan +Link: https://lore.kernel.org/r/20200406155331.2105-4-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/vmbus_drv.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -55,7 +55,13 @@ static int hyperv_panic_event(struct not + + vmbus_initiate_unload(true); + +- if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { ++ /* ++ * Hyper-V should be notified only once about a panic. If we will be ++ * doing hyperv_report_panic_msg() later with kmsg data, don't do ++ * the notification here. ++ */ ++ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE ++ && !hv_panic_page) { + regs = current_pt_regs(); + hyperv_report_panic(regs, val); + } +@@ -68,7 +74,13 @@ static int hyperv_die_event(struct notif + struct die_args *die = (struct die_args *)args; + struct pt_regs *regs = die->regs; + +- hyperv_report_panic(regs, val); ++ /* ++ * Hyper-V should be notified only once about a panic. If we will be ++ * doing hyperv_report_panic_msg() later with kmsg data, don't do ++ * the notification here. ++ */ ++ if (!hv_panic_page) ++ hyperv_report_panic(regs, val); + return NOTIFY_DONE; + } + diff --git a/queue-5.6/x86-hyper-v-unload-vmbus-channel-in-hv-panic-callback.patch b/queue-5.6/x86-hyper-v-unload-vmbus-channel-in-hv-panic-callback.patch new file mode 100644 index 00000000000..f76cf405bec --- /dev/null +++ b/queue-5.6/x86-hyper-v-unload-vmbus-channel-in-hv-panic-callback.patch @@ -0,0 +1,109 @@ +From 74347a99e73ae00b8385f1209aaea193c670f901 Mon Sep 17 00:00:00 2001 +From: Tianyu Lan +Date: Mon, 6 Apr 2020 08:53:26 -0700 +Subject: x86/Hyper-V: Unload vmbus channel in hv panic callback + +From: Tianyu Lan + +commit 74347a99e73ae00b8385f1209aaea193c670f901 upstream. + +When kdump is not configured, a Hyper-V VM might still respond to +network traffic after a kernel panic when kernel parameter panic=0. +The panic CPU goes into an infinite loop with interrupts enabled, +and the VMbus driver interrupt handler still works because the +VMbus connection is unloaded only in the kdump path. The network +responses make the other end of the connection think the VM is +still functional even though it has panic'ed, which could affect any +failover actions that should be taken. + +Fix this by unloading the VMbus connection during the panic process. +vmbus_initiate_unload() could then be called twice (e.g., by +hyperv_panic_event() and hv_crash_handler(), so reset the connection +state in vmbus_initiate_unload() to ensure the unload is done only +once. + +Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") +Reviewed-by: Michael Kelley +Signed-off-by: Tianyu Lan +Link: https://lore.kernel.org/r/20200406155331.2105-2-Tianyu.Lan@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/channel_mgmt.c | 3 +++ + drivers/hv/vmbus_drv.c | 21 +++++++++++++-------- + 2 files changed, 16 insertions(+), 8 deletions(-) + +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -839,6 +839,9 @@ void vmbus_initiate_unload(bool crash) + { + struct vmbus_channel_message_header hdr; + ++ if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED) ++ return; ++ + /* Pre-Win2012R2 hosts don't support reconnect */ + if (vmbus_proto_version < VERSION_WIN8_1) + return; +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -53,9 +53,12 @@ static int hyperv_panic_event(struct not + { + struct pt_regs *regs; + +- regs = current_pt_regs(); ++ vmbus_initiate_unload(true); + +- hyperv_report_panic(regs, val); ++ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { ++ regs = current_pt_regs(); ++ hyperv_report_panic(regs, val); ++ } + return NOTIFY_DONE; + } + +@@ -1391,10 +1394,16 @@ static int vmbus_bus_init(void) + } + + register_die_notifier(&hyperv_die_block); +- atomic_notifier_chain_register(&panic_notifier_list, +- &hyperv_panic_block); + } + ++ /* ++ * Always register the panic notifier because we need to unload ++ * the VMbus channel connection to prevent any VMbus ++ * activity after the VM panics. ++ */ ++ atomic_notifier_chain_register(&panic_notifier_list, ++ &hyperv_panic_block); ++ + vmbus_request_offers(); + + return 0; +@@ -2204,8 +2213,6 @@ static int vmbus_bus_suspend(struct devi + + vmbus_initiate_unload(false); + +- vmbus_connection.conn_state = DISCONNECTED; +- + /* Reset the event for the next resume. */ + reinit_completion(&vmbus_connection.ready_for_resume_event); + +@@ -2289,7 +2296,6 @@ static void hv_kexec_handler(void) + { + hv_stimer_global_cleanup(); + vmbus_initiate_unload(false); +- vmbus_connection.conn_state = DISCONNECTED; + /* Make sure conn_state is set as hv_synic_cleanup checks for it */ + mb(); + cpuhp_remove_state(hyperv_cpuhp_online); +@@ -2306,7 +2312,6 @@ static void hv_crash_handler(struct pt_r + * doing the cleanup for current CPU only. This should be sufficient + * for kdump. + */ +- vmbus_connection.conn_state = DISCONNECTED; + cpu = smp_processor_id(); + hv_stimer_cleanup(cpu); + hv_synic_disable_regs(cpu); diff --git a/queue-5.6/xsk-add-missing-check-on-user-supplied-headroom-size.patch b/queue-5.6/xsk-add-missing-check-on-user-supplied-headroom-size.patch new file mode 100644 index 00000000000..acfc2e6ba59 --- /dev/null +++ b/queue-5.6/xsk-add-missing-check-on-user-supplied-headroom-size.patch @@ -0,0 +1,49 @@ +From 99e3a236dd43d06c65af0a2ef9cb44306aef6e02 Mon Sep 17 00:00:00 2001 +From: Magnus Karlsson +Date: Tue, 14 Apr 2020 09:35:15 +0200 +Subject: xsk: Add missing check on user supplied headroom size + +From: Magnus Karlsson + +commit 99e3a236dd43d06c65af0a2ef9cb44306aef6e02 upstream. + +Add a check that the headroom cannot be larger than the available +space in the chunk. In the current code, a malicious user can set the +headroom to a value larger than the chunk size minus the fixed XDP +headroom. That way packets with a length larger than the supported +size in the umem could get accepted and result in an out-of-bounds +write. + +Fixes: c0c77d8fb787 ("xsk: add user memory registration support sockopt") +Reported-by: Bui Quang Minh +Signed-off-by: Magnus Karlsson +Signed-off-by: Daniel Borkmann +Link: https://bugzilla.kernel.org/show_bug.cgi?id=207225 +Link: https://lore.kernel.org/bpf/1586849715-23490-1-git-send-email-magnus.karlsson@intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + net/xdp/xdp_umem.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/net/xdp/xdp_umem.c ++++ b/net/xdp/xdp_umem.c +@@ -343,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem + u32 chunk_size = mr->chunk_size, headroom = mr->headroom; + unsigned int chunks, chunks_per_page; + u64 addr = mr->addr, size = mr->len; +- int size_chk, err; ++ int err; + + if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { + /* Strictly speaking we could support this, if: +@@ -382,8 +382,7 @@ static int xdp_umem_reg(struct xdp_umem + return -EINVAL; + } + +- size_chk = chunk_size - headroom - XDP_PACKET_HEADROOM; +- if (size_chk < 0) ++ if (headroom >= chunk_size - XDP_PACKET_HEADROOM) + return -EINVAL; + + umem->address = (unsigned long)addr;