5 ms·
Remote code execution occurs in one of exactly two ways. - eval/exec() of untrusted turing-complete code - memory unsafety There are strange machines and log
by gue5t 11y ago
Remote code execution occurs in one of exactly two ways.
- eval/exec() of untrusted turing-complete code
- memory unsafety
There are strange machines and logic vulnerabilities, which as you're aware are pitfalls present in all languages, and can be very subtle. But these are not the same as executing arbitrary operations with all the privileges of the process. This is something we can end today, and Rust would suffice to do it, and can be deployed in many of the same situations as C.
The primary second-system problem with Rust is lack of a stable ABI and upgradable dynamic linking story (e.g. for generics which are effectively inlined even across shared library boundaries), which makes it impossible to upgrade shared libraries. That's a serious problem, which needs to be addressed if Rust is going to improve security for the world outside of the "we static-link 50MB of libraries" Web browser space.
- JabavuAdams 11y agoEvery engineering decision has costs as well as benefits. It's the same reason soldiers only wear heavy armour in the centre of their chests and backs. Why don't we armour the rest? Because the cost outweighs the benefits ... and the tooling (i.e. medevac and modern medicine) makes up for the deficits.
- anon1385 11y ago>Every engineering decision has costs as well as benefits. This is only true if you are superstitious or religious and believe that good things that happens to you (or humanity in general) must be balanced out by something bad happening.
- JabavuAdams 11y agoAre fucking serious? Have you built anything significant? This is a very empirical view, not a superstition. If you want to learn more about this, and aren't just trolling look at the development of the A4 Skyhawk, the lunar lander, the space shuttle ... hell, any well documented large system. I wish I could reach through the internet and smack you in the head for such a stupid comment.
- dang 11y ago> Are fucking serious? Have you built anything significant? [...] I wish I could reach through the internet and smack you in the head for such a stupid comment. I gave you a general reply upthread, but this comment deserves a specific one. You simply can't attack people like this here. I don't think you intended it in a mean way, but it's still the kind of thing we ban accounts for. https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newswelcome.html https://news.ycombinator.com/newswelcome.html
- autoreleasepool 11y agoThat's such an irrational assertion, ironically enough. Every decision has a trade off, even non-engineering decisions. It's called opportunity cost.
- woodman 11y ago> It's called opportunity cost. The law of conservation of energy, as close to the metal as it gets. I remember reading about the same thing in terms of algorithmic complexity (in the context of data compression), and how one can only shift entropy about. Anybody got any keywords handy for practical examples? My hour of searching ended with conservation of information and black holes...
- deleted 11y ago[deleted]
- anon1385 11y agoOpportunity cost doesn't make all decisions zero-sum. There is a quirk of human psychology that makes us believe that most things must be zero sum (i.e. that anything I do that improves something I care about must have a 'payback' at a later date and that to achieve a good outcome I must always make an equivalent sacrifice). JabavuAdams is falling for that. Although his inability to control his own violent emotional outbursts is probably going to be the more significant problem in his life.
- deleted 11y ago[deleted]
- TeMPOraL 11y agoCosts and benefits don't usually add up to 0. If they did, everything you do in your life would be absolutely irrelevant. The trick is to chose things with best cost+benefit value, and if it's not easy to express all costs and benefits in a single unit (because it may be hard to estimate them), then you chose so that you get costs and benefits you like the most.
- thrownaway2424 11y agoI have seen my share of benefit-free engineering decisions.
- pcwalton 11y ago> Every engineering decision has costs as well as benefits. Can you elaborate, in detail, what the costs of memory safety are?
- JabavuAdams 11y agoAt the very least: the cost of rewriting, re-testing, and re-deploying systems in a memory-safe language. The cost of realizing half-way through adoption that there are things that you need to do, used to be able to do, but cannot do in the new language.
- pcwalton 11y ago> At the very least: the cost of rewriting, re-testing, and re-deploying systems in a memory-safe language. True. In most cases, this is completely outweighed by the benefit of not having these kinds of security vulnerabilities, as well as the other benefits that come with safety. > The cost of realizing half-way through adoption that there are things that you need to do, used to be able to do, but cannot do in the new language. Can you explain exactly you cannot do with Rust?
- RaleyField 11y agoMemory safety costs 10% in execution speed and takes 50% more effort to develop, a fair trade-off anyone can take on behalf of their customers. Shortcomings of C are offset by many eyeballs law and the security life-cycle processes so much so that we can afford to safely abandon most organized auditing as well as any defensive coding.
- pcwalton 11y ago> Memory safety costs 10% in execution speed and takes 50% more effort to develop, a fair trade-off anyone can take on behalf of their customers. That doesn't match my experience. Source? > Shortcomings of C are offset by many eyeballs law and the security life-cycle processes so much so that we can afford to safely abandon most organized auditing as well as any defensive coding. In effect, you're saying we shouldn't care about security vulnerabilities, because they'll be patched. That may be true for your projects. It's not true for many organizations.
- dbaupp 11y agoRust code exposing a C ABI (e.g. as a slot-in replacement for an existing C library) behaves like any other upgradable shared library.
- gue5t 11y agoOf course, but then you've hamstrung the typesystem that makes Rust safer than C, and generated a lot of work for developers who have to convert all internal types to #[repr(C)] ones at library boundaries. Rust without cross-crate generics is way less fun--you lose "theorems for free", unless you can make guarantees about the pre-ABI translation to/from C types (which would ultimately amount to defining an ABI).
- dbaupp 11y agoYou've hamstring the type system at the interface, internally you still get all the benefits. In any case, a typical use-case for a shared library like this is embedded into other applications, which may not be written in Rust at all, and hence things like generics don't work anyway. In fact, this is reflected in a common way to expose an interface in this manner: have a main Rust interface (i.e. with normal generics etc.), with thin C-compatible shims that do the right set-up (e.g. converting arguments) to call that code. Also, I'm not exactly sure how you expect arbitrary cross-crate generics to work for a dynamically reloadable library: they're somewhat inherently incompatible (a downstream type can be inserted deeply into a library's code). I vaguely recall inklings of some approach for C++, beyond just explicitly instantiating specific template parameter combinations in the shared library, so if you know more about that, I'd love to here.
- gue5t 11y agoPersonally, I've always thought that type safety provides the most benefit at boundaries between codebases: you have people composing pieces that they don't understand, and the types serve to guide how those pieces can be composed to result in a correct program. Within a library, it's not uncommon that the core data structure or processing is only correct because a human looked hard at it--I would be surprised if Rust implementations of, say, font rendering, used types internally to guarantee the correctness of their rendering relative to a formal specification. Instead they're using types to make sure they process all input, or make sure they handle memory safely. Generics are another place where this becomes the case: if a library exposes a "fold" function generic over both the accumulator and element type, accepting void* instead of T and U means you lose the ability to make sure user don't mix up places where you want an element and places where you want an accumulator. Dynamically upgradable cross-crate generics, ultimately, require recompilation if you want the performance benefits of monomorphization. But it would be possible to have patchable sites around inlined generics that the dynamic linker could change to instead jump to a version which did not inline generics and which simply called into a non-type-specialized routine in the other library. You'd end up with two versions of compiled code in the binary around each call site for a generic: an inlined-optimized-and-code-motioned one, as usual, and an assumption-free one compiled considering generics to be opaque blobs and using dynamic dispatch for trait methods so that the same code can be used for all instantiations of the generic function. For example, a function parameterized over an unconstrained type T can't do anything useful with values of that type, except dropping them. Thus code would be generated in which the call to the drop impl would be dynamic. I think this can be made to work w/r/t non-object-safe trait bounds as well, but I'm not sure how to justify that. I think library changes which alter which impls get called on which types (i.e. which affect specialization) would still be ABI-breaking, unless you had some more cleverness (type-id-based dispatch for the deoptimized case? ugh) to deal with that complexity. I also don't think this solution is ideal, but I think it's very important for Rust to be considering these issues, because given the design of the current modern operating system, having separately upgradable libraries is really important. Maybe Rust should be pushing for changes in the OS design, in a direction like NixOS is taking, but it seems like it isn't ready use for building the future's userspace when it can't provide both safety benefit across library boundaries and separate upgradeability.