mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 13:59:45 -04:00
KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
In all the vgic_its_save_*() functinos, they do not check whether the data length is 8 bytes before calling vgic_write_guest_lock. This patch adds the check. To prevent the kernel from being blown up when the fault occurs, KVM_BUG_ON() is used. And the other BUG_ON()s are replaced together. Cc: stable@vger.kernel.org Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> [Jing: Update with the new entry read/write helpers] Signed-off-by: Jing Zhang <jingzhangos@google.com> Link: https://lore.kernel.org/r/20241107214137.428439-4-jingzhangos@google.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
@@ -2086,7 +2086,6 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
|
|||||||
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
||||||
struct its_ite *ite, gpa_t gpa, int ite_esz)
|
struct its_ite *ite, gpa_t gpa, int ite_esz)
|
||||||
{
|
{
|
||||||
struct kvm *kvm = its->dev->kvm;
|
|
||||||
u32 next_offset;
|
u32 next_offset;
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
@@ -2095,7 +2094,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
|||||||
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
|
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
|
||||||
ite->collection->collection_id;
|
ite->collection->collection_id;
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2239,7 +2239,6 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
|
|||||||
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
||||||
gpa_t ptr, int dte_esz)
|
gpa_t ptr, int dte_esz)
|
||||||
{
|
{
|
||||||
struct kvm *kvm = its->dev->kvm;
|
|
||||||
u64 val, itt_addr_field;
|
u64 val, itt_addr_field;
|
||||||
u32 next_offset;
|
u32 next_offset;
|
||||||
|
|
||||||
@@ -2250,7 +2249,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
|||||||
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
|
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
|
||||||
(dev->num_eventid_bits - 1));
|
(dev->num_eventid_bits - 1));
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2437,7 +2437,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
|
|||||||
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
|
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
|
||||||
collection->collection_id);
|
collection->collection_id);
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, gpa, val, esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2453,8 +2454,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
|
|||||||
u64 val;
|
u64 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUG_ON(esz > sizeof(val));
|
ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
|
||||||
ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
val = le64_to_cpu(val);
|
val = le64_to_cpu(val);
|
||||||
@@ -2492,7 +2492,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|||||||
u64 baser = its->baser_coll_table;
|
u64 baser = its->baser_coll_table;
|
||||||
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
|
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
|
||||||
struct its_collection *collection;
|
struct its_collection *collection;
|
||||||
u64 val;
|
|
||||||
size_t max_size, filled = 0;
|
size_t max_size, filled = 0;
|
||||||
int ret, cte_esz = abi->cte_esz;
|
int ret, cte_esz = abi->cte_esz;
|
||||||
|
|
||||||
@@ -2516,10 +2515,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|||||||
* table is not fully filled, add a last dummy element
|
* table is not fully filled, add a last dummy element
|
||||||
* with valid bit unset
|
* with valid bit unset
|
||||||
*/
|
*/
|
||||||
val = 0;
|
return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
|
||||||
BUG_ON(cte_esz > sizeof(val));
|
|
||||||
ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -146,6 +146,29 @@ static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
||||||
|
u64 *eval, unsigned long esize)
|
||||||
|
{
|
||||||
|
struct kvm *kvm = its->dev->kvm;
|
||||||
|
|
||||||
|
if (KVM_BUG_ON(esize != sizeof(*eval), kvm))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return kvm_read_guest_lock(kvm, eaddr, eval, esize);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
||||||
|
u64 eval, unsigned long esize)
|
||||||
|
{
|
||||||
|
struct kvm *kvm = its->dev->kvm;
|
||||||
|
|
||||||
|
if (KVM_BUG_ON(esize != sizeof(eval), kvm))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return vgic_write_guest_lock(kvm, eaddr, &eval, esize);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct provides an intermediate representation of the fields contained
|
* This struct provides an intermediate representation of the fields contained
|
||||||
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
|
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
|
||||||
|
|||||||
Reference in New Issue
Block a user