logoalt Hacker News

quotemstrtoday at 3:45 AM1 replyview on HN

> In a race, you at worst access an object you could have loaded from whatever field you were racing on.

Suppose a pointer ptr is initialized to foo and transitions once to bar; suppose also that x is attacker-controlled. Then,

  T1: T* p = ptr; if (p == bar) p[x] = 7
  T2: ptr = bar
A program can observe p == bar (testing the address bits) but still permit a write to foo through p (allowed by the stale capability bits after offset by attacker-controlled x), allowing T1 to perform an unexpected mutation of foo.

No, you do not always trap in this scenario, as you've claimed repeatedly on X. You perform the capability check after combining p and x. If an attacker sets x == foo - bar, then p[x] refers to memory inside foo even if p == bar.

Because (for understandable reasons) you don't insert a memory barrier between a write of a pointer's address bits and its capabilities, use two-word atomic accesses, STM, or in any other way synchronize writes to pointer addresses and capabilities, programs with data races can observe arbitrary combinations of linear addresses and capabilities that go along with them.

Plenty of exploit chains have had humbler beginnings.

This access-foo-through-pointer-to-bar scenario can't happen in Java. It can't happen in CHERI. It can happen in Fil-C. Yes, T1 at one time had a capability on foo, but the programmer intent is clearly to mutate only bar, and Fil-C allows an execution that mutates foo instead.

Elsewhere, you've claimed such executions cannot be exploited. I am skeptical of this claim given previous exploits that began by the camel poking its nose through similarly innocuous-seeming holes in the tent.

Fil-C cannot fully protect C programs from exploitable memory corruption caused by violations of the C virtual machine. 99.9% of practical ones? Sure! Fil-C is good stuff. But there are holes (not only here, but for arenas, intra-object corruption, etc.), and these are holes that safe Rust prevents. Fil-C and Rust rules prohibit different (but mostly overlapping) classes of exploit.

Could you define Fil-C's behavior as "memory safety"? Sure. You can define words to mean anything. You cannot, however, define Fil-C as something that just deletes the security implications of bugs in existing C programs. Does it mostly achieve this goal? Sure. Does it supply comprehensive coverage? No! It's a hardening tool, not a panacea, and it would behoove you to represent it as the useful tool it is, not magic pixie dust that makes C safe.

Please stop ruining a tool as good as Fil-C by claiming it does things it does not and cannot.

> In Go, you can bypass all protections and corrupt all of memory if you race on structs (I think).

This is my understanding as well. I'm glad we agree, opinions on Fil-C memory model counting as "safe" aside, that Go is awful.


Replies

pizlonatortoday at 4:41 AM

The “bug” in your example hinges on this:

> if (p == bar)

It is not in scope of memory safety to make sure that logic not related to memory accesses works as you expected.

In Fil-C, the integer pointer value (the intval) is not trusted. You could get it wrong with things more sexy than races (integer overflows or just plain bad math). Fil-C just guarantees that your accesses obey the capability model, which is true in your example - the only object the program can access is whatever object the capability you loaded points to.

You’re being disingenuously imprecise when you use this framing:

> access-foo-through-pointer-to-bar

In fact, you can only access foo if bar’s capability referred to foo, and that can only happen if the thing being raced on (the pointer in shared memory) had a prior store to it that had foo’s capability.

Hence, this isn’t an arbitrary memory access. This is a memory access that obeys the capability model. It’s a memory access that would have been possible even if the program had no race.

> Please stop ruining a tool as good as Fil-C by claiming it does things it does not and cannot.

You are mischaracterizing the issue to make it seem like it’s a memory safety issue, when it’s not. I think that is doing more damage than anything I have said

show 1 reply