Kernel module won't load: 'Operation not permitted' on Ubuntu 22.04
Your kernel module fails to load with 'Operation not permitted' after a kernel update. This usually means Secure Boot is blocking unsigned modules.
You just updated your Ubuntu 22.04 system. Maybe you ran apt upgrade and got a new kernel. Now you try to load a custom module — maybe a VirtualBox host module, a Wi-Fi driver, or a proprietary GPU driver — and you see this:
sudo modprobe vboxdrv
modprobe: ERROR: could not insert 'vboxdrv': Operation not permitted
Or maybe you get the same error with insmod. The module file is there. Permissions look fine. But the kernel just says no.
What's really happening
The real culprit is Secure Boot. When you update your kernel, the new kernel still has Secure Boot enabled (if your UEFI firmware has it on). But your kernel module isn't signed with a key the firmware trusts. Older kernels might have worked because they were signed at install time. After a kernel update, the new kernel's signature checking is stricter, or the signing key changed.
Secure Boot, when active, only lets signed kernel modules load. Unsigned modules get the 'Operation not permitted' error. It's a security feature — it stops rootkits from loading bad drivers. But if you're trying to load a legit module, it's a pain.
The fix: sign your module with a Machine Owner Key (MOK)
You have two paths. You can disable Secure Boot in your BIOS settings — but that weakens your system's security. I don't recommend it unless you're in a hurry. The better fix is to sign the module with your own key and enroll it with mokutil.
Here's how to do it the right way.
-
Check if Secure Boot is on. Open a terminal and run:
mokutil --sb-stateIf it says
SecureBoot enabled, you're in the right place. If it says disabled, your problem is something else (maybe the module is corrupted or for a different kernel version). -
Install the signing tools. You need
mokutilandopenssl. They're usually already there, but double-check:sudo apt update sudo apt install mokutil opensslAfter this runs, you'll have the tools to create a signing key.
-
Create your own signing key. This step makes a key pair. Run these commands one by one:
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.key -out MOK.crt -nodes -days 3650 -subj "/CN=My Kernel Module Signing Key/" sudo mokutil --import MOK.crtWhen you run the second command, it asks for a password. This is a temporary password for the enrollment process. Pick something you can remember for five minutes. You'll type it again in the next step.
-
Reboot to enroll the key. After you import the key, you need to reboot. The system will show a blue MOK Manager screen during boot. It looks different from normal boot. When you see it:
- Select Enroll MOK
- Then Continue
- Then Yes
- Type the password you set in step 3
- Select Reboot
This only happens once. After that, your key is trusted by the firmware.
-
Sign the kernel module. Now sign the actual module file. Find the module path first. For VirtualBox it's usually
/lib/modules/$(uname -r)/misc/vboxdrv.ko. Then sign it:sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 MOK.key MOK.crt /lib/modules/$(uname -r)/misc/vboxdrv.koReplace the path with your actual module. If you're not sure where it is, run
find /lib/modules/$(uname -r) -name "*.ko" | grep your-module-name.After signing, check it worked:
modinfo /lib/modules/$(uname -r)/misc/vboxdrv.ko | grep sigYou should see something like
signer: My Kernel Module Signing Key. -
Load the module. Now try again:
sudo modprobe vboxdrvIf it loads without errors, you're done. Check with
lsmod | grep vboxdrvto confirm it's running.
What if it still fails?
If the module still won't load after signing, check a few things:
- Is the module for the right kernel version? Run
uname -rand compare to the path you signed. If they don't match, reinstall the module from its source (like DKMS or the driver installer). - Did you enroll the key correctly? Reboot and check with
mokutil --list-enrolled. You should see your certificate's hash. - Is the module still unsigned? Run
hexdump -C /lib/modules/$(uname -r)/misc/your-module.ko | tail. If you seeModule signature appendedat the end, it's signed. If not, the signing command didn't work — maybe the script wasn't found. - Try a different kernel. Sometimes the module just doesn't work with newer kernels. Boot an older kernel from the GRUB menu and see if the module loads there.
That's the whole process. It takes about 10 minutes, but it's solid. I've done this for VirtualBox, NVIDIA drivers, and custom Wi-Fi modules. It works every time if you follow the steps.
Was this solution helpful?