Skip to content

Commit 2a4ec24

Browse files
jingzhangosgregkh
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 dd2f986 commit 2a4ec24

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
@@ -2211,7 +2211,6 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
22112211
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
22122212
struct its_ite *ite, gpa_t gpa, int ite_esz)
22132213
{
2214-
struct kvm *kvm = its->dev->kvm;
22152214
u32 next_offset;
22162215
u64 val;
22172216

@@ -2220,7 +2219,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
22202219
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
22212220
ite->collection->collection_id;
22222221
val = cpu_to_le64(val);
2223-
return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
2222+
2223+
return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
22242224
}
22252225

22262226
/**
@@ -2361,7 +2361,6 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
23612361
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
23622362
gpa_t ptr, int dte_esz)
23632363
{
2364-
struct kvm *kvm = its->dev->kvm;
23652364
u64 val, itt_addr_field;
23662365
u32 next_offset;
23672366

@@ -2372,7 +2371,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
23722371
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
23732372
(dev->num_eventid_bits - 1));
23742373
val = cpu_to_le64(val);
2375-
return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
2374+
2375+
return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
23762376
}
23772377

23782378
/**
@@ -2559,7 +2559,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
25592559
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
25602560
collection->collection_id);
25612561
val = cpu_to_le64(val);
2562-
return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
2562+
2563+
return vgic_its_write_entry_lock(its, gpa, val, esz);
25632564
}
25642565

25652566
/*
@@ -2575,8 +2576,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
25752576
u64 val;
25762577
int ret;
25772578

2578-
BUG_ON(esz > sizeof(val));
2579-
ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
2579+
ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
25802580
if (ret)
25812581
return ret;
25822582
val = le64_to_cpu(val);
@@ -2614,7 +2614,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
26142614
u64 baser = its->baser_coll_table;
26152615
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
26162616
struct its_collection *collection;
2617-
u64 val;
26182617
size_t max_size, filled = 0;
26192618
int ret, cte_esz = abi->cte_esz;
26202619

@@ -2638,10 +2637,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
26382637
* table is not fully filled, add a last dummy element
26392638
* with valid bit unset
26402639
*/
2641-
val = 0;
2642-
BUG_ON(cte_esz > sizeof(val));
2643-
ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
2644-
return ret;
2640+
return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
26452641
}
26462642

26472643
/**

arch/arm64/kvm/vgic/vgic.h

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

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

0 commit comments

Comments
 (0)