I'm sorry, dear Mr Stallman, but POSIX is defective by design and even though it was an amazing project 30+ years ago, it is now biting us E V E R Y - S I N G L E - D A Y. What was the very best in the mini- and micro-computers era is now totally unadapted and no hardware tweak or supervisory tool could ever solve the fundamental problems. And all the new languages (even the "safe" ones) perpetuate the misconceptions that you could make an unsafe system safe by using a safe language. You should already know that the weakest link breaks first, right ?
POSIX was never meant to be safe by design. It is inherently tied to the standard libraries, which are inherently designed for and by the C language, which is well known to not be safe...
- You can change the application programming language : you keep the standard libraries.
- OK let's change the standard libraries : nobody will want to program for your platform, AND the core OS will remain tied to the standard interfaces...
- Let's make a novel interface and kernel then ? Oh, others have tried and... they are stuck by performance issues because their HW platform is designed to run POSIX fast.
This co-evolution creates a macabre dance and there is no solution. The whole thing is rotten to the core but held in place because everybody uses it !
Of course the "new programming model" requires an adapted platform to run smoothly. However this is not a hard requirement and the system can be emulated at some level or another, to help bootstrap the transition.
Let's simply start with the most common source of vulnerabilities : buffer overflows. These should NEVER happen. Yet they do. All the time.
The i286 introduced the BOUND opcode in 1982... Where is it used ???
Oh yes, segmented and paginated memory is the solution...
But wait, flat space is sexier and segment registers are PITA.
Let's make fast SW and throw all the compiler warnings through the window...
IF you use a language that implements boundary checks. Some are more stringent than others... but speed always ends up being the excuse for indulging in the safety-sin again and again, and processors are tired and tired of checking the same pointers for nothing. Because it can never occur right ?
iAPX432 wanted to solve this with a micro-managed system with complex properties and it was slow. I understand why... but it would have been safer, right ?
But wait !
We're in 2020 and in hindsight (hahaha) 70% of all security bugs are memory safety issues and half of them "are use-after-free vulnerabilities, a type of security issue that arises from incorrect management of memory pointers"
So you use a block, free it and ... it can still be read ? Why would that be possible ?
Oh wait : we are bound to use the standard libs, even if our programming language has its own system.
"There will always be bugs" is an old refrain, and it is not false.
It is however a lousy pretext to accept preventable bugs and incapable platforms.
I see a kind of bugs that is not completely dependent on the tools and the programming languages : check the goddamned access rights. Check which process requests what service and in which context.
This is not the perfect solution but any system call should be easily traced by the callee to the root of the process tree. The whole history and tree of who calls what and with which access rights must be visible by the whole computer. So it's another hardware-assisted feature that must be etched in silicon (or whatever).
I am not blaming anyone here, and I know extensive efforts are being made, for example with Rust. However this is not a complete solution, as long as the whole computer system co-evolves around old premises dating from the 60s, when things were so simple and laid back (or not, if you happened to develop MULTICS).
But the time has come.
Yann Guidon / YGDES
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
The POSIX library's fundamental data type is the null-terminated character string and the unbounded buffer, accessed by a single register-sized pointer. The size info is in-band and unsafe. Any safe & sane strengthening of POSIX will have to replace all those uses by something more complicated, giving start address, current end, and container limit. Those changes can be implemented with acceptable safety and efficiency on ANY computer architecture, for all programs that are rewritten into the changed language & API. But not for any unchanged C programs expecting legacy library headers. Have big companies adopted some nearly-standard alternatives?
Are you sure? yes | no
iAPX432 was famously inefficient. Its design for object-oriented programs, object-structured kernel calls, and rigorous safety checks were just part of its overhead inefficiencies. That same chip/OS team went on to re-implement their high level safety notions on an i960 RISC chip with an efficiency-aware design. I wonder if their final i960approach is general and efficient enough to serve as a starting point. When calling between different protection domains, how many cache/memory cycles were needed to call, to copy value params, to read or write ref params, and to return?
Are you sure? yes | no
These are indeed very cautionary tales :-)
Since this rant 6 years ago, I've studied the set of desirable and possible "required hardware features" and I have reduced them to a minimal, essential working set that requires the least circuits (no microprogramming) with the least side effects, aiming at efficiency without compromising security.
I have to find time to lay everything out, discuss all the implications, and you're more than welcome to chime in!
Are you sure? yes | no