aboutsummaryrefslogtreecommitdiffstats
path: root/f32/AUDIT-RLC-01.md
blob: cb44522689afd0e4fcc7cab5484960102fc4a7ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# RLC (gfx11) — first pass, and why it ranks low on this card

Evidence class **[ST]**. Image `psp_out/gc_11_0_0_rlc.bin`, code blobs `RLC_G`, `RLCP`,
`RLCV` (established as F32 code in `AUDIT-F32-01.md`; `IRAM`/`DRAM`/`SRL_SRM` are data).

## RLC uses a different register-addressing convention from SDMA

The SDMA result (`AUDIT-SDMA-01.md`) was `F32_index = 4*host_dword_offset + 0x4980`,
i.e. byte addressing. **That model is impossible for RLC**: 67% of RLC_G's register
indices and 61% of RLCV's are **odd**, so they cannot be `4*offset + C` for any single
`C`. Testing both conventions against `regRLC_*` (seg 1):

| blob | model | best fit | null median / 95th / max |
| --- | --- | --- | --- |
| RLC_G | `offset + C` | **18/82** at `C=0xab7a` | 1 / 3 / 4 |
| RLC_G | `4*offset + C` | 7/82 | 0 / 0 / 1 |
| RLCV | `offset + C` | **27/106** at `C=0xaba1` | 0 / 2 / 3 |
| RLCV | `4*offset + C` | 5/106 | 0 / 1 / 1 |

So RLC's F32 addresses registers by **dword index** with an RLC-block base around
`0xab80`, while SDMA's uses byte offsets. A joint fit over all three blobs gives
`C = 0xab93`, naming 28 of 163 distinct indices, with plausible results —
`RLC_SPM_RING_WRPTR/RDPTR`, `RLC_SPM_ACCUM_SAMPLES_REQUESTED`, `RLC_RLCS_PG_CHANGE_READ`,
`RLC_RLCP_DOORBELL_CNTL/RANGE`, `RLC_PACE_TIMER_CTRL`.

**This is partial, not solved.** Coverage is ~17% versus SDMA's 57%, and the base is not
a clean value. The remaining indices belong to other register blocks (RLC reaches into
GC, GRBM, CP and GCVM), each of which would need its own aperture base. An attempt to fit
those per-block bases produced **21 "significant" candidates with mutually inconsistent
assignments** — e.g. mapping an index inside RLC firmware to
`regSDMA0_QUEUE4_RB_AQL_CNTL` — which is overfitting across 21 prefixes × thousands of
constants, not a result. It is recorded here as a rejected approach so nobody repeats it.

## Structure

| blob | insns | distinct reg indices | `r1` reads |
| --- | --- | --- | --- |
| `RLC_G` (load base 0x2000) | 6144 | 82 | 1 |
| `RLCP` | 2048 | 6 | 1 |
| `RLCV` | 3072 | 106 | 1 |

The `r1` count is the important column. In SDMA TH0, `r1` is read **370** times because
`r1` pulls dwords off the host command queue — that is what made a precise taint model
possible. In all three RLC blobs it is read **once**, so **RLC has no host packet
surface**. Its inputs are driver-written RLC registers, the kernel-built save/restore
lists, and (for RLCV) the SR-IOV mailbox.

## Why this ranks low on *this* card, stated plainly

Every input that drives RLC here is already privileged:

* the RLC control registers are written by the kernel driver;
* the save/restore and register lists are built by the kernel driver;
* `RLCV` is the **virtualization** engine — its interesting surface is the VF→PF
  mailbox, which is a genuine guest→host boundary, but **this is a consumer Navi 31 with
  no SR-IOV**, so that path is inert on the hardware we have.

So unlike SDMA (where user-mode queues create a real user→kernel boundary, which is why
the `RB_PRIV` gating result mattered), RLC on this card offers **no trust boundary to
cross**. A bug here would be "the privileged driver can confuse the privileged RLC",
which is not a security finding under this tree's framing — the same reason every DMCUB
finding is scoped as loss of isolation rather than escalation.

**Recommendation: RLC is low priority on this hardware.** The part worth auditing is
`RLCV`'s mailbox handling, and that needs SR-IOV-capable silicon (an MI-series or
VF-enabled part) to be both reachable and meaningful.

## What would change that ranking

1. **SR-IOV hardware.** RLCV's VF mailbox is the only genuine boundary in RLC, and it is
   already disassembled here — the audit would be cheap once the hardware exists.
2. **Finishing the namespace.** At ~17% coverage the listings are only partly readable.
   The SDMA namespace was solved from a *structural* anchor (a bounded per-queue loop
   revealing the stride); the equivalent for RLC would be a loop over a known register
   array, which has not been located yet. Fitting alone will not do it.