Hacker News new | past | comments | ask | show | jobs | submit login

Image libraries are exactly where we need rust-style safe code.



No, image libraries is exactly where performance always beats safety and where other approaches to secure them actually work, like sandboxes and containers, and kind of have to be used anyway, since memory safety doesn't guarantee that unpacking an image won't DoS the system.


> No, image libraries is exactly where performance always beats safety and where other approaches to secure them actually work, like sandboxes and containers, and kind of have to be used anyway, since memory safety doesn't guarantee that unpacking an image won't DoS the system.

Sandboxes have significant performance costs of their own: the cost of spawning and communicating with a separate process, in addition to the extra memory use of a multiprocess architecture. They also come with high engineering overhead: creating a Chromium-like sandbox is a lot of work (which is why so few apps go to the trouble), and it's easy to mess up and accidentally introduce sandbox escapes. There is the attack surface of the kernel and IPC layer. Finally, what seems at first to be a simple IPC interface between the image decoder and the host application becomes a lot more complex when hardware acceleration (GPU or otherwise) becomes involved. Securely providing a decoder access to hardware (say, to perform iDCT or colorspace conversion) is a nontrivial task.

This comment didn't deserve to be downvoted, as it's a legitimate argument. But when you add up all of these costs compared to just having a system that prevents memory safety issues in the first place, the Rust approach is rather appealing.

(Oh, by the way: Preventing image DoS isn't as hard as it sounds. Refusing to decode images larger in area than some limit gets you most of the way there.)


Sandboxes and, to a certain extend, containers, are mitigation techniques ! Since you cannot trust the program you run on the server, you add an additional layer to reduce the risk that an attacker does harm before the vulnerabilities are found and patched. I know nobody who doesn't apply security patches for his software because he uses containers …

If you can get rid of half of the security risks by using software that are free for memory-born vulnerabilities, that's a win. That's what Rust is about.


Bounds checking and panicing are similar mitigation techniques and not an actual freedom from memory-born vulnerabilities, just take place directly in the code, not on the OS level.

Things are a bit more complicated with image libraries though, because a) performance is usually critical and b) even if you have that casual use case and it's not yet critical, memory safety is still not going to make it free from vulnerabilities to accidental DoS attacks (not even talking about malicious users here!), unless you apply those mitigation techniques and deploy supporting infrastructure to prevent process from using all memory and all CPU and take too long, etc.


> Bounds checking and panicing are similar mitigation techniques and not an actual freedom from memory-born vulnerabilities

Absolutely. Bounds checking is a mitigation technique to avoid potential footgun when you want/have to use manual array indexing.

In most situations in Rust, you use iterators instead of array indexing. Those are the «actual freedom from memory-born vulnerabilities» and have no associated overhead. Since it is known at compile time that you are not going to access invalid memory, there is no need for bounds checking in this scenario.

Most of rust safety comes from clever compile time checks with no additional cost at runtime. The two main counter-examples I can think of are :

- bounds checking on manual array indexing

- usage of a secure hash function by default in HashMaps

The whole story about safe multi-threading and dangling pointers prevention is totally free performance-wise: everything is checked at compile time by the borrow checker.

> memory safety is still not going to make it free from vulnerabilities to accidental DoS attacks (not even talking about malicious users here!)

You're right, Rust doesn't solve all the problems at once. Is it a good reason to get rid of the benefits of solving the worst 50% of problems ?


> Is it a good reason to get rid of the benefits of solving the worst 50% of problems ?

Again, not for images. I believe the real reason is different, Rust people simply want to have an image library in its ecosystem, just like Go. Nothing wrong with that goal, makes it more appealing to new users. But that's it.


> not an actual freedom from memory-born vulnerabilities

"Memory-born vulnerabilities" sounds like a broad term, and if it includes DOS issues then Rust code is as vulnerable as anything else. But it's worth being precise: Rust's security model is about preventing undefined behavior.

If you have an out-of-bounds array write in C, that could do anything to the program. But in safe Rust code, all it can do is panic. Like you said, that's not necessarily any different from a DOS point of view, but it rules out a huge class of remote-code-execution bugs and leaks like Heartbleed. Of course it's still possible to write bugs and leak something you didn't mean to leak, but it shouldn't be possible to do that in a totally unrelated part of your process, and that's a big deal.


> memory safety is still not going to make it free from vulnerabilities to accidental DoS attacks

What kinds of DoS attacks are you thinking about that aren't covered by simply limiting the size of the images you need to parse?

I mean, I've written a PNG decoder and the only dynamic allocation I can think of that I needed was the actual decoded image data.


PNG compresses the image data using the DEFLATE algorithm. You can write data that decompresses to almost 1023 times the size of the compressed data. So if you allow 1 MB images, be prepared to allocate memory for and process about 1 GB of data.


PNG also explicitly specifies image dimensions, so there's no need for that at all.


"Performance beats safety" is a dichotomy that Rust is attempting to fundamentally reject. Safety often means you can go faster, not slower, but it depends on context, of course.


Rust tightly couples performance and safety. Sandboxing separates out performance and safety, so you can take your pick of languages for performance, and your pick of sandboxes for safety, without conflict.


     here other approaches to    
     secure them actually work, 
     like sandboxes and containers,
"It is a fallacy to think that for 30+ years people haven't been able to write a secure OS. But virtualization, and containers are" - Theo de Raant


GEMSOS, KeyKOS, ASOS, LOCK, VAX VMM, INTEGRITY-178B, seL4, NOVA... all in the 4Kloc-50+Kloc range for a reason. All simpler, smaller, and easier to model than a full OS. Two survived pentesting by NSA with others during validation way better in defect rate or correctness case than most OS's.

Theo's quote is BS by the numbers and pentest results. Sandboxing done right is way more secure.


While true, in practical terms, those OSes are not what people have lying around to do their image processing. I'd love a secure, formally verified, capabilities-based microkernel OS as much as next person, but all I have is Linux and various BSDs. It's a bit academic at this point.


The commenter countered that sandboxing was worthwhile by citing a claim by Theo de Raadt that getting those (i.e. VM's) right was about as hard as getting whole OS's of code right. That one proved futile meant the other would. I countered that citation with numerous examples that disprove his point. Then, by implication, sandboxing might be effective if it's done like in my examples. And there are CompSci designs doing stuff like that.

Whether you want to do image processing on a Linux, BSD, or one of my kernels is a separate topic. However, it's worth noting that even stuff like I cited could be useful for that where it stashes the image processor into its own protection domain with read access to memory containing input and write access to memory that will have the output. The code itself isn't allowed to do or touch anything else. At this point, exploits must be chained in clever ways. Modifying this to preserve pointer integrity, lowest overhead range being around 1-10%, would choke those kind of attackers further.

Using Rust is yet another tactic that can work well with or in lieu of a sandbox. Ideally with for issues the language itself can't cover. Three precedents for that are right on my list: GEMSOS's safety was improved using a Pascal subset with call-by-value semantics; ASOS was a combo of security kernel and Ada runtime to host embedded, Ada applications (lang-safety + sandbox); separation kernels like INTEGRITY-178B usually support runtimes for Ada and Java subset to get safety within components. Now, there's some OS's like Tock and Redox plus low-level libraries written in a new, safety-enhancing language. Such designs can benefit from the old strategies which we see a few in Redox. On other end, Genode uses many old and recent tricks in architecture but not safe language. It can also run a Linux desktop with your image processing code. ;)

Note: A bit academic is also misleading. Several, separation kernels are deployed commercially for things like secure, web browsing. INTEGRITY and LynxSecure are among oldest. The Nizza and Perseus architectures got turned into Sirrix's Turaya Desktop. These things aren't just academic.


It's academic in the colloquial sense that the tools you describe aren't available to use. I'd love to have all the futurustic, secure stuff you describe, but for a user's run-of-the-mill AWS deployment, that's not an option.

All the other stuff you say is on point, of course, and there's an argument or a hundred to be made that a lot of these problems are already solved, and that we (as users and developers) are missing out on a massive amount of amazing OS research that could have made everything better than our current insecure, 1970s-tech monolithic kernel OSes.


"It's academic in the colloquial sense that the tools you describe aren't available to use."

I just named multiple tools available to use in commercial sector and FOSS. Their predecessors were used by commercial and government sector for a decade before that. That's 100% not academic even if a few started there. If anything, more work just needs to be poured into FOSS stuff so it gets more deployment and impact.

"All the other stuff you say is on point, of course, and there's an argument or a hundred to be made that a lot of these problems are already solved, and that we (as users and developers) are missing out on a massive amount of amazing OS research that could have made everything better than our current insecure, 1970s-tech monolithic kernel OSes."

We're definitely in agreement there. Fortunately, we're seeing some exploration into that including on the Rust front with Redox.


    Then, by implication, sandboxing might be effective if 
    it's done like in my examples. And there are CompSci 
    designs doing stuff like that.
I mean it is great if you can wave your hands and invent a Hoarce Logic proof your code is secure. But your Hoarce Logic models hardware. While you can prove your Hoarce Logic is consistent you can't prove your Hoarce Logic maps to existing hardware. You can only ensure the review board you made your best effort.

Which defeats the exercise completely.


You could argue against safety of Rust, OpenBSD, etc. with the same strawman. What it and those kernels did were creating an abstract model realistic enough to be useful, embed a safety/security policy in that model, and produce code that corresponds to that model. Older systems used what's called Abstract, State Machines which are quite easy to model-check or even analyze by hand. Typically converted to FSM's with same advantage. It was usually done by hand and eye instead of formally. In GEMSOS, the Gypsy specs mapped to code's functions/modules about 1-to-1 in most cases.

Recent efforts did it formally for things ranging from kernels to application-layer sandboxes. In case of VCC and SPARK, they do annotations on the code itself. In things like seL4, they do proofs on the code connecting it to a model. So, one can do that. It's usually not necessary since we're talking about improving the security of things over the status quo. You seem to be adding an additional requirement of totally unhackable with mathematical proof down to the hardware. AAMP7G and SSP are production CPU's close to that, esp AAMP7G. VAMP with CodeSeal & CHERI might do it, too. One academic one was proven down to the gates. They're all irrelevant as we're talking about reducing damage of an image library on regular CPU's & OS'.

You trust the Rust typesystem, compiler, and optimizations were implemented correctly enough that they'll knock out a bunch of problems. Certifying compilers like FLINT & CompCert took mountains of verification effort to pull off a fraction of that. Whereas, I'm saying one can trust 4-12Kloc or a compiler transformation connected to an abstract model fitting on a page or two might do its job with fewer problems than trusting just complex, native code in C or whatever. I also encourage mixing such TCB's with language-based security. However, such a tiny, clean, ASM-style program will have way fewer defects than a full OS or application.


    You could argue against safety of Rust [...] with the same strawman.
Not in the slightest.

Rust does a mapping of input symbols to output symbols. The input symbols have no 1:1 mapping with machine instructions on any 1 platform. All Rust does is attempt to ensure the constraints of the input symbol language are ensured to exist in the output symbol language.

Lastly no compiler attempts to say it's model is 100% consistent will always work correctly in all circumstances.

Hell C doesn't even bother defining how most integer operations work (in older versions).

    What it and those kernels did were creating an abstract 
    model realistic enough to be useful

    realistic enough

    enough
That is my point. It is a close enough model. The model is an approximation. Most models do not cover all hardware, or inter-generational bugs for example the recent skylake 0xF000000000000000F bug.

This is impossible for them too. But for an attacker it is trivial to exploit these bugs.

Saying you've proved a system means the system is rigorously true beyond the shadow of a doubt. The fact you can't rigorously test underlying state machine, or hoarce logic correctly maps 1:1 with the underlying machine you haven't proved anything.

Okay so let us pretend I prove P=NP for a collection of symbols which I state map 1:1 to a set of all possible algorithms in both P and NP space. But I don't prove that second statement. I'll get laughed out my advisors office.

What proving software correct does is effectively no different then my antidote from a rigorous perspective.

Done a damned good audit? Yes.

Proved? No.

You are auditing software, not proving it.

This isn't a straw man. Or a logical fallacy. It is a failure of logic. You prove A is true in system B. But never prove system B is correct... You've proved nothing.


"It is a fallacy to think that for 30+ years people haven't been able to write a secure OS. But virtualization, and containers are" - Theo de Raant"

"here are some examples of containers & virtualization that were either proved secure against a policy with realistic model, survived tons of pentesting, or both. Sandboxing done right is way more secure" - Nick P. paraphrased

"you can't prove your Hoarce Logic maps to existing hardware... Which defeats the exercise completely." (you)

"Most models do not cover all hardware, or inter-generational bugs for example the recent skylake 0xF000000000000000F bug."

"let us pretend I prove P=NP for a collection of symbols which I state map 1:1 to a set of all possible algorithms in both P and NP space."

It's like you're talking about a whole, different conversation. Theo's claim is thoroughly refuted whether it was done by eye, hand proofs, model-checking, or full verification down to the gates. Done by each of these actually. The use of smaller systems with simpler API's plus assurance techniques that worked to reduce defects got results no monolithic OS or UNIX got. Hence, why people are recommending investigation or use of such approaches to sandbox applications given those approaches might similarly result in fewer vulnerabilities or with less, severe damage.

Then, you counter talking about how they aren't proven to code, in all circumstances, the hardware, P = NP, etc. What does all that have to do with the claim about reduction of efforts required or damage created using these approaches vs what building or relying on a whole OS would entail? You could throw all that same stuff at the alternative approaches. It would still be true. Whereas, people acting on my recommendations instead of Theo's would provably reduce their attack surface and number of hits they take based on the results gotten in the past by examples I gave. That's why your reply is a strawman to the discussion of whether sandboxing can reduce impact of problems or not with Theo's criticism being destroyed. Even by his own OS which had way many more kernel bugs that needed mitigation than stuff I cited which ran such crap deprivileged or eliminated it at design level where possible.


If you squint then containerisation looks rather like the minimalistic microkernels which have formed the few genuinely secure OSes of those 30+ years.


That's a hilariously appropriate typo in the spelling of his last name.


Containers provide resource limits but not necessarily safety. The ABI surface is too large. You kind of need the code inside them to be secure.


Hmm, what large surface? You only need like a couple of syscalls for an image decoder, it doesn't need anything else from the OS and is supposed to be short-lived.


> You only need like a couple of syscalls for an image decoder, it doesn't need anything else from the OS and is supposed to be short-lived.

Not if you're going to take advantage of hardware acceleration.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: