Products > Security
T-Head XuanTie C910 and C920 RISC-V CPUs: GhostWrite
(1/1)
madires:
Full RAM access and control of peripheral devices for unprivileged attackers:
- GhostWrite - https://ghostwriteattack.com/
brucehoult:
This is a very bad bug from THead, which renders this CPU unsafe to use in a multi-user environment which might have bad actors e.g. a public multi-home server.
Since these are the cores which are in the 64 core SG2042 which has been available in single-socket systems since the start of this year, and is about to come out on dual-socket boards, this is a pretty big deal.
The same CPU is used in the Scaleway RISC-V servers, on a chip with 4 cores. However when you rent those you get the whole chip to yourself.
I disagree with the authors implication that this is a misimplemented instruction, which they call `vse128.v`. First off, that naming style is for RVV 1.0 while the chips in question implement RVV draft 0.7.1 where the store instructions are named `vsb.v`, `vsh.b`, `vsw.v`, and simply `vse.v` and have very different semantics to the RVV 1.0 stores in the event that the store size is different from the current vector element size. The {b,h,w} instructions truncate larger values on store. If the sizes are the same then you might as well use `vse.v` -- and you have no choice for 64 bit elements anyway. In contrast the RVV 1.0 instructions *always* make you specify the load/store size explicitly always, and have 8, 16, 32, 64 sizes. In the event of a size mismatch they do a straight binary transfer of `vl` elements of the given size, but from more than or less than `LMUL` vector registers (a concept called `EMUL` Effective LMUL.
There is no `vse128.v` specified in the RVV 1.0 spec and it is not obvious what the encoding would be if one was to be added later.
The RVV 0.7 spec has fewer bits for the load/store size (and they are used up faster from having both sign-extend and zero-extend loads, which RVV 1.0 doesn't have), so there is no room to encode a 64 bit load/store let alone a 128 bit one.
So it is complete nonsense to claim that `vse128.v` is some kind of intended instruction on RVV 0.7 and that it iwas implemented incorrectly.
It is simply an undefined combination of opcode bits. No one except an attacker would ever try to use it. Certainly no compiler or assembler can be persuaded to generate it, except by directly giving the hex value.
This undefined instruction should never of course give the behaviour they find. It should be detected and trapped in the instruction decoder as an illegal instruction.
I'd also suggest that the bug is not a bug of somehow bypassing the MMU, but is a bug of somehow decoding an illegal instruction as executing in M mode, which always bypasses the MMU.
In an high performance OoO CPU it might well be that each instruction carries with it the execution mode in which is was decoded, in order to not cause a flush of the hundreds of instructions in the reorder buffer every time you bounce into M mode and back.
So this should certainly never happen, and it's very very bad of THead to allow this, but it is not I think caused by what the authors claim it is.
ejeffrey:
Thanks for that explanation Bruce, I read that article a few days ago and was definitely confused how a CPU could ship with a bug where a regular instruction bypassed the MMU, since it would be completely unusable. Your explanation makes much more sense, and obviously it is still catastrophically bad for multi user applications. But it's good to know it's not something that e.g., a javascript compiler could accidentally create.
What are your thoughts on the fuzzing technique they describe?
brucehoult:
I'm currently travelling and spending time with people (my parents, other relatives, old friends) and haven't had a chance to read the full paper -- just the bare minimum of computer time at the moment. Home late this week...
Navigation
[0] Message Index
Go to full version