System calls such as sigaction must take arguments that are data structures in userland. In that case you fill a userland buffer and pass a pointer to it to the kernel. If anything about this data needs to be checked before it can be safely acted upon by the kernel, a risk arises: what if the data is changed by another user thread *after* it's been checked but before it's acted upon? The change can be a malicious one, intended to slip in to the kernel code exactly the kind of thing that kernel's checking is supposed to protect against. For this reason, the general solution is to *only* use the userland pointer to copy the argument data struct into kernel space, and only then check the copied data, never acting on its copy left in userspace. So messing with that data will get the attacker nothing. Observe this pattern in http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/syscall/sigaction.c#42: actp is a userland pointer, only referenced in copyin() l.#63; the rest of accesses are to the kernel-land act, which copyin() fills. Similarly, the userland oactp is only used in copyout(). Illumos' way of copying the data is copyin()/copyout(), Linux's copy_from_user()/copy_to_user() [cf. http://www.ibm.com/developerworks/library/l-kernel-memory-access/] This discipline of working aroung userland pointers seems simple, but bugs like http://keenlab.tencent.com/en/2017/01/09/Racing-for-everyone-descriptor-describes-TOCTOU-in-Apple-s-core/ are still found in modern systems! To check for such bugs automatically, Linux goes further than Illumos and introduces a special type attribute "__user" to be checked by automatic tools (such as sparce) when building the kernel. Compare: http://src.illumos.org/source/xref/linux-master/kernel/signal.c#3314 both act and oact pointers have the __user attribute, used as described in http://stackoverflow.com/questions/4521551/what-are-the-implications-of-the-linux-user-macro --------------------------------------------------------------------------- Think of this issue from the hardware angle. In the x86 rings model of security, Ring0 code is empowered to read any data at lower rings, including the userland Ring3---but should it, really? It may be as bad for the kernel to consume userland data as for the userland code to overwrite kernel data. For this reason, the GrSec/PaX Linux kernel hardening patch trapped accesses from Ring0 to Ring3 except from a number of whitelisted locations in code. Here is a story of the original design: https://grsecurity.net/~spender/uderef.txt and a sketch of using the new x86 features called SMEP/SMAP: https://forums.grsecurity.net/viewtopic.php?f=7&t=3046 GrSec/PaX team also was the first to introduce ASLR into a production system---years before Microsoft picked it up for Windows.