From Kernel Extensions to System Extensions: Why Apple Moved Drivers Out of the Kernel
The architectural reasoning behind Apple's multi-year push to deprecate kernel extensions in favor of user-space System Extensions and DriverKit, and what actually changes when a driver runs outside the kernel.
For most of macOS’s history, third-party drivers — antivirus software hooking into filesystem or network events, VPN clients implementing custom network interfaces, hardware drivers for peripherals — ran as kernel extensions (kexts), loaded directly into the same address space and privilege level as the kernel itself. Apple has spent years pushing developers away from this model entirely, toward System Extensions and DriverKit, which run the equivalent functionality in user space instead.
Why kexts were risky by design, not just by accident
A kernel extension, once loaded, runs with the full privilege and access of the kernel itself — there’s no isolation between a third-party kext’s code and the kernel’s own memory and control structures. This means a bug in a third-party kext (a crash, a memory corruption issue, a race condition) doesn’t just crash that piece of software — it can crash or corrupt the entire operating system, because the kext’s faulty code is executing with unrestricted kernel privilege rather than being contained the way a user-space process’s bugs are contained to that process. Kernel panics traceable to third-party kexts were, for years, one of the more common sources of macOS stability problems that had nothing to do with Apple’s own code.
What System Extensions and DriverKit do differently
System Extensions (covering categories like network extensions, endpoint security, and driver extensions built on DriverKit specifically) run the equivalent functionality as ordinary, isolated user-space processes, communicating with the kernel through well-defined, narrow APIs rather than executing directly inside kernel space. DriverKit specifically provides a user-space framework for writing device drivers — USB, serial, and other peripheral drivers — that historically required kernel-level kexts, now implementable entirely in user space with the kernel exposing only the specific, narrow hardware-access primitives a driver actually needs, rather than full kernel privilege.
Why this actually improves reliability, not just security
The security benefit (a compromised or malicious extension can’t directly control the kernel) is real, but the reliability benefit is arguably just as significant in practice: a bug in a System Extension crashes that extension’s own process, which the operating system can detect and restart, rather than crashing or corrupting the entire kernel. This directly converts what used to be a whole-system kernel panic into an isolated, recoverable single-process crash — the same fundamental benefit that process isolation has always provided for ordinary application crashes, now extended to the driver and low-level extension category that had previously been exempt from it by running in kernel space.
The transition’s actual timeline and pressure
Apple didn’t remove kext support outright in one release — it announced kexts as deprecated well ahead of actually restricting them, giving developers a multi-year runway to migrate to System Extensions/DriverKit equivalents, while gradually tightening the requirements and warnings around loading third-party kexts (including requiring explicit user approval in System Preferences/Settings for any third-party kext to load at all, a meaningfully higher-friction process than kexts had previously required). This staged approach reflects a recurring pattern in how Apple handles platform-level deprecations that would otherwise break a meaningful amount of existing third-party software if done abruptly — announce early, add friction gradually, then eventually restrict or remove.
What this meant for existing third-party software
Vendors of software that had relied on kexts — endpoint security and antivirus vendors being the most affected category, given how deeply that category of software has historically needed to hook into low-level system events — had to substantially rewrite the affected components against the new System Extensions APIs, which don’t offer identical capabilities to what unrestricted kernel-level access provided. Some categories of low-level system hooking that were straightforward from kernel space required entirely different approaches (or, in some cases, simply aren’t achievable at all) from the more restricted user-space System Extensions APIs, which was a genuine source of friction for vendors used to the older model’s flexibility, even as it closed off real attack surface and stability risk in the process.
The broader pattern this reflects
This transition sits alongside several other Apple platform-security moves from roughly the same era — System Integrity Protection restricting what even root can modify, the signed system volume separating the OS itself from user-writable storage, notarization requirements for distributed software — as part of a broader, sustained push to shrink the amount of unrestricted, unsandboxed privilege available anywhere in the system, including to Apple’s own historical extension mechanisms, not just to third-party application code.