I am posting this here instead of on Stack Overflow because this is more conceptual. I am primarily thinking of this a Linux context, but this can be extended to other operating systems.
When I didn’t know what I know now about operating systems, I figured that iOS applications signature checked by other programs. I was thinking of real time integrity checks, the kind that occur anytime and every time a resource is accessed. My guess was that these “system” programs could deny the execution of applications with invalid signatures, control their access to files, and deny access to improperly signed resources. I figured other code signature checks on other operating systems like Windows worked the same way.
I have since learned that these integrity checks on iOS devices take place in the kernel. All of the ideas for file integrity that I have seen so far for operating systems like Linux and *BSD leverage the kernel to perform the checks. Is it possible to create a system where non-kernel processes could perform the kind of integrity checks I had in mind when I was first introduced to iOS? Would it require a radically different operating system design for this to work?
Interesting question. I am no OS expert, but I know a bit, and here is my two cents.
The filesystem is the component of an OS responsible for performing file integrity checks. In the systems I am familiar with, such as ZFS, files are checksummed, to detect and recover from hardware or software errors. It sounds like you’re referring to signing files with some kind of asymmetric key system, which is considerably more involved, and I am not familiar with how iOS does this. But I would imagine it could be done in userland, and it is done in the kernel merely for performance concerns.
We can divide operating systems into two categories: monolithic kernels and microkernels. As the names suggest, monolithic kernels have a lot more functionality built into the kernel (and that therefore runs in supervisor mode), while microkernels put the bare minimum amount of functionality into the kernel, and run the remainder of the operating system as userland processes. Of course, there is really a spectrum between these two extremes, but the terminology is common.
Examples of functionality that must be run in kernel mode, and are therefore contained in a microkernel, are memory management, interprocess communication, and CPU scheduling (although additional schedulers may be written as user program plugins). Other functionality commonly seen in monolithic kernels, such as device drivers and file systems, can actually be run in userland, and are done so in a microkernel.
So to answer you question: yes, it’s almost certainly possible; but I’d like to hear from someone who knows why iOS chose to implement this functionality in the kernel (my money’s on efficiency).
A popular counter-example (where integrity checks happen in userland, not in kernel) is the git version control system.
It is well known (and I saw several video talks by Linus Torvalds explaining) that
git performs a lot of integrity checks & verifications. It keeps some cryptographic quality hash signature for every blob, and checks them regularly, because one of the features needed in
git is to detect even disk malfunctions on repository data (inside your hidden
.git directory). Linus really wanted
git to be reliable enough to never pollute your checkout files, even in case of hardware failure.