mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 06:31:58 +02:00
Two serious ARM fixes:
* 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.
-----BEGIN PGP SIGNATURE-----
iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmRDIaMUHHBib256aW5p
QHJlZGhhdC5jb20ACgkQv/vSX3jHroN7Hwf+Pjf7eQ6YZJdmG/4ySbEHJwml1MoW
KxZn6aODWlxhSj7AtQMpvw0+HoGOoOPE0dV4GOMOqh9P/i0gwFOHtmhFczssyxgY
WwjoW3JEuYZYJ7v1uhUVR0aQvKsTplNsW2tnD6WvneV+YbGgSDc7QRH3FbP7wOow
/tsCerEuNLr7aQP5PdYnnbGQ/YyVKCX/Z0iuENa1tNn9T4/fVlzzMXNzCnrUAFp4
bOEDmgZNDfJRT626Yg8HiLsVB2Dwkbxo1u1d4JP2x+/7Gl38RPSSX7y6e3EQ1rdO
Ttb/2JD5iLhtNShCY0JbPR/rsGd8cTFZn1odpnXd+PRu+OOvStSEFcdx3g==
=XhSQ
-----END PGP SIGNATURE-----
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini:
"Two serious ARM fixes:
- 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"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: arm64: Fix buffer overflow in kvm_arm_set_fw_reg()
KVM: arm64: Make vcpu flag updates non-preemptible
This commit is contained in:
commit
2caeeb9d4a
|
|
@ -576,9 +576,22 @@ struct kvm_vcpu_arch {
|
|||
({ \
|
||||
__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) \
|
||||
do { \
|
||||
typeof(v->arch.flagset) *fset; \
|
||||
|
|
@ -586,9 +599,11 @@ struct kvm_vcpu_arch {
|
|||
__build_check_flag(v, flagset, f, m); \
|
||||
\
|
||||
fset = &v->arch.flagset; \
|
||||
__vcpu_flags_preempt_disable(); \
|
||||
if (HWEIGHT(m) > 1) \
|
||||
*fset &= ~(m); \
|
||||
*fset |= (f); \
|
||||
__vcpu_flags_preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#define __vcpu_clear_flag(v, flagset, f, m) \
|
||||
|
|
@ -598,7 +613,9 @@ struct kvm_vcpu_arch {
|
|||
__build_check_flag(v, flagset, f, m); \
|
||||
\
|
||||
fset = &v->arch.flagset; \
|
||||
__vcpu_flags_preempt_disable(); \
|
||||
*fset &= ~(m); \
|
||||
__vcpu_flags_preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#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)
|
|||
u64 val;
|
||||
int wa_level;
|
||||
|
||||
if (KVM_REG_SIZE(reg->id) != sizeof(val))
|
||||
return -ENOENT;
|
||||
if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
|
||||
return -EFAULT;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user