diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-09 14:52:22 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-09 14:52:22 -0400 |
| commit | f5ee072aa3ea42f67eb5df20b1b3d71c19829368 (patch) | |
| tree | 4f0ede7e96c3752ed1dd052a216c691d70da99bf /kernel | |
| parent | 70ea49c667eb101b90730ed7a5077a7d7444c9ef (diff) | |
| download | open-iov-f5ee072aa3ea42f67eb5df20b1b3d71c19829368.tar.gz open-iov-f5ee072aa3ea42f67eb5df20b1b3d71c19829368.zip | |
vgsp-sema: validate the CE ring entry0 before trusting the layout USERD (ISSUE-0002)
r41 c1 regressed: svc_lookup answered rank4's fresh gpfifo VA with an
unrelated FB offset (0x90000) and the idle acceptance cemented the wrong
USERD (ring+0x10000 of the bogus base). Gate the layout-derived USERD on
the ring's entry0 decoding to a CE push VA + plausible len, the same
check svc_ring_autopin already uses; a bogus ring now falls through to
the previous candidate list.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 309210d..4cc1624 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -7728,19 +7728,42 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch, * An idle (0/0) read is accepted here because the guest writes the * block on the channel's first push; only unreadable or incoherent * candidates fall through to the old list. + * + * The ring itself must validate first (entry0 = a CE push VA + len, + * same gate as svc_ring_autopin): r41 showed svc_lookup can answer a + * fresh gpfifo VA with an unrelated FB offset (rank4 -> 0x90000), and + * an idle acceptance on that bogus base cemented the wrong USERD. */ if (ring_pa && ch->engine_type != 0) { - u32 p = 0, g = 0; - int rc = svc_userd_probe(vgpu, ring_pa + 0x10000, ring_ap, - ch->gpfifo_entries, &p, &g); + u8 e[SVC_GPFIFO_ENTRY_SIZE]; + u32 e0, e1, len; + u64 va; + bool ring_ok = false; - if (rc == 0 || rc == -EAGAIN) { - ch->userd_pa = ring_pa + 0x10000; - ch->userd_as = ring_ap; - ch->userd_ok = true; - *put = p; - *get = g; - return 0; + if (!svc_read_ap(vgpu, ring_pa, ring_ap, e, sizeof(e))) { + memcpy(&e0, e, 4); + memcpy(&e1, e + 4, 4); + va = ((u64)(e1 & 0xff) << 32) | + (u64)(e0 & 0xfffffffc); + len = ((e1 >> 10) & 0x1fffff) << 2; + ring_ok = !(va & 0xfffff) && + va >= 0x120000000ULL && va < 0x121000000ULL && + len >= 4 && len <= 0x10000; + } + if (ring_ok) { + u32 p = 0, g = 0; + int rc = svc_userd_probe(vgpu, ring_pa + 0x10000, + ring_ap, ch->gpfifo_entries, + &p, &g); + + if (rc == 0 || rc == -EAGAIN) { + ch->userd_pa = ring_pa + 0x10000; + ch->userd_as = ring_ap; + ch->userd_ok = true; + *put = p; + *get = g; + return 0; + } } } |
