Commit 265b97cb authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvmarm-fixes-6.3-4' of...

Merge tag 'kvmarm-fixes-6.3-4' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD

KVM/arm64 fixes for 6.3, part #4

 - Plug a buffer overflow due to the use of the user-provided register
   width for firmware regs. Outright reject accesses where the
   user register width does not match the kernel representation.

 - Protect non-atomic RMW operations on vCPU flags against preemption,
   as an update to the flags by an intervening preemption could be lost.
parents 0bf9601f a25bc848
...@@ -576,9 +576,22 @@ struct kvm_vcpu_arch { ...@@ -576,9 +576,22 @@ struct kvm_vcpu_arch {
({ \ ({ \
__build_check_flag(v, flagset, f, m); \ __build_check_flag(v, flagset, f, m); \
\ \
v->arch.flagset & (m); \ READ_ONCE(v->arch.flagset) & (m); \
}) })
/*
* Note that the set/clear accessors must be preempt-safe in order to
* avoid nesting them with load/put which also manipulate flags...
*/
#ifdef __KVM_NVHE_HYPERVISOR__
/* the nVHE hypervisor is always non-preemptible */
#define __vcpu_flags_preempt_disable()
#define __vcpu_flags_preempt_enable()
#else
#define __vcpu_flags_preempt_disable() preempt_disable()
#define __vcpu_flags_preempt_enable() preempt_enable()
#endif
#define __vcpu_set_flag(v, flagset, f, m) \ #define __vcpu_set_flag(v, flagset, f, m) \
do { \ do { \
typeof(v->arch.flagset) *fset; \ typeof(v->arch.flagset) *fset; \
...@@ -586,9 +599,11 @@ struct kvm_vcpu_arch { ...@@ -586,9 +599,11 @@ struct kvm_vcpu_arch {
__build_check_flag(v, flagset, f, m); \ __build_check_flag(v, flagset, f, m); \
\ \
fset = &v->arch.flagset; \ fset = &v->arch.flagset; \
__vcpu_flags_preempt_disable(); \
if (HWEIGHT(m) > 1) \ if (HWEIGHT(m) > 1) \
*fset &= ~(m); \ *fset &= ~(m); \
*fset |= (f); \ *fset |= (f); \
__vcpu_flags_preempt_enable(); \
} while (0) } while (0)
#define __vcpu_clear_flag(v, flagset, f, m) \ #define __vcpu_clear_flag(v, flagset, f, m) \
...@@ -598,7 +613,9 @@ struct kvm_vcpu_arch { ...@@ -598,7 +613,9 @@ struct kvm_vcpu_arch {
__build_check_flag(v, flagset, f, m); \ __build_check_flag(v, flagset, f, m); \
\ \
fset = &v->arch.flagset; \ fset = &v->arch.flagset; \
__vcpu_flags_preempt_disable(); \
*fset &= ~(m); \ *fset &= ~(m); \
__vcpu_flags_preempt_enable(); \
} while (0) } while (0)
#define vcpu_get_flag(v, ...) __vcpu_get_flag((v), __VA_ARGS__) #define vcpu_get_flag(v, ...) __vcpu_get_flag((v), __VA_ARGS__)
......
...@@ -397,6 +397,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) ...@@ -397,6 +397,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
u64 val; u64 val;
int wa_level; int wa_level;
if (KVM_REG_SIZE(reg->id) != sizeof(val))
return -ENOENT;
if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id))) if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment