6 ms·
Doesn't the kernel control CPU access?
by herpderperator 5y ago
Doesn't the kernel control CPU access?
- kevingadd 5y agoRegisters aren't resources you access through syscalls, there's no way for the kernel to control them unless you're running under virtualization or the CPU architecture specifically allows access control for the register. (As the site notes, virtualization allows controlling access to this register)
- kolbusa 5y agoCan kernel scan each page it maps as executable and return an error if it finds instructions interacting with the 'bad' register? Assuming the kernel requires executable pages to be read-only (W^X), this may even be doable (but probably very very slow).
- josephcsible 5y ago> Assuming the kernel requires executable pages to be read-only (W^X) Which macOS's kernel doesn't.
- marcan_42 5y agoIt does require that, but it allows flipping between RX and RW at will (for JITs), and the M1 actually has proprietary features to allow userspace to do this without involving the kernel, so the kernel couldn't re-scan when those flips happen (plus it would kill performance anyway). Plus, as I said above, this is prone to false positives anyway because the executable section on ARM also includes constant pools.
- josephcsible 5y agoCan't a MAP_JIT region be writable by one thread and executable by a different thread at the same time?
- anyfoo 5y agohttps://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon https://developer.apple.com/documentation/apple-silicon/port...
- josephcsible 5y agoThat link confirms that it can: > Because pthread_jit_write_protect_np changes only the current thread’s permissions, avoid accessing the same memory region from multiple threads. Giving multiple threads access to the same memory region opens up a potential attack vector, in which one thread has write access and another has executable access to the same region.
- marcan_42 5y agoAh, yes, I forgot about that. So indeed there is no non-racy hook point for the kernel to do such a check, even if it made sense and the RX/RW switch went through the kernel, which it doesn't.
- marcan_42 5y agoThe kernel doesn't get a say in what instructions a userspace program can run, other than what the CPU is designed to allow it to control. The bug is the CPU designers forgot to allow it to control this one.
- saagarjha 5y agoApple could "mitigate" this by refusing to sign code interacting with s3_5_c15_c10_1, I guess.
- josephcsible 5y agoDoesn't Rice's theorem mean that they cannot?
- cokernel_hacker 5y agoI believe that Rice's theorem is about computability, not about whether or not it is possible to validate which CPU instructions a program can contain. With certain restrictions, it is possible to do this: Google Native Client [1] has a verifier which checks that programs it executed did not jump into the middle of other instructions, forbade run-time code generation inside of such programs, etc. [1]: https://en.wikipedia.org/wiki/Google_Native_Client https://en.wikipedia.org/wiki/Google_Native_Client
- josephcsible 5y agoYes, but then you're not just blocking instructions that touch s3_5_c15_c10_1; you're also blocking a bunch of other kinds of instructions too.
- anyfoo 5y ago(What other kinds of instructions? Genuinely asking.) I don't think Rice's Theorem applies here. As a counterexample: On a hypothetical CPU where all instructions have fixed width (e.g. 32 bits), if accessing a register requires the instruction to have, say, the 10th bit set, and all other instructions don't, and if there is no way to generate new instructions (e.g. the CPU only allows execution from ROM), then it is trivial to check whether there is any instruction in ROM that has bit 10 set. The next part I'm less sure how to state it rigorously (I'm not in the field): In our hypothetical CPU, I think disallowing that instruction either lets you remain being Turing Complete or not. In the former case, it's still the case that you can compute everything a Turing Machine can.
- CGamesPlay 5y agoThere's more specific answers here, but in general the answer to this question is "only partly". The kernel is what initially gives your process a time slice on the CPU, by setting an alarm for the CPU to return control to the kernel at the end of the time slice, and then just jumping into your code. During your time slice, you can do anything you want to the CPU, and in general only interrupts (timer interrupts, hardware interrupts, page faults, etc) will cause the kernel to get involved again. There are some specific features that CPU designers add to give extra control to the kernel, but that's a feature of the CPU and it's only when the CPU has explicitly added that type of control.
- saagarjha 5y ago> The kernel is what initially gives your process a time slice on the CPU, by setting an alarm for the CPU to return control to the kernel at the end of the time slice, and then just jumping into your code. Somewhat critically, it will also drop down to EL0.