We can debate about the 90s style package management, but old C-based file parsers and DAC access control were certainly not designed for modern attack vectors. Defending a device now requires layered security using a combination of among other things:
- Memory-safe languages where possible.
- Sandboxing of applications, parsers, etc., along with a strong permission model.
- Mitigation like secure app spawning, zeroing out pages, etc.
- Modern mitigation hardware-assisted mitigation like MTE and PAC.
- Storing secrets in a separate secure enclave (not ~/.config or ~/.ssh).
- Read-only and fully verified system partitions (anti-persistence).
This graph:
https://security.apple.com/assets/image/generated/xlarge_adv...
from Apple's MIE docs [1] shows where modern systems like iOS and Android are. An attacker often needs a long exploit chain to compromise a device and it becomes increasingly difficult with various mitigation techniques. On the standard Linux desktop it's often as easy as exploiting an image parser in a client. Old parsers in C have a history of bad vulnerabilities, exploiting one often gives you privileges of the process calling the function, since Linux applications mostly don't separate/sandbox parsers and from there you have direct access to all data of the user, since Linux applications are typically not sandboxed.
[1] https://security.apple.com/blog/memory-integrity-enforcement...
Another angle on this is general reliability and what that does to the experience. I'm reminded of Linus having a moan about poor availability of ECC in consumer RAM and how many errors that get blamed on software are actually down to something happening to hardware but it isn't specifically identified. Plus when you're talking billions of devices even small proportions are significant. Firefox built a memory tester into their bug reporter tool as that 'noise' became a large enough problem for them.
Lets not forget that the motivations for Alef, and Limbo, from the C authors themselves, were also to improve language safety.
In Inferno, only the kernel, DisVM (+ JIT), and a few drivers are still C, everything else in userspace is Limbo.
> Limbo is the application programming language for the Inferno operating system. Although Limbo looks syntactically like C, it has a number of features that make it easier to use, safer, and more suited to the heterogeneous, networked Inferno environment: a rich set of basic types, strong typing, garbage collection, concurrency, communications, and modules. Limbo may be interpreted or compiled ‘just in time’ for efficient, portable execution.
https://doc.cat-v.org/inferno/4th_edition/inferno_OS
And even if the design isn't the best in the world, it was then followed by Go, it was not what Google is doing in C++ should be redone in C.
https://commandcenter.blogspot.com/2012/06/less-is-exponenti...