From: Greg Kroah-Hartman Date: Tue, 18 Apr 2023 10:28:45 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.14.313~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75b59565ee174f59b2f39b902f1045c905624922;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches 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 --- 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 index 00000000000..0be4c27ae04 --- /dev/null +++ b/queue-4.19/arm64-kvm-fix-system-register-enumeration.patch @@ -0,0 +1,52 @@ +From 5d8d4af24460d079ecdb190254b14b528add1228 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 2 Apr 2019 03:28:39 +0100 +Subject: arm64: KVM: Fix system register enumeration + +From: Marc Zyngier + +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 +Signed-off-by: Takahiro Itazuri +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..04496109b74 --- /dev/null +++ b/queue-4.19/kvm-arm64-factor-out-core-register-id-enumeration.patch @@ -0,0 +1,85 @@ +From be25bbb392fad3a721d6d21b78639b60612b5439 Mon Sep 17 00:00:00 2001 +From: Dave Martin +Date: Fri, 15 Mar 2019 15:47:04 +0000 +Subject: KVM: arm64: Factor out core register ID enumeration + +From: Dave Martin + +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 +Reviewed-by: Julien Thierry +Tested-by: zhang.lei +Signed-off-by: Marc Zyngier +Signed-off-by: Takahiro Itazuri +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b79daae9e3e --- /dev/null +++ b/queue-4.19/kvm-arm64-filter-out-invalid-core-register-ids-in-kvm_get_reg_list.patch @@ -0,0 +1,125 @@ +From df205b5c63281e4f32caac22adda18fd68795e80 Mon Sep 17 00:00:00 2001 +From: Dave Martin +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 + +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 +Reviewed-by: Andrew Jones +Tested-by: Andrew Jones +Signed-off-by: Marc Zyngier +Signed-off-by: Takahiro Itazuri +Signed-off-by: Greg Kroah-Hartman +--- + 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++; + } diff --git a/queue-4.19/series b/queue-4.19/series index 7bb31646f18..ebd736de5d8 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -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