]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2023 10:28:45 +0000 (12:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2023 10:28:45 +0000 (12:28 +0200)
added patches:
arm64-kvm-fix-system-register-enumeration.patch
kvm-arm64-factor-out-core-register-id-enumeration.patch
kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch

queue-4.19/arm64-kvm-fix-system-register-enumeration.patch [new file with mode: 0644]
queue-4.19/kvm-arm64-factor-out-core-register-id-enumeration.patch [new file with mode: 0644]
queue-4.19/kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/arm64-kvm-fix-system-register-enumeration.patch b/queue-4.19/arm64-kvm-fix-system-register-enumeration.patch
new file mode 100644 (file)
index 0000000..0be4c27
--- /dev/null
@@ -0,0 +1,52 @@
+From 5d8d4af24460d079ecdb190254b14b528add1228 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 2 Apr 2019 03:28:39 +0100
+Subject: arm64: KVM: Fix system register enumeration
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit 5d8d4af24460d079ecdb190254b14b528add1228 upstream.
+
+The introduction of the SVE registers to userspace started with a
+refactoring of the way we expose any register via the ONE_REG
+interface.
+
+Unfortunately, this change doesn't exactly behave as expected
+if the number of registers is non-zero and consider everything
+to be an error. The visible result is that QEMU barfs very early
+when creating vcpus.
+
+Make sure we only exit early in case there is an actual error, rather
+than a positive number of registers...
+
+Fixes: be25bbb392fa ("KVM: arm64: Factor out core register ID enumeration")
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Takahiro Itazuri <itazur@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/guest.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/kvm/guest.c
++++ b/arch/arm64/kvm/guest.c
+@@ -333,17 +333,17 @@ int kvm_arm_copy_reg_indices(struct kvm_
+       int ret;
+       ret = kvm_arm_copy_core_reg_indices(uindices);
+-      if (ret)
++      if (ret < 0)
+               return ret;
+       uindices += ret;
+       ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+-      if (ret)
++      if (ret < 0)
+               return ret;
+       uindices += kvm_arm_get_fw_num_regs(vcpu);
+       ret = copy_timer_indices(vcpu, uindices);
+-      if (ret)
++      if (ret < 0)
+               return ret;
+       uindices += NUM_TIMER_REGS;
diff --git a/queue-4.19/kvm-arm64-factor-out-core-register-id-enumeration.patch b/queue-4.19/kvm-arm64-factor-out-core-register-id-enumeration.patch
new file mode 100644 (file)
index 0000000..0449610
--- /dev/null
@@ -0,0 +1,85 @@
+From be25bbb392fad3a721d6d21b78639b60612b5439 Mon Sep 17 00:00:00 2001
+From: Dave Martin <Dave.Martin@arm.com>
+Date: Fri, 15 Mar 2019 15:47:04 +0000
+Subject: KVM: arm64: Factor out core register ID enumeration
+
+From: Dave Martin <Dave.Martin@arm.com>
+
+commit be25bbb392fad3a721d6d21b78639b60612b5439 upstream.
+
+In preparation for adding logic to filter out some KVM_REG_ARM_CORE
+registers from the KVM_GET_REG_LIST output, this patch factors out
+the core register enumeration into a separate function and rebuilds
+num_core_regs() on top of it.
+
+This may be a little more expensive (depending on how good a job
+the compiler does of specialising the code), but KVM_GET_REG_LIST
+is not a hot path.
+
+This will make it easier to consolidate ID filtering code in one
+place.
+
+No functional change.
+
+Signed-off-by: Dave Martin <Dave.Martin@arm.com>
+Reviewed-by: Julien Thierry <julien.thierry@arm.com>
+Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Takahiro Itazuri <itazur@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/guest.c |   32 ++++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 8 deletions(-)
+
+--- a/arch/arm64/kvm/guest.c
++++ b/arch/arm64/kvm/guest.c
+@@ -200,9 +200,28 @@ int kvm_arch_vcpu_ioctl_set_regs(struct
+       return -EINVAL;
+ }
++static int kvm_arm_copy_core_reg_indices(u64 __user *uindices)
++{
++      unsigned int i;
++      int n = 0;
++      const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;
++
++      for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
++              if (uindices) {
++                      if (put_user(core_reg | i, uindices))
++                              return -EFAULT;
++                      uindices++;
++              }
++
++              n++;
++      }
++
++      return n;
++}
++
+ static unsigned long num_core_regs(void)
+ {
+-      return sizeof(struct kvm_regs) / sizeof(__u32);
++      return kvm_arm_copy_core_reg_indices(NULL);
+ }
+ /**
+@@ -276,15 +295,12 @@ unsigned long kvm_arm_num_regs(struct kv
+  */
+ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+ {
+-      unsigned int i;
+-      const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;
+       int ret;
+-      for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
+-              if (put_user(core_reg | i, uindices))
+-                      return -EFAULT;
+-              uindices++;
+-      }
++      ret = kvm_arm_copy_core_reg_indices(uindices);
++      if (ret)
++              return ret;
++      uindices += ret;
+       ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+       if (ret)
diff --git a/queue-4.19/kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch b/queue-4.19/kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch
new file mode 100644 (file)
index 0000000..b79daae
--- /dev/null
@@ -0,0 +1,125 @@
+From df205b5c63281e4f32caac22adda18fd68795e80 Mon Sep 17 00:00:00 2001
+From: Dave Martin <Dave.Martin@arm.com>
+Date: Wed, 12 Jun 2019 13:44:49 +0100
+Subject: KVM: arm64: Filter out invalid core register IDs in KVM_GET_REG_LIST
+
+From: Dave Martin <Dave.Martin@arm.com>
+
+commit df205b5c63281e4f32caac22adda18fd68795e80 upstream.
+
+Since commit d26c25a9d19b ("arm64: KVM: Tighten guest core register
+access from userspace"), KVM_{GET,SET}_ONE_REG rejects register IDs
+that do not correspond to a single underlying architectural register.
+
+KVM_GET_REG_LIST was not changed to match however: instead, it
+simply yields a list of 32-bit register IDs that together cover the
+whole kvm_regs struct.  This means that if userspace tries to use
+the resulting list of IDs directly to drive calls to KVM_*_ONE_REG,
+some of those calls will now fail.
+
+This was not the intention.  Instead, iterating KVM_*_ONE_REG over
+the list of IDs returned by KVM_GET_REG_LIST should be guaranteed
+to work.
+
+This patch fixes the problem by splitting validate_core_offset()
+into a backend core_reg_size_from_offset() which does all of the
+work except for checking that the size field in the register ID
+matches, and kvm_arm_copy_reg_indices() and num_core_regs() are
+converted to use this to enumerate the valid offsets.
+
+kvm_arm_copy_reg_indices() now also sets the register ID size field
+appropriately based on the value returned, so the register ID
+supplied to userspace is fully qualified for use with the register
+access ioctls.
+
+Cc: stable@vger.kernel.org
+Fixes: d26c25a9d19b ("arm64: KVM: Tighten guest core register access from userspace")
+Signed-off-by: Dave Martin <Dave.Martin@arm.com>
+Reviewed-by: Andrew Jones <drjones@redhat.com>
+Tested-by: Andrew Jones <drjones@redhat.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Takahiro Itazuri <itazur@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/guest.c |   51 +++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 43 insertions(+), 8 deletions(-)
+
+--- a/arch/arm64/kvm/guest.c
++++ b/arch/arm64/kvm/guest.c
+@@ -57,9 +57,8 @@ static u64 core_reg_offset_from_id(u64 i
+       return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
+ }
+-static int validate_core_offset(const struct kvm_one_reg *reg)
++static int core_reg_size_from_offset(u64 off)
+ {
+-      u64 off = core_reg_offset_from_id(reg->id);
+       int size;
+       switch (off) {
+@@ -89,11 +88,24 @@ static int validate_core_offset(const st
+               return -EINVAL;
+       }
+-      if (KVM_REG_SIZE(reg->id) == size &&
+-          IS_ALIGNED(off, size / sizeof(__u32)))
+-              return 0;
++      if (!IS_ALIGNED(off, size / sizeof(__u32)))
++              return -EINVAL;
+-      return -EINVAL;
++      return size;
++}
++
++static int validate_core_offset(const struct kvm_one_reg *reg)
++{
++      u64 off = core_reg_offset_from_id(reg->id);
++      int size = core_reg_size_from_offset(off);
++
++      if (size < 0)
++              return -EINVAL;
++
++      if (KVM_REG_SIZE(reg->id) != size)
++              return -EINVAL;
++
++      return 0;
+ }
+ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+@@ -204,11 +216,34 @@ static int kvm_arm_copy_core_reg_indices
+ {
+       unsigned int i;
+       int n = 0;
+-      const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;
+       for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
++              u64 reg = KVM_REG_ARM64 | KVM_REG_ARM_CORE | i;
++              int size = core_reg_size_from_offset(i);
++
++              if (size < 0)
++                      continue;
++
++              switch (size) {
++              case sizeof(__u32):
++                      reg |= KVM_REG_SIZE_U32;
++                      break;
++
++              case sizeof(__u64):
++                      reg |= KVM_REG_SIZE_U64;
++                      break;
++
++              case sizeof(__uint128_t):
++                      reg |= KVM_REG_SIZE_U128;
++                      break;
++
++              default:
++                      WARN_ON(1);
++                      continue;
++              }
++
+               if (uindices) {
+-                      if (put_user(core_reg | i, uindices))
++                      if (put_user(reg, uindices))
+                               return -EFAULT;
+                       uindices++;
+               }
index 7bb31646f18f513752918a2facf84ad948334c79..ebd736de5d8df5c9985d88b6278e2c6423c4d59a 100644 (file)
@@ -52,3 +52,6 @@ cgroup-cpuset-wake-up-cpuset_attach_wq-tasks-in-cpuset_cancel_attach.patch
 watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch
 coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch
 kvm-nvmx-add-missing-consistency-checks-for-cr0-and-cr4.patch
+kvm-arm64-factor-out-core-register-id-enumeration.patch
+kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch
+arm64-kvm-fix-system-register-enumeration.patch