Remix.run Logo
tripdout 5 hours ago

I really wish I understood this, it hits a bunch of topics that I've heard of and are/sound interesting, but I don't know enough to follow it. I don't get the link between the NX bit (which I get) and speculative access.

Nail2680 4 hours ago | parent | next [-]

NX means not executable, so some bytes are excutable, some are non excutable. so some are instructions for the processor and others are data. Sometimes those are mixed and the cpu pukes out a bunch and restarts interpretation. most of the time those are normal. keep it normal and go fast.

RiverCrochet 5 hours ago | parent | prev | next [-]

Basically, the NX bit prevents CPU behavior (speculative fetches) that had a hand in Spectre-type vulnerabilities. That's surprising because that's not its purpose. This is for ARM CPUs.

jnwatson 4 hours ago | parent [-]

No, NX precedes Spectre by a long shot. It was originally intended so an attacker couldn't use a buffer overflow to change the PC and execute directly out of the attacker-controlled buffer.

adrian_b 4 hours ago | parent [-]

That is exactly what the poster to whom you replied said.

So Arm did not add another means to disable this kind of speculative execution, after Spectre was discovered, but they just reused the existing NX flag, expanding its functionality.

zephen 5 hours ago | parent | prev [-]

In an attempt to go fast and beat benchmarks and other computers, CPUs attempt to speculatively execute code, and then later undo the results of the speculation if it turns out it was wrong. This causes all sorts of security issues (spectre, meltdown, and friends et al.) even when it's done relatively competently.

When it's done incompetently as on this ARM implementation, then you can't even run perfectly good and correct code, because the CPU will attempt speculative execution on a location that you never asked it to execute code at, and then bork itself when it realizes that can't possibly work.

Naturally, this is the sort of problem that requires tedious dissection of what exactly happened, and copious amounts of alcohol.

MBCook 3 hours ago | parent | next [-]

So in this specific case, if I understood correctly, here’s what should happen:

Interrupt(?) fires to trigger hypervisor, hypervisor figures out what it needs to do, jumps to that code, does its job, returns.

The “figured out what it needs to do” is the issue right? So what was actually happening was:

Same start… CPU predicts what hypervisor will do, speculatively loads instructions from mispredicted branch target, that wrong instruction reads memory(?) against the “no data prefetch” settings for that part of memory, CPU blows up/halts/whatever.

The fix is to mark the area the branch was mispredicted to in such a way that the CPU won’t prefetch instructions. Thus that won’t be run and prefetch data, thus no violation. CPU execution continues taking the correct branch and everything is fine.

repiret 3 hours ago | parent | prev [-]

Speculative instruction fetches fetch code from "a location that you never asked it to execute code at" by design. If it already knew you asked it to execute code there, it wouldn't be speculative.

The Armv8/9-A architecture reference manual is clear that speculative instruction fetches are permitted in Device memory unless that memory is also marked NX. So if your hardware has side-effects from a certain address, but it maps it as Device non-NX memory, then your code is not "perfectly good and correct". Assigning correct memory attributes is one of the many things needed for correct code.