Kernel Module Loading Fails: "operation not permitted"
Tried loading a kernel module and got "operation not permitted". Here's the fix and why it happens.
Yeah, that "operation not permitted" error when you run modprobe or insmod is annoying. You've done everything right — the module file exists, permissions are fine — but the kernel just says no. Let's fix it.
The Fix
The real cause here is either Secure Boot or the kernel lockdown feature. Both block unsigned modules from loading. Here's the fix that works 90% of the time:
- Check if Secure Boot is enabled. Run:
If it says "SecureBoot enabled", that's the problem.mokutil --sb-state - Disable Secure Boot from your BIOS/UEFI settings. Each motherboard is different, but look for Secure Boot under the Boot or Security tab. Disable it, save, and reboot.
- After reboot, check again:
It should say "SecureBoot disabled".mokutil --sb-state - Try loading your module again:
sudo modprobe your_module_name
If that still fails, check the kernel lockdown status:
cat /sys/kernel/security/lockdown
If it says "integrity" or "confidentiality", the kernel is locked down. On most distros, disabling Secure Boot also lifts this lockdown. But some distros (like Fedora 38 with certain configs) keep lockdown even without Secure Boot. You can temporarily relax it with:
sudo sh -c 'echo 1 > /sys/kernel/security/lockdown'
But that's not permanent. For a real fix, you'll need to sign your module or rebuild the kernel without lockdown.
Why This Happens
What's actually happening here is the kernel's security policy. Secure Boot verifies that only signed bootloaders and kernels run. But then the kernel also checks signatures of modules it loads. If a module isn't signed with a key trusted by the kernel, it refuses — and gives you the generic "operation not permitted" error (code -1).
The kernel lockdown feature goes further. Even if Secure Boot is off, lockdown blocks any operation that could let you access kernel memory directly or load unsigned code. Some distros enable lockdown by default — Ubuntu 22.04 does this if Secure Boot was ever enabled, even after you disable it in BIOS, because the kernel's lockdown state is stored separately.
That's why step 2 works: turning off Secure Boot in BIOS stops the kernel from entering lockdown in the first place. But if your distro's boot loader (like shim) passes the lockdown flag anyway, you'll still hit the error.
Less Common Variations
1. Signed Modules Only
Some distros (like RHEL 9, CentOS Stream) ship kernels that only load signed modules. Period. Even with Secure Boot off. You get the same error. The fix is to sign your module with the Machine Owner Key (MOK).
Steps to sign:
- Generate a key pair:
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj "/CN=My Module Key/" - Enroll the key with
mokutil:
You'll be asked for a password. Use it temporarily.sudo mokutil --import MOK.der - Reboot. The Shimm boot manager will ask you to enroll the key. Do it.
- Sign your module:
sudo /usr/src/kernel-headers-$(uname -r)/scripts/sign-file sha256 MOK.priv MOK.der your_module.ko - Load it:
sudo modprobe your_module_name
2. Module Compilation Issues
Sometimes "operation not permitted" is a red herring. The real error is in the kernel log. Check dmesg | tail right after the failed modprobe. You might see:
module: module verification failed: signature and/or required key missing - tainting kernel
That's the same signature issue. But you might also see:
module: loading module with unknown symbol: symbol_name
That means your module was compiled against different kernel headers than the running kernel. Recompile it with make -C /lib/modules/$(uname -r)/build and try again.
3. SELinux or AppArmor Blocking Module Loading
Rare, but possible. If you're on Fedora or RHEL with SELinux in enforcing mode, module loading can be blocked. Check ausearch -m avc -ts recent for denials. If you see something about insmod or modprobe, you can set a boolean:
sudo setsebool -P module_load 1
On Ubuntu with AppArmor, check aa-status. If a profile blocks module loading, you'll see it in the logs. You can disable that profile temporarily (not recommended for production).
Prevention
To stop this from happening again, do one of these:
- Disable Secure Boot permanently in BIOS if you plan to load custom modules regularly. Just don't expect it to be set back on if you ever need to boot a signed-only distro.
- Sign your modules using MOK. This keeps Secure Boot on and your system secure. It's more work upfront but saves headaches later.
- Use DKMS (Dynamic Kernel Module Support). DKMS can auto-sign modules if you set up MOK enrollment. Install DKMS, add your module's source, and it handles the rest. On Ubuntu:
sudo apt install dkms. Thensudo dkms add /path/to/module-source. - Check your distro's policy. Some distros (like Fedora) enable lockdown by default. Read the release notes for your version. On Fedora 38 and later, you can disable lockdown by adding
lockdown=noneto the kernel command line in GRUB. Edit/etc/default/grub, add it toGRUB_CMDLINE_LINUX, then runsudo grub2-mkconfig -o /boot/grub2/grub.cfg. Reboot.
That's it. No magic, no fluff. The kernel is just doing what it's told. You just need to tell it to trust your module.
Was this solution helpful?