]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 Jun 2021 16:03:43 +0000 (18:03 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 Jun 2021 16:03:43 +0000 (18:03 +0200)
added patches:
btrfs-fix-unmountable-seed-device-after-fstrim.patch
kvm-arm64-fix-debug-register-indexing.patch
kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch

queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch [new file with mode: 0644]
queue-4.19/kvm-arm64-fix-debug-register-indexing.patch [new file with mode: 0644]
queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch b/queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch
new file mode 100644 (file)
index 0000000..4dd620e
--- /dev/null
@@ -0,0 +1,111 @@
+From foo@baz Tue Jun  8 05:36:16 PM CEST 2021
+From: Anand Jain <anand.jain@oracle.com>
+Date: Fri, 30 Apr 2021 19:59:51 +0800
+Subject: btrfs: fix unmountable seed device after fstrim
+
+From: Anand Jain <anand.jain@oracle.com>
+
+commit 5e753a817b2d5991dfe8a801b7b1e8e79a1c5a20 upstream.
+
+The following test case reproduces an issue of wrongly freeing in-use
+blocks on the readonly seed device when fstrim is called on the rw sprout
+device. As shown below.
+
+Create a seed device and add a sprout device to it:
+
+  $ mkfs.btrfs -fq -dsingle -msingle /dev/loop0
+  $ btrfstune -S 1 /dev/loop0
+  $ mount /dev/loop0 /btrfs
+  $ btrfs dev add -f /dev/loop1 /btrfs
+  BTRFS info (device loop0): relocating block group 290455552 flags system
+  BTRFS info (device loop0): relocating block group 1048576 flags system
+  BTRFS info (device loop0): disk added /dev/loop1
+  $ umount /btrfs
+
+Mount the sprout device and run fstrim:
+
+  $ mount /dev/loop1 /btrfs
+  $ fstrim /btrfs
+  $ umount /btrfs
+
+Now try to mount the seed device, and it fails:
+
+  $ mount /dev/loop0 /btrfs
+  mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
+
+Block 5292032 is missing on the readonly seed device:
+
+ $ dmesg -kt | tail
+ <snip>
+ BTRFS error (device loop0): bad tree block start, want 5292032 have 0
+ BTRFS warning (device loop0): couldn't read-tree root
+ BTRFS error (device loop0): open_ctree failed
+
+>From the dump-tree of the seed device (taken before the fstrim). Block
+5292032 belonged to the block group starting at 5242880:
+
+  $ btrfs inspect dump-tree -e /dev/loop0 | grep -A1 BLOCK_GROUP
+  <snip>
+  item 3 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16169 itemsize 24
+       block group used 114688 chunk_objectid 256 flags METADATA
+  <snip>
+
+>From the dump-tree of the sprout device (taken before the fstrim).
+fstrim used block-group 5242880 to find the related free space to free:
+
+  $ btrfs inspect dump-tree -e /dev/loop1 | grep -A1 BLOCK_GROUP
+  <snip>
+  item 1 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16226 itemsize 24
+       block group used 32768 chunk_objectid 256 flags METADATA
+  <snip>
+
+BPF kernel tracing the fstrim command finds the missing block 5292032
+within the range of the discarded blocks as below:
+
+  kprobe:btrfs_discard_extent {
+       printf("freeing start %llu end %llu num_bytes %llu:\n",
+               arg1, arg1+arg2, arg2);
+  }
+
+  freeing start 5259264 end 5406720 num_bytes 147456
+  <snip>
+
+Fix this by avoiding the discard command to the readonly seed device.
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/extent-tree.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -1984,16 +1984,20 @@ int btrfs_discard_extent(struct btrfs_fs
+               for (i = 0; i < bbio->num_stripes; i++, stripe++) {
+                       u64 bytes;
+                       struct request_queue *req_q;
++                      struct btrfs_device *device = stripe->dev;
+-                      if (!stripe->dev->bdev) {
++                      if (!device->bdev) {
+                               ASSERT(btrfs_test_opt(fs_info, DEGRADED));
+                               continue;
+                       }
+-                      req_q = bdev_get_queue(stripe->dev->bdev);
++                      req_q = bdev_get_queue(device->bdev);
+                       if (!blk_queue_discard(req_q))
+                               continue;
+-                      ret = btrfs_issue_discard(stripe->dev->bdev,
++                      if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state))
++                              continue;
++
++                      ret = btrfs_issue_discard(device->bdev,
+                                                 stripe->physical,
+                                                 stripe->length,
+                                                 &bytes);
diff --git a/queue-4.19/kvm-arm64-fix-debug-register-indexing.patch b/queue-4.19/kvm-arm64-fix-debug-register-indexing.patch
new file mode 100644 (file)
index 0000000..6a294bc
--- /dev/null
@@ -0,0 +1,208 @@
+From cb853ded1d25e5b026ce115dbcde69e3d7e2e831 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Fri, 14 May 2021 09:05:41 +0100
+Subject: KVM: arm64: Fix debug register indexing
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit cb853ded1d25e5b026ce115dbcde69e3d7e2e831 upstream.
+
+Commit 03fdfb2690099 ("KVM: arm64: Don't write junk to sysregs on
+reset") flipped the register number to 0 for all the debug registers
+in the sysreg table, hereby indicating that these registers live
+in a separate shadow structure.
+
+However, the author of this patch failed to realise that all the
+accessors are using that particular index instead of the register
+encoding, resulting in all the registers hitting index 0. Not quite
+a valid implementation of the architecture...
+
+Address the issue by fixing all the accessors to use the CRm field
+of the encoding, which contains the debug register index.
+
+Fixes: 03fdfb2690099 ("KVM: arm64: Don't write junk to sysregs on reset")
+Reported-by: Ricardo Koller <ricarkol@google.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/sys_regs.c |   42 +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -426,14 +426,14 @@ static bool trap_bvr(struct kvm_vcpu *vc
+                    struct sys_reg_params *p,
+                    const struct sys_reg_desc *rd)
+ {
+-      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
++      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
+       if (p->is_write)
+               reg_to_dbg(vcpu, p, dbg_reg);
+       else
+               dbg_to_reg(vcpu, p, dbg_reg);
+-      trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
++      trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
+       return true;
+ }
+@@ -441,7 +441,7 @@ static bool trap_bvr(struct kvm_vcpu *vc
+ static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+               const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -451,7 +451,7 @@ static int set_bvr(struct kvm_vcpu *vcpu
+ static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+       const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
+       if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -461,21 +461,21 @@ static int get_bvr(struct kvm_vcpu *vcpu
+ static void reset_bvr(struct kvm_vcpu *vcpu,
+                     const struct sys_reg_desc *rd)
+ {
+-      vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg] = rd->val;
++      vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val;
+ }
+ static bool trap_bcr(struct kvm_vcpu *vcpu,
+                    struct sys_reg_params *p,
+                    const struct sys_reg_desc *rd)
+ {
+-      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
++      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
+       if (p->is_write)
+               reg_to_dbg(vcpu, p, dbg_reg);
+       else
+               dbg_to_reg(vcpu, p, dbg_reg);
+-      trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
++      trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
+       return true;
+ }
+@@ -483,7 +483,7 @@ static bool trap_bcr(struct kvm_vcpu *vc
+ static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+               const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -494,7 +494,7 @@ static int set_bcr(struct kvm_vcpu *vcpu
+ static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+       const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
+       if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -504,22 +504,22 @@ static int get_bcr(struct kvm_vcpu *vcpu
+ static void reset_bcr(struct kvm_vcpu *vcpu,
+                     const struct sys_reg_desc *rd)
+ {
+-      vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg] = rd->val;
++      vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val;
+ }
+ static bool trap_wvr(struct kvm_vcpu *vcpu,
+                    struct sys_reg_params *p,
+                    const struct sys_reg_desc *rd)
+ {
+-      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
++      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
+       if (p->is_write)
+               reg_to_dbg(vcpu, p, dbg_reg);
+       else
+               dbg_to_reg(vcpu, p, dbg_reg);
+-      trace_trap_reg(__func__, rd->reg, p->is_write,
+-              vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]);
++      trace_trap_reg(__func__, rd->CRm, p->is_write,
++              vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]);
+       return true;
+ }
+@@ -527,7 +527,7 @@ static bool trap_wvr(struct kvm_vcpu *vc
+ static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+               const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -537,7 +537,7 @@ static int set_wvr(struct kvm_vcpu *vcpu
+ static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+       const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
+       if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -547,21 +547,21 @@ static int get_wvr(struct kvm_vcpu *vcpu
+ static void reset_wvr(struct kvm_vcpu *vcpu,
+                     const struct sys_reg_desc *rd)
+ {
+-      vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg] = rd->val;
++      vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val;
+ }
+ static bool trap_wcr(struct kvm_vcpu *vcpu,
+                    struct sys_reg_params *p,
+                    const struct sys_reg_desc *rd)
+ {
+-      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
++      u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
+       if (p->is_write)
+               reg_to_dbg(vcpu, p, dbg_reg);
+       else
+               dbg_to_reg(vcpu, p, dbg_reg);
+-      trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
++      trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
+       return true;
+ }
+@@ -569,7 +569,7 @@ static bool trap_wcr(struct kvm_vcpu *vc
+ static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+               const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -579,7 +579,7 @@ static int set_wcr(struct kvm_vcpu *vcpu
+ static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+       const struct kvm_one_reg *reg, void __user *uaddr)
+ {
+-      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
++      __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
+       if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+               return -EFAULT;
+@@ -589,7 +589,7 @@ static int get_wcr(struct kvm_vcpu *vcpu
+ static void reset_wcr(struct kvm_vcpu *vcpu,
+                     const struct sys_reg_desc *rd)
+ {
+-      vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg] = rd->val;
++      vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val;
+ }
+ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
diff --git a/queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch b/queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch
new file mode 100644 (file)
index 0000000..1edafa6
--- /dev/null
@@ -0,0 +1,66 @@
+From foo@baz Tue Jun  8 05:38:40 PM CEST 2021
+From: Sean Christopherson <seanjc@google.com>
+Date: Wed, 21 Apr 2021 19:21:22 -0700
+Subject: KVM: SVM: Truncate GPR value for DR and CR accesses in !64-bit mode
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 0884335a2e653b8a045083aa1d57ce74269ac81d upstream.
+
+Drop bits 63:32 on loads/stores to/from DRs and CRs when the vCPU is not
+in 64-bit mode.  The APM states bits 63:32 are dropped for both DRs and
+CRs:
+
+  In 64-bit mode, the operand size is fixed at 64 bits without the need
+  for a REX prefix. In non-64-bit mode, the operand size is fixed at 32
+  bits and the upper 32 bits of the destination are forced to 0.
+
+Fixes: 7ff76d58a9dc ("KVM: SVM: enhance MOV CR intercept handler")
+Fixes: cae3797a4639 ("KVM: SVM: enhance mov DR intercept handler")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20210422022128.3464144-4-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[sudip: manual backport to old file]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/svm.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -4033,7 +4033,7 @@ static int cr_interception(struct vcpu_s
+       err = 0;
+       if (cr >= 16) { /* mov to cr */
+               cr -= 16;
+-              val = kvm_register_read(&svm->vcpu, reg);
++              val = kvm_register_readl(&svm->vcpu, reg);
+               switch (cr) {
+               case 0:
+                       if (!check_selective_cr0_intercepted(svm, val))
+@@ -4078,7 +4078,7 @@ static int cr_interception(struct vcpu_s
+                       kvm_queue_exception(&svm->vcpu, UD_VECTOR);
+                       return 1;
+               }
+-              kvm_register_write(&svm->vcpu, reg, val);
++              kvm_register_writel(&svm->vcpu, reg, val);
+       }
+       return kvm_complete_insn_gp(&svm->vcpu, err);
+ }
+@@ -4108,13 +4108,13 @@ static int dr_interception(struct vcpu_s
+       if (dr >= 16) { /* mov to DRn */
+               if (!kvm_require_dr(&svm->vcpu, dr - 16))
+                       return 1;
+-              val = kvm_register_read(&svm->vcpu, reg);
++              val = kvm_register_readl(&svm->vcpu, reg);
+               kvm_set_dr(&svm->vcpu, dr - 16, val);
+       } else {
+               if (!kvm_require_dr(&svm->vcpu, dr))
+                       return 1;
+               kvm_get_dr(&svm->vcpu, dr, &val);
+-              kvm_register_write(&svm->vcpu, reg, val);
++              kvm_register_writel(&svm->vcpu, reg, val);
+       }
+       return kvm_skip_emulated_instruction(&svm->vcpu);
index 0596a8ff0b8a15dfc0e288c15bb20247078e3ab5..c14c1e6f30655e1542c7ed48578232e7acb140fe 100644 (file)
@@ -49,3 +49,6 @@ selftests-bpf-avoid-running-unprivileged-tests-with-alignment-requirements.patch
 bnxt_en-remove-the-setting-of-dev_port.patch
 perf-cgroups-don-t-rotate-events-for-cgroups-unnecessarily.patch
 perf-core-fix-corner-case-in-perf_rotate_context.patch
+btrfs-fix-unmountable-seed-device-after-fstrim.patch
+kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch
+kvm-arm64-fix-debug-register-indexing.patch