Why Catalina may have problems with extensions

There are several reports of problems getting Catalina to accept and load kernel extensions (KEXTs). This article looks briefly at how they can arise, and whether you can do anything about them.

How kernel extensions are loaded

A kernel extension is a fairly fundamental extension to what macOS does, effectively changing or extending what happens deep down inside it. macOS does this itself: in Mojave, for example, Apple provides over 300 of its own kernel extensions, to drive graphics cards, networking, and a great deal more besides. Without kernel extensions, there’d be no macOS.

The original concept of kernel extensions was that they were loaded soon after the kernel started up, and old versions of Mac OS X did that. With only a few dozen to load, this wasn’t a particular burden, and in those days you could watch each kernel extension load, or fail, in the logs. But as their number grew, this made startup unacceptably slow, so Mac OS X started to prelink the kernel with all the extensions it needed to load, into a prelinked kernel. Since then, macOS has started up by loading that instead, which saves a great deal of time.

Kernel extensions are dangerous in several ways. Because they load early during startup (whether one at a time, or prelinked), there aren’t any sophisticated security protections available. Not only that, but they can do things at the very heart of your Mac, which would be incredibly dangerous in malware. Apple has therefore evolved strict security requirements for kernel extensions, which have become even tougher in Catalina.

Catalina’s security mechanisms

For some time now, Apple has required those developing kernel extensions to obtain special security certificates for their KEXTs. In April this year, for Mojave and Catalina, kernel extensions have also had to be notarized, which ensures that Apple has checked each of them for malware as well.

Main security checks therefore have to be performed when you first install a kernel extension. If it was signed from April 2019 onwards but hasn’t been notarized, Mojave and Catalina will refuse to accept it, and although in some circumstances you might be able to work around that (in Mojave at least), in most cases that is and should be a show-stopper. It means the kernel extension hasn’t been checked for malware by Apple, and you simply shouldn’t trust it: contact its developer and remind them of Apple’s security rules.

Even when it has been notarized and passes Catalina’s security checks, you still have to add it using the General tab of the Security & Privacy pane – what Apple terms User-Approved Kernel Extension Loading. Although Catalina tends to bombard you with alerts and prompts when installing and first running some software, this is one of the more important, and needs particular care.

Catalina was to have introduced a further change to the installation of kernel extensions, which required the Mac to restart after the user had approved an extension, before it could be loaded. This was present in most betas, but was removed shortly before 10.15 was released, and it’s unclear whether this applies to the release version, will be re-instated in a future update to Catalina, or has been abandoned altogether. Hopefully Apple will clarify this soon.

Once a kernel extension has been built into the prelinked kernel, the latter needs System Integrity Protection (SIP), to ensure that nothing else can tamper with its contents. In Catalina, that not only means setting permissions and applying SIP, but storing it on the read-only System volume.

Creating and installing a prelinked kernel

Once your newly installed extension is in place, it’s the task of the kextcache command tool to link it with all the other kernel extensions and the kernel itself, and create the prelinked kernel ready for the next time your Mac starts up. Before Catalina’s read-only System volume, this was complex enough, and with the prelinked kernel now stored on that System volume, it gets even more complicated, and prone to failure.

Christian at Objective Development has recently documented in detail how this new system works. There are only two occasions when storing a newly built prelinked kernel on the System volume is feasible: during a macOS update, when the installer has write access to the System volume in order to apply the update, and just before macOS shuts down. The latter works because all other processes have been shut down, and the System volume can then safely be mounted for write access, allowing a shell script shove_kernels to copy the new prelinked kernel into the folder /System/Library/PrelinkedKernels/prelinkedkernel.

What could possibly go wrong?

Objective Development have overcome technical problems which make it almost impossible to see what is going on after macOS stops writing to the unified log and before the kernel shuts down, and discovered that this final step in the process can fail in 10.15 and many earlier beta-releases of Catalina. As a result of their observations, and problems experienced by Little Snitch users with Catalina, they’re currently recommending Catalina users not to try updating Little Snitch until Apple fixes this problem. This is because running a newer version of Little Snitch with an older version of its kernel extension can cause serious conflicts.

It’s currently unclear whether this only applies to updating kernel extensions which have already been installed successfully, or whether problems only occur with some kernel extensions and not others. My own experience is that it is perfectly possible to install completely new kernel extensions successfully in Catalina: I did this with Parallels Desktop in a late beta of 10.15, which Objective Development claims suffered this problem. Given the number of other prominent products which rely on installing kernel extensions, I find it hard to believe that 10.15 can’t update its prelinked kernel at all.

One potential workaround which hasn’t yet been considered, and won’t be possible until the release of 10.15.1, is, after installing a new kernel extension successfully, to install a macOS update which replaces the kernel or any system kernel extensions. As that necessarily forces a new prelinked kernel to be built and installed, it should include the updated kernel extension(s) too.

Relief in sight?

At WWDC 2019 back in June, Apple announced that it wants to move away altogether from third-party kernel extensions, and announced their replacement in the form of System Extensions, which should do away with at least some of these problems. However, so far Apple doesn’t appear to have made much progress in encouraging developers away from kernel extensions. Some developers who have applied for new security certificates with which to sign them haven’t heard anything back from Apple since June, so the delay isn’t with third-party developers.

Maybe it will be a while before we see third-party apps replacing KEXTs with SEXTs after all.