Skip to content

Commit aea671e

Browse files
jingzhangosSasha Levin
authored andcommitted
KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
commit 7fe28d7 upstream. 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: [email protected] Signed-off-by: Kunkun Jiang <[email protected]> [Jing: Update with the new entry read/write helpers] Signed-off-by: Jing Zhang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 04ad55a commit aea671e

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,6 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
20902090
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
20912091
struct its_ite *ite, gpa_t gpa, int ite_esz)
20922092
{
2093-
struct kvm *kvm = its->dev->kvm;
20942093
u32 next_offset;
20952094
u64 val;
20962095

@@ -2099,7 +2098,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
20992098
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
21002099
ite->collection->collection_id;
21012100
val = cpu_to_le64(val);
2102-
return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
2101+
2102+
return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
21032103
}
21042104

21052105
/**
@@ -2243,7 +2243,6 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
22432243
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
22442244
gpa_t ptr, int dte_esz)
22452245
{
2246-
struct kvm *kvm = its->dev->kvm;
22472246
u64 val, itt_addr_field;
22482247
u32 next_offset;
22492248

@@ -2254,7 +2253,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
22542253
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
22552254
(dev->num_eventid_bits - 1));
22562255
val = cpu_to_le64(val);
2257-
return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
2256+
2257+
return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
22582258
}
22592259

22602260
/**
@@ -2441,7 +2441,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
24412441
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
24422442
collection->collection_id);
24432443
val = cpu_to_le64(val);
2444-
return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
2444+
2445+
return vgic_its_write_entry_lock(its, gpa, val, esz);
24452446
}
24462447

24472448
/*
@@ -2457,8 +2458,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
24572458
u64 val;
24582459
int ret;
24592460

2460-
BUG_ON(esz > sizeof(val));
2461-
ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
2461+
ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
24622462
if (ret)
24632463
return ret;
24642464
val = le64_to_cpu(val);
@@ -2496,7 +2496,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
24962496
u64 baser = its->baser_coll_table;
24972497
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
24982498
struct its_collection *collection;
2499-
u64 val;
25002499
size_t max_size, filled = 0;
25012500
int ret, cte_esz = abi->cte_esz;
25022501

@@ -2520,10 +2519,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
25202519
* table is not fully filled, add a last dummy element
25212520
* with valid bit unset
25222521
*/
2523-
val = 0;
2524-
BUG_ON(cte_esz > sizeof(val));
2525-
ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
2526-
return ret;
2522+
return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
25272523
}
25282524

25292525
/*

arch/arm64/kvm/vgic/vgic.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,29 @@ static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
146146
return ret;
147147
}
148148

149+
static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr,
150+
u64 *eval, unsigned long esize)
151+
{
152+
struct kvm *kvm = its->dev->kvm;
153+
154+
if (KVM_BUG_ON(esize != sizeof(*eval), kvm))
155+
return -EINVAL;
156+
157+
return kvm_read_guest_lock(kvm, eaddr, eval, esize);
158+
159+
}
160+
161+
static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr,
162+
u64 eval, unsigned long esize)
163+
{
164+
struct kvm *kvm = its->dev->kvm;
165+
166+
if (KVM_BUG_ON(esize != sizeof(eval), kvm))
167+
return -EINVAL;
168+
169+
return vgic_write_guest_lock(kvm, eaddr, &eval, esize);
170+
}
171+
149172
/*
150173
* This struct provides an intermediate representation of the fields contained
151174
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC

0 commit comments

Comments
 (0)