summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-09 14:52:22 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-09 14:52:22 -0400
commit088fa8f3e854ff33fe2d1188d2d237942956b918 (patch)
tree207eae76f97d37602416a5c536b101e27eeb4086 /kernel/gsp_sema_service.c
parent439cb2e0b28267a9e2645b9555e85f0dd3008c1b (diff)
downloadopen-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/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c43
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;
+ }
}
}