From ec768f1a64bfba70fe871ff1c58421a64e67e498 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Apr 2020 16:41:49 +0200 Subject: [PATCH] 4.4-stable patches added patches: crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch --- ...x-scatterlist-linearization-for-hash.patch | 113 ++++++++++++++++++ ...ge-page-tracking-when-moving-memslot.patch | 102 ++++++++++++++++ queue-4.4/series | 2 + 3 files changed, 217 insertions(+) create mode 100644 queue-4.4/crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch create mode 100644 queue-4.4/kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch diff --git a/queue-4.4/crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch b/queue-4.4/crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch new file mode 100644 index 00000000000..223fb282cc6 --- /dev/null +++ b/queue-4.4/crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch @@ -0,0 +1,113 @@ +From fa03481b6e2e82355c46644147b614f18c7a8161 Mon Sep 17 00:00:00 2001 +From: Rosioru Dragos +Date: Tue, 25 Feb 2020 17:05:52 +0200 +Subject: crypto: mxs-dcp - fix scatterlist linearization for hash +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rosioru Dragos + +commit fa03481b6e2e82355c46644147b614f18c7a8161 upstream. + +The incorrect traversal of the scatterlist, during the linearization phase +lead to computing the hash value of the wrong input buffer. +New implementation uses scatterwalk_map_and_copy() +to address this issue. + +Cc: +Fixes: 15b59e7c3733 ("crypto: mxs - Add Freescale MXS DCP driver") +Signed-off-by: Rosioru Dragos +Reviewed-by: Horia Geantă +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/mxs-dcp.c | 54 ++++++++++++++++++++++------------------------- + 1 file changed, 26 insertions(+), 28 deletions(-) + +--- a/drivers/crypto/mxs-dcp.c ++++ b/drivers/crypto/mxs-dcp.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #define DCP_MAX_CHANS 4 + #define DCP_BUF_SZ PAGE_SIZE +@@ -626,49 +627,46 @@ static int dcp_sha_req_to_buf(struct cry + struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm); + struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct hash_alg_common *halg = crypto_hash_alg_common(tfm); +- const int nents = sg_nents(req->src); + + uint8_t *in_buf = sdcp->coh->sha_in_buf; + uint8_t *out_buf = sdcp->coh->sha_out_buf; + +- uint8_t *src_buf; +- + struct scatterlist *src; + +- unsigned int i, len, clen; ++ unsigned int i, len, clen, oft = 0; + int ret; + + int fin = rctx->fini; + if (fin) + rctx->fini = 0; + +- for_each_sg(req->src, src, nents, i) { +- src_buf = sg_virt(src); +- len = sg_dma_len(src); ++ src = req->src; ++ len = req->nbytes; + +- do { +- if (actx->fill + len > DCP_BUF_SZ) +- clen = DCP_BUF_SZ - actx->fill; +- else +- clen = len; ++ while (len) { ++ if (actx->fill + len > DCP_BUF_SZ) ++ clen = DCP_BUF_SZ - actx->fill; ++ else ++ clen = len; + +- memcpy(in_buf + actx->fill, src_buf, clen); +- len -= clen; +- src_buf += clen; +- actx->fill += clen; ++ scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen, ++ 0); + +- /* +- * If we filled the buffer and still have some +- * more data, submit the buffer. +- */ +- if (len && actx->fill == DCP_BUF_SZ) { +- ret = mxs_dcp_run_sha(req); +- if (ret) +- return ret; +- actx->fill = 0; +- rctx->init = 0; +- } +- } while (len); ++ len -= clen; ++ oft += clen; ++ actx->fill += clen; ++ ++ /* ++ * If we filled the buffer and still have some ++ * more data, submit the buffer. ++ */ ++ if (len && actx->fill == DCP_BUF_SZ) { ++ ret = mxs_dcp_run_sha(req); ++ if (ret) ++ return ret; ++ actx->fill = 0; ++ rctx->init = 0; ++ } + } + + if (fin) { diff --git a/queue-4.4/kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch b/queue-4.4/kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch new file mode 100644 index 00000000000..a5e841a0c6b --- /dev/null +++ b/queue-4.4/kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch @@ -0,0 +1,102 @@ +From edd4fa37baa6ee8e44dc65523b27bd6fe44c94de Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Tue, 18 Feb 2020 13:07:15 -0800 +Subject: KVM: x86: Allocate new rmap and large page tracking when moving memslot + +From: Sean Christopherson + +commit edd4fa37baa6ee8e44dc65523b27bd6fe44c94de upstream. + +Reallocate a rmap array and recalcuate large page compatibility when +moving an existing memslot to correctly handle the alignment properties +of the new memslot. The number of rmap entries required at each level +is dependent on the alignment of the memslot's base gfn with respect to +that level, e.g. moving a large-page aligned memslot so that it becomes +unaligned will increase the number of rmap entries needed at the now +unaligned level. + +Not updating the rmap array is the most obvious bug, as KVM accesses +garbage data beyond the end of the rmap. KVM interprets the bad data as +pointers, leading to non-canonical #GPs, unexpected #PFs, etc... + + general protection fault: 0000 [#1] SMP + CPU: 0 PID: 1909 Comm: move_memory_reg Not tainted 5.4.0-rc7+ #139 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + RIP: 0010:rmap_get_first+0x37/0x50 [kvm] + Code: <48> 8b 3b 48 85 ff 74 ec e8 6c f4 ff ff 85 c0 74 e3 48 89 d8 5b c3 + RSP: 0018:ffffc9000021bbc8 EFLAGS: 00010246 + RAX: ffff00617461642e RBX: ffff00617461642e RCX: 0000000000000012 + RDX: ffff88827400f568 RSI: ffffc9000021bbe0 RDI: ffff88827400f570 + RBP: 0010000000000000 R08: ffffc9000021bd00 R09: ffffc9000021bda8 + R10: ffffc9000021bc48 R11: 0000000000000000 R12: 0030000000000000 + R13: 0000000000000000 R14: ffff88827427d700 R15: ffffc9000021bce8 + FS: 00007f7eda014700(0000) GS:ffff888277a00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7ed9216ff8 CR3: 0000000274391003 CR4: 0000000000162eb0 + Call Trace: + kvm_mmu_slot_set_dirty+0xa1/0x150 [kvm] + __kvm_set_memory_region.part.64+0x559/0x960 [kvm] + kvm_set_memory_region+0x45/0x60 [kvm] + kvm_vm_ioctl+0x30f/0x920 [kvm] + do_vfs_ioctl+0xa1/0x620 + ksys_ioctl+0x66/0x70 + __x64_sys_ioctl+0x16/0x20 + do_syscall_64+0x4c/0x170 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + RIP: 0033:0x7f7ed9911f47 + Code: <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 21 6f 2c 00 f7 d8 64 89 01 48 + RSP: 002b:00007ffc00937498 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 + RAX: ffffffffffffffda RBX: 0000000001ab0010 RCX: 00007f7ed9911f47 + RDX: 0000000001ab1350 RSI: 000000004020ae46 RDI: 0000000000000004 + RBP: 000000000000000a R08: 0000000000000000 R09: 00007f7ed9214700 + R10: 00007f7ed92149d0 R11: 0000000000000246 R12: 00000000bffff000 + R13: 0000000000000003 R14: 00007f7ed9215000 R15: 0000000000000000 + Modules linked in: kvm_intel kvm irqbypass + ---[ end trace 0c5f570b3358ca89 ]--- + +The disallow_lpage tracking is more subtle. Failure to update results +in KVM creating large pages when it shouldn't, either due to stale data +or again due to indexing beyond the end of the metadata arrays, which +can lead to memory corruption and/or leaking data to guest/userspace. + +Note, the arrays for the old memslot are freed by the unconditional call +to kvm_free_memslot() in __kvm_set_memory_region(). + +Fixes: 05da45583de9b ("KVM: MMU: large page support") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Reviewed-by: Peter Xu +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/x86.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7982,6 +7982,13 @@ int kvm_arch_create_memslot(struct kvm * + { + int i; + ++ /* ++ * Clear out the previous array pointers for the KVM_MR_MOVE case. The ++ * old arrays will be freed by __kvm_set_memory_region() if installing ++ * the new memslot is successful. ++ */ ++ memset(&slot->arch, 0, sizeof(slot->arch)); ++ + for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) { + unsigned long ugfn; + int lpages; +@@ -8050,6 +8057,10 @@ int kvm_arch_prepare_memory_region(struc + const struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) + { ++ if (change == KVM_MR_MOVE) ++ return kvm_arch_create_memslot(kvm, memslot, ++ mem->memory_size >> PAGE_SHIFT); ++ + return 0; + } + diff --git a/queue-4.4/series b/queue-4.4/series index 75a865cc980..11904d36b0b 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -30,3 +30,5 @@ mips-octeon-irq-fix-potential-null-pointer-dereference.patch ath9k-handle-txpower-changes-even-when-tpc-is-disabled.patch signal-extend-exec_id-to-64bits.patch x86-entry-32-add-missing-asm_clac-to-general_protection-entry.patch +kvm-x86-allocate-new-rmap-and-large-page-tracking-when-moving-memslot.patch +crypto-mxs-dcp-fix-scatterlist-linearization-for-hash.patch -- 2.47.3