Will there be a massive review process every time someone updates the vendored dependencies? Or will each dependency change be reviewed one release increment at a time?
What happens if a dependency adds a system call something? Libraries intended for kernel-friendly use cases really need that scope to be an intentional goal.
Of course, they would certainly review any updates to vendored code. Just because most companies are too lazy to audit their dependencies doesn't mean the kernel needs to be.
As for syscalls, Rust has a whole ecosystem of no_std crates for kernel and microcontroller development that already assume the lack of an OS. We use (and contribute to) such crates extensively in our product (which is already developed jointly with the Linux Foundation, though we're not working on the Linux kernel (well we are a little bit, but all of that work is still in C :P )) and can vouch for their quality.
Ah this makes total sense. Other day I read how some factories are dumping pollutant chemicals in rivers. But it turned out to be all fine as there was no wrong intentions it just was not economically viable for them to properly dispose waste.
Congratulations, you found the solution to the problem. Hold companies liable for the damages their sloppy security practices create. Bruce Schneier wrote an excellent article on the topic in 2003 [1].
This is more a coordination/incentive/game theory problem than a cost one. If all the companies that use open source libraries contributed resources to pooled audits then individually they'd have to pay far less than each reviewing dependencies on their own.
Maybe that could be incentivized by penalizing data breaches caused by negligence and using non-audited code = negligence. But I suspect this would just result in people running some random static analysis tool and calling it a day rather than doing for proper code reviews.
Penalizing does not work, period. Religion tried with scare tactics for thousands of years. Sharing costs for auditing open source libraries depended on would need a platform to share the load, something like a Patreon for businesses.
> What happens if a dependency adds a system call something?
AFAIK, in Haskell, any function that returns IO must indicate it in the type signature.
If you could find a way to take that idea, expand upon it with much more fine-grained types, then you could build an ecosystem where any system call, external network call, use of env variables, etc is baked into the type signature of every function and package. If you could do that, you could build pretty trivial checks to ensure that a given package doesn't perform any kind of system call.
So sort of like the types of permissions we assign to apps on Android, but represented (and enforced) directly in the type system.
It would be difficult to make something like this ergonomic but could be pretty cool.
This works in Haskell because it is a purely functional language, and the IO monad is an intrusion into that to allow for useful computation. Rust is not purely functional, so there is no way to enforce something like this in the compiler. You could add an IO monad, but it would be easy for someone further down the chain of packages to ignore it and make a syscall.
Anything similar in rust would have to be enforced through code auditing tools, either forking the compiler, using some of its code as a basis or starting from scratch.
Yes, it is a shame that no version of that purely functional Haskell ideal has been created that could reasonably be used for kernel development. Using the type system to constrain side effects of code in the way you suggest would eliminate massive classes of security vulnerabilities and crashes.
IO is necessary because of purity, but it's in no way enabled by it. You don't need purity to have the IO monad, and you don't need purity to enforce that IO is defined in a type signature.
I feel like effect systems like the ones in unison and koka (or haskell with extensible effects / freer libraries like polysemy or eff) get pretty close to that. I feel like there's a lot of effort needed to make the idea "mainstream" and to get a good implementation going though (I think a lot of implementations use delimited continuations, but I'm not sure so don't quote me on that. At least it's the design for haskell's new primops to make that kind of library better)
If you're going to pick a "counterexample" just say unsafePerformIO, or the aptly named accursedUnutterablePerformIO[0]. (There are quite a few variants.)
Everybody knows that there are escape hatches because they are actually sometimes absolutely required for asymptotics or just plainly because it may be too hard to "prove" that your code is safe to the compiler.
That isn't a gotcha -- you know exactly what code you need to audit extra carefully.
[0] That one's actually in ByteString to technically not standard Haskell, but I just like the name.
What happens if a dependency adds a system call something? Libraries intended for kernel-friendly use cases really need that scope to be an intentional goal.