3 ms·
Machine code running in unprivileged mode with no shared memory and where syscalls auto-fail can do nothing malicious. Such a system is even more locked down th
by Veserv 3y ago
Machine code running in unprivileged mode with no shared memory and where syscalls auto-fail can do nothing malicious. Such a system is even more locked down than a Java program (when it does not also rely on hardware isolation) with no access to the filesystem class.
To break the JVM protection boundary and access the filesystem only requires finding a JVM runtime breach or a vulnerable library to access the otherwise inaccessible filesystem class.
To break the hardware isolation requires finding a hardware bug in the protection boundary which is vastly less common to the point where I am not even sure there has even been a hardware cross-privilege data integrity bug in over a decade.
The examples you keep providing are not apples-to-apples as you keep comparing locked down source level programs against ensembles of machine code programs plus unrestricted access to a insecure operating system runtime. Every error you highlight in the machine-code system is actually a operating system/runtime problem, not a problem with machine code as a software delivery mechanism.
- James_K 3y ago> To break the JVM protection boundary and access the filesystem only requires finding a JVM runtime breach or a vulnerable library to access the otherwise inaccessible filesystem class. CPUs also have bugs in them, and those are much harder to patch. Practically speaking, I think it is more likely for a CPU bug to be found than for a Java program to do what you describe here. The prospect of a vulnerable library seems the most likely avenue of attack, but under my proposed system, not even libraries would have access the the file-system. > Machine code running in unprivileged mode with no shared memory and where syscalls auto-fail can do nothing malicious I'm fairly sure it can do nothing, so while that technically satisfies the objective, I don't think it really matches the spirit of the assignment. Then if you want to re-introduce the file-system to such a process, your options are much more complex than they would be in the Java case. You can write some Java code that doesn't interact with the file system at all, then pass objects representing files (i.e. streams) into it. The result is absolute fine-grained control over what the process can access because it is not relying on any kind of shared state. All the information it uses is passed into it. This is much easier than attempting to containerise an existing executable, which requires support from the operating system (and also technically support from the hardware). My core point here is that the software solution to security simply works better than a hardware one. It seems to me that pure functions provide the ultimate form of containerisation, and do so in an immediately intuitive way.
- Veserv 3y agoCPU bugs are extremely rare compared to software bugs. Like, millions to billions of times less likely. CPU bugs are news, software bugs are Tuesday. You might as well argue that a steel box protects its contents no better than a cardboard box because who knows, maybe a meteor will land on the box so steel is no better than cardboard. You can not just dismiss factors of millions on feelings. Again, you are talking about machine code plus OS ensembles. The machine code can not access a filesystem or files unless the OS allows it just like your Java example. You can pass precisely a file or stream to your program if your OS supports such a notion. Even Linux, as insecure as it is, can express your notion of streams with pipes to input files. The insecurity of machine code on Linux is an artifact of OS design providing things like an innate right for processes to access a file system, not anything to do with the machine code. Containerisation does not provide a security boundary and is difficult because the OS design and the programs targeting that OS API are not designed to operate in that way. Such a program would not operate correctly in your Java model either because the program only functions when there is a global filesystem conforming to the implicit requirements of the programs. As soon as you modify that program to operate correctly according to your model it then becomes trivial to precisely provide the same dependencies to the machine code variant as long as your OS supports such abstractions. Every single abstraction you are describing can be expressed as a OS concept at the cost of performance. An argument can be made that the performance impacts are too high, so commercial designs sacrifice protection and that by supporting language-level protections you recover enough performance to enable secure designs. But, in that case you would expect proof-of-concepts demonstrating feasibility and proven protection in the equivalent, but non-performant model, and only then optimizing the performance by leveraging language-level protections. Until that is done there is precisely zero reason to believe any language-level protections are robust. To say it again, language-level protections are strictly more powerful than OS/machine code level protections. If you can prove them then you can trivially prove any OS level protection by jus allowing less fine separation. If you can not demonstrate weaker results like a unhackable OS design, then you do not have a robust language-level solution. It is like proving P != NP without proving something easier like P != PSPACE. Language level solutions would be awesome, but they are not a stepping stone to protection, they are the end result once you have already mastered security.