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 | 088fa8f3e854ff33fe2d1188d2d237942956b918 (patch) | |
| tree | 207eae76f97d37602416a5c536b101e27eeb4086 /kernel | |
| parent | 439cb2e0b28267a9e2645b9555e85f0dd3008c1b (diff) | |
| download | open-iov-088fa8f3e854ff33fe2d1188d2d237942956b918.tar.gz open-iov-088fa8f3e854ff33fe2d1188d2d237942956b918.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; + } } } |
