Comment by pizlonator

Comment by pizlonator 2 days ago

32 replies

> that's a weird execution for any useful definition of "weird".

Weird execution is a term of art in the security biz. This is not that.

Weird execution happens when the attacker can control all of memory, not just objects the victim program rightly loaded from the heap.

> Your central claim is that you can take any old C program, compile it with Fil-C, and get a memory-safe C program.

Yes. Your program is memory safe. You get to access P1 if p pointed at P1.

You don’t get to define what memory safety means in Fil-C. I have defined it here: https://fil-c.org/gimso

Not every memory safe language defines it the same way. Python and JavaScript have a weaker definition since they both have powerful reflection including eval and similar superpowers. Rust has a weaker definition if you consider that you can use `unsafe`. Go has a weaker definition if you consider that tearing in Go leads to actual weird execution (attacker gets to pop the entire Go type system). Java’s definition is most similar to Fil-C’s, but even there you could argue both ways (Java has more unsafe code in its implementation while Fil-C doesn’t have the strict aliasing of Java’s type system).

You can always argue that someone else’s language isn’t memory safe if you allow yourself to define memory safety in a different way. That’s not a super useful line of argumentation, though it is amusing and fun

quotemstr 2 days ago

You may define "memory safety" as you like. I will define "trustworthy system" as one in which the author acknowledges and owns limitations instead of iteratively refining private definitions until the limitations disappear. You can define a mathematical notation in which 2+3=9, but I'm under no obligation to accept it, and I'll take the attempt into consideration when evaluating the credibility of proofs in this strange notation.

Nobody is trying to hide the existence of "eval" or "unsafe". You're making a categorical claim of safety that's true only under a tendentious reading of common English words. Users reading your claims will come away with a mistaken faith in your system's guarantees.

Let us each invest according to our definitions.

  • pizlonator 2 days ago

    > I will define "trustworthy system" as one in which the author acknowledges and owns limitations instead of iteratively refining private definitions until the limitations disappear.

    You know about this limitation that you keep going on about because it’s extremely well documented on fil-c.org

    • quotemstr 2 days ago

      [Woman walking on beach at sunset, holding hands with husband]

      Voiceover: "Miracurol cures cancer."

      [Couple now laughing over dinner with friends]

      "Ask your doctor if Miracurol is right for you."

      [Same footage continues, voice accelerates]

      "In clinical trials, five mice with lymphoma received Miracurol. All five were cured. One exploded. Not tested in humans. Side effects include headache, itchiness, impotence, explosion, and death. Miracurol's cancer-free guarantee applies only to cancers covered under Miracurol's definition of cancer, available at miracurol.org. Manufacturer not responsible for outcomes following improper use. Consult your doctor."

      [Couple walking golden retriever, sun flare]

      Voiceover: "Miracurol. Because you deserve to live cancer-free."

      Patient: "I exploded."

      Miracurol: "That's extremely well documented on miracurol.org."

      • yjftsjthsd-h 2 days ago

        Wait, no, you just said

        > I will define "trustworthy system" as one in which the author acknowledges and owns limitations

        You can't then go on to complain that the author does document the limitations but considers the overall system good. Fil-C, by the definition you just espoused, is a "trustworthy system".

      • foldr 2 days ago

        It’s really sad to see your posts on this thread. Fil-C is an incredible achievement and absolutely full of interesting technical details to dig into. I’m not a mod, but as a reader of the site and someone who takes a curious interest in the progress of Fil-C, can you please stop attacking its creator like this. It’s tedious, needlessly rude, and lessens the opportunity for the rest of us to actually learn something from an expert.

        • quotemstr a day ago

          Facts are facts and exist independent of who discovers them. If you'd like to learn, the last thing you want to do is stop people poking at contradictions and pressure-testing claims. If Fil-C is really the "incredible achievement" you say it is, it can withstand scrutiny.

torginus 2 days ago

Sorry to intrude on the discussion, but I have a hard time grasping how to produce the behavior mentioned by quotemstr. From what I understand the following program would do it:

    int arr1[] = {1, 2, 3, 4, 5};
    int arr2[] = {10, 20, 30, 40, 50};
    int *p1 = &arr1[1];  
    int *p2 = &arr2[2];  
    int *p = choose_between(p1,p2);

    //then sometime later, a function gets passed p
    // and this snippet runs
    if (p == p2) {
     //p gets torn by another thread
     return p; // this allows an illegal index/pointer combo, possibly returning p1[1]
    }
Is this program demonstrating the issue? Does this execute under Fil-C's rules without a memory fault? If not, could you provide some pseudocode that causes the described behavior?
  • pizlonator 2 days ago

    No, this program doesn’t demonstrate the issue.

    You can’t access out of bounds of whatever capability you loaded.

    • quotemstr 2 days ago

      Fil-C lets programs access objects through the wrong pointer under data race. All over the Internet, you've responded to the tearing critique (and I'm not the only one making it) by alternatively 1) asserting that racing code will panic safely on tear, which is factually incorrect, and 2) asserting that a program can access memory only through its loaded capabilities, which is factually correct but a non sequitur for the subject at hand.

      You're shredding your credibility for nothing. You can instead just acknowledge Fil-C provides memory safety only for code correctly synchronized under the C memory model. That's still plenty useful and nobody will think less of you for it. They'll think more, honestly.

      • pizlonator a day ago

        > asserting that racing code will panic safely on tear, which is factually incorrect

        Try it. That’s what happens.

        > through its loaded capabilities, which is factually correct but a non sequitur for the subject at hand.

        It’s literally the safety property that Fil-C guarantees.

        Safety properties provided by languages aren’t about preventing every bad thing that users can imagine. Just because the language does something different than what you expect - even if it allows you to write a program with a security bug - doesn’t mean that the language in question isn’t memory safe.

        > You're shredding your credibility for nothing. You can instead just acknowledge Fil-C provides memory safety only for code correctly synchronized under the C memory model.

        Fil-C provides memory safety even for incorrectly synchronized code. That safety guarantee is easy to understand and easy to verify: you only get to access the memory of the capability you actually loaded. You’re trying to evade this definition by getting hung up on what the pointer’s intval was, and your PoC uses a pointer comparison to illustrate that. You’re right that the intval is untrusted under Fil-C rules.

        I’m not going to downplay the guarantees of my technology just to appease you. Whether or not you find me credible is less important to me than being honest about what Fil-C guarantees.

        • quotemstr a day ago

          In https://news.ycombinator.com/item?id=46270657, you write

          > If you set the index to `((alice - bob) / sizeof(...))` then that will fail under Fil-C’s rules (unless you get lucky with the torn capability and the capability refers to Alice).

          In the comment above, you write, referring to a fault on access through a torn capability

          > Try it. That’s what happens.

          Your position would be clearer if you could resolve this contradiction. Yes or no: does an access through a pointer with an arbitrary offset under a data race that results in that pointer's capability tearing always fault?

          > You’re right that the intval is untrusted under Fil-C rules.

          Can Fil-C compile C?

          You can't argue, simultaneously,

          1) it's the capability, not your "intval", that is the real pointer with respect to execution flow and simultaneously, and

          2) that Fil-C compiles normal C in which the "intval" has semantic meaning.

          Your argument is that Fil-C is correct with respect to capabilities even if pointers are transiently incorrect under data races. The trouble is that Fil-C programs can't observe these capabilities and can observe pointers, and so make control flow decisions based on these transient incorrect (you call them "untrusted") inputs.

      • judofyr 2 days ago

        Can you show an actual minimal C program which has this problem? I’m trying to follow along here, but it’s very hard for me to understand the exact scenario you’re talking about.

tialaramex 2 days ago

> Rust has a weaker definition if you consider that you can use `unsafe`

I don't see it. Rust makes the same guarantees regardless of the unsafe keyword. The difference is only that with the unsafe keyword you the programmer are responsible for upholding those guarantees whereas the compiler can check safe Rust.

  • foldr 2 days ago

    C is safe by the same logic, then? You can write safe code in anything if you don’t make mistakes.

    • tialaramex 2 days ago

      But the definition is what we're talking about, not whether you make mistakes. Of course it's important that safe Rust is checked by the compiler, but that's crucially not part of how safety is defined.

      I would guess that somebody more on the pulse of C's safety efforts could tell you whether they have a definition of memory safety for C or whether they're comfortable with an existing definition from somebody else.

      • jancsika 2 days ago

        Since you know C and you know Rust:

        I'm curious what you make of quotemastr's point about a race causing a mismatch between the pointer's capability and its index. First off, in your estimation can this realistically be exploited to wreak havoc on extant C programs compiled using Fil-C? Second, is such a mismatch able to happen in safe Rust? Third, is such a mismatch able to happen in unsafe Rust?

        Edit: clarification to narrow the question even further

        • tialaramex 2 days ago

          I can try.

          "Wreak havoc" is a very vague claim. Instinctively the tearing feels like something very difficult to usefully exploit, but, we know historically that the only people who can reliably tell you whether it was difficult are the attackers actually trying to do it. Don't believe the defenders.

          AIUI this capability versus value distinction is a Fil-C thing. So, that's not a thing in Rust at all. In Safe Rust the pointer types, which is what we care about here, aren't very interesting because safe Rust can't dereference them, safe Rust is fine with you making a pointer from the word "LAUGHING" (not a pointer to the string, just the literal bytes in ASCII, but treated as a pointer) or from just some random bytes you found in a data file, because it's not allowed to dereference them so, cool, whatever, no harm no foul.

          In unsafe Rust we're allowed to dereference valid pointers, but it's our job to ensure we obey that rule about validity, it being our job to obey rules is what "unsafe" means. So, that silly "LAUGHING" pointer isn't valid, it's just pointer-shaped toxic material. Even if, by coincidence, a pointer you have happened to have the same address as that pointer, in both C and Rust it's not OK to just go around dereferencing invalid pointers, they are not offsets into an imaginary huge array of all memory even though some C programmers act like they are.

          Ignoring the Fil-C specific capabilities, in Rust the tearing issue is a matter of synchronization, which is something Rust cares about as part of delivering "fearless concurrency". Rust's marker traits Send and Sync are good place to start learning about that. Yes, we could unsafely implement these marker traits in unsafe Rust when we shouldn't, and thus enable what I imagine you'd call havoc.

          So, mostly the problem is that your question is (unintentionally) too vague to answer well but I hope I was at least somewhat helpful.

      • foldr 2 days ago

        What I mean is, what’s to stop us saying that C upholds all the same guarantees that Rust does and that it’s the programmer that’s responsible for upholding them (just as the programmer is responsible in the case of Rust code marked ‘unsafe’)? This seems like a semantic game to avoid acknowledging that unsafe Rust comes with some of (though not all) of the same risks as C code.

        In short, the definitions are not important. What matters are the risks that you do or don’t run. And if your Rust code contains unsafe blocks, you are running risks that you wouldn’t be if you used Fil-C, which has no such escape hatch. (Of course this goes both ways – your Fil-C code is more likely to fail, safely, with a runtime error due to a mistake that Rust would have caught at compile time.)