logoalt Hacker News

pizlonatortoday at 4:41 AM1 replyview on HN

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


Replies

quotemstrtoday at 4:51 AM

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

This logic is related to memory accesses. This is not an issue that can occur in systems that provide the memory-safety guarantees that the words "memory safe" usually name.

You can't escape failure to meet a public definition of a term by adopting a private definition. The English language has a term for this pattern.

> You’re being disingenuously imprecise

You are the one being imprecise. You claim that because T1 could access foo at some time in the past, it's okay for a subsequent execution to access foo when the program text limits the access to bar. The temporal history is irrelevant. You are taking language that applies to inter-actor access control and applying it to invalid execution detection.

If T1 and T2 were, say, mutually untrusting actors over a network, that T1 had a capability at one point would be a valid defense. We're talking about a totally different scenario, not an object-capability security system, but preventing attackers turning illegal C into various kinds of exploit, e.g. EOP, information disclosure, and so on.

It does not matter that T1 used to have the capability and could have used it. We're talking about an attacker using an exploit to make T1 do his bidding, not T1 itself being a hostile actor running in a sandbox.

You can't just define the problem away. Real-world C has these races. They've been exploitable. Your system doesn't close them.

> Hence, this isn’t an arbitrary memory access.

Not arbitrary, true. Irrelevant. It's a cross-object access that violates programmer expectations and is likely exploitable.

> This is a memory access that obeys the capability model

You're using the English words that denote a strong guarantee in the security community and using them to describe your weaker system.

> I think that is doing more damage than anything I have said

Damage to what? You can't fix this problem in Fil-C without introducing atomics to every globally-visible store path, so you're going around the internet trying to play definition games to define it out of existence. The only damage here is to people who think Fil-C provides stronger mitigations than it does.