Earlier quoted context omitted.
> like forgetting to check error returns One of the most common bugs in C (in my experience) is forgetting to check the error return on a malloc call. Kind of the worst of both worlds.
> One of the most common bugs in C (in my experience) is forgetting to check the error return on a malloc call. Very unlikely. 1. it won't happen in regular use, only if your are asking for a huge amount of memory (possibly by mistake), or the system is already full and you will likely experience problems with the whole system (freezes, instability, processes killed, etc) and not just with your program. 2. it will ne…
Redox OS Crash Challenge
71–80 of 82 posts
Re: Redox OS Crash Challenge
#72Earlier quoted context omitted.
The idea that something can be "necessary but not sufficient" comes up a lot, and is very often misunderstood. Rust-like guarantees are necessary but not sufficient for safe systems.
As DJB and other excellent programmers have demonstrated, they're not strictly necessary either. (and I really like Rust)
There was a time when good drivers argued that seatbelts weren't strictly necessary if you knew what you were doing in a car, so there shouldn't be laws insisting on them.
So if by "strictly", you mean logically possible and sometimes within human ability; yeahbut we now just have to be more practical.
No doubt I should have narrowed the scope of the first sentence of my first post; but I'll leave it for now.
Re: Redox OS Crash Challenge
#73Earlier quoted context omitted.
Yes! In fact I'd argue that null-pointer dereferences are not a memory-safety bug the way buffer overflows / use-after-frees / etc. are, they're a type-safety bug. It's not that NULL is a currently-invalid pointer, it's that NULL is not a pointer at all - it's a value that's been stuffed into the pointer type because C has no better way to represent this. The actual return type of malloc is the set of all possible po…
Why do you think NULL isn't a pointer? It most definitely is a pointer, it's the kernel the limits a ptr to 0 from being used, in fact you can use it if mmap_min_addr is set to 0.
1. A valid address to an object of some type.
2. Null.
One of these can be dereferenced, the other cannot; the valid operations are not the same, because they are not the same "type". Now, C of course will happily store both the address of an object and "NULL" in the same "type", and that's the problem.
There are a great many places in code in C where one would like to take a pointer that must contain an object's address; that is, a non-null pointer. The type system offered by C has no way to indicate this, and so the compiler cannot catch passing NULL to such a function.
(And I honestly would bet that the kernel limits it more due to C, than C uses 0 because the kernel limits it. That is, yes, the kernel limits allocating address 0, but the arrow of causality is the other way around.)
Re: Redox OS Crash Challenge
#74Earlier quoted context omitted.
Yes! In fact I'd argue that null-pointer dereferences are not a memory-safety bug the way buffer overflows / use-after-frees / etc. are, they're a type-safety bug. It's not that NULL is a currently-invalid pointer, it's that NULL is not a pointer at all - it's a value that's been stuffed into the pointer type because C has no better way to represent this. The actual return type of malloc is the set of all possible po…
Why do you think NULL isn't a pointer? It most definitely is a pointer, it's the kernel the limits a ptr to 0 from being used, in fact you can use it if mmap_min_addr is set to 0.
0x00000000 is a pointer, sure, and it points to the memory at address zero. But that's not the same concept as NULL, even if it happens to have the same representation. If malloc(32) returns NULL, it doesn't mean the memory between 0x00000000 and 0x00000020 is available for me to use.
false also has the same representation, but no one would claim that false is a pointer.
mmap_min_addr exists because C is unable to distinguish NULL and a pointer to address zero, and the Linux kernel is written in C, and too much code wrongly treats NULL as a pointer to 0x00000000 and attempts to read or execute the contents of memory there. If code did not confuse the two, mmap_min_addr would not need to exist.
And it is relatively recent; it was added as a security measure in June 2007 for Linux 2.6.23 in https://github.com/torvalds/linux/commit/ed0321895182ffb6ecf... , about 40 years after the invention of NULL.
Re: Redox OS Crash Challenge
#75Earlier quoted context omitted.
One example is something like enum A { B, C }: a function might have a precondition that it requires an A::B, and crashes/misbehaves when given an A::C. In Rust, this can be seen in Option::unwrap (requires a Some, panicking if given a None). Technically this is the same sort of thing as in Java, but, at least to me, it seems different/more easily controlled.
Unwrap is essentially asking for it to fail under that condition, so that's not exactly broken. Unwrap should always be suspect. It's easy to turn it into a pattern matcher instead, which explicitly forces you to hand the none case. I'm not saying you're wrong, but I don't think it's an example of an error created by a polymorphic type. (Instances of the same type can do this as well.)
One could actually even express the Option concept as a trait, with manual downcasts:
trait OptionLike {
type Contained;
fn is_some(self) -> bool;
fn as_some(self) -> Some;
}
struct Some { value: T }
impl OptionLike for Some { ... }
struct None { _phantom: ... }
impl OptionLike for None { ... }
Under this scheme, Option is expressed as a trait object like Box>, and the whole thing looks a lot more like the OOP/subclassing approach.In any case, the fact that unwrap is clearly documented to fail on the None case is orthogonal: it's an invariant about the (sub)types of it's arguments that isn't expressed in the signature.
Re: Redox OS Crash Challenge
#76Related: the Changelog podcast did a really good interview with the developer[1]. It's pretty long but worth the listen IMO. [1]: https://changelog.com/podcast/280
Re: Redox OS Crash Challenge
#77Earlier quoted context omitted.
> > Exceptions don't exist > > They're called panics. Nope. https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
It's non-local control flow with deterministic unwinding and defined stop points. It's an exception system. Sure, it's not "recommended", but recommendations don't define semantics.
If hypothetical unreasonable libraries are in scope, they can just open /proc/self/mem for writing (in safe Rust!) and violate memory safety, and that's not an argument that Rust isn't memory safe. So why should hypothetical unreasonable libraries be an argument that Rust has exceptions?
Re: Redox OS Crash Challenge
#78Earlier quoted context omitted.
Apache Struts and Equifax might disagree that the handling of exceptions doesn't cause security issues in Java.
If I'm understanding right, the Equifax vulnerability was CVE-2017-5638, where if an invalid Content-Type issue is given, it gets passed to an error-message printing function that searches through the entire provided message for OGNL code (a domain-specific language that apparently can deserialize arbitrary Java objects, or something), and so an attacker can pass OGNL code that spawns an external process in the Conte…
Re: Redox OS Crash Challenge
#79Earlier quoted context omitted.
If I'm understanding right, the Equifax vulnerability was CVE-2017-5638, where if an invalid Content-Type issue is given, it gets passed to an error-message printing function that searches through the entire provided message for OGNL code (a domain-specific language that apparently can deserialize arbitrary Java objects, or something), and so an attacker can pass OGNL code that spawns an external process in the Conte…
I agree that it isn't Java-specific, but Java is affected despite being memory safe and "it's pretty hard to provide malicious input to non-malicious Java source code that takes control over the interpreter" may not be as true a statement as it appears.
I think there is a meaningful distinction, still, between something like OGNL where the program / library is providing its own interpreter of the EDSL that is excessively capable (which can be done in any language, including Turing-incomplete languages, capability systems, etc.: a library can always dispatch input to whatever functions are available to it) -- i.e., where the programmer intended the functionality that was implemented, they just didn't think through what they were doing -- and things like buffer overflows and ROP where the course of program execution, on the existing interpreter / runtime / platform, is subverted to something the programmer did not intend. I'm not quite sure how to phrase it. (And I'm not sure on which side of the line arbitrary-object deserialization lands.)
Re: Redox OS Crash Challenge
#80Earlier quoted context omitted.
I agree that it isn't Java-specific, but Java is affected despite being memory safe and "it's pretty hard to provide malicious input to non-malicious Java source code that takes control over the interpreter" may not be as true a statement as it appears.
That's a fair objection, and I already had to add a caveat about deserialization libraries that can instantiate arbitrary objects. (Which is a problem that affects other memory-safe dynamically-typed languages too, e.g., Python's pickle and yaml modules have the same problems.) I think there is a meaningful distinction, still, between something like OGNL where the program / library is providing its own interpreter of…