According to TN2459
Approved KEXTs are tracked in a system-wide policy database through the team identifier in the KEXT's code signature and the bundle identifier from the KEXT's Info.plist, so updating a KEXT that has already been approved will not trigger a new approval request.
This database (at least until Mojave) is /var/db/SystemPolicyConfiguration/KextPolicy and you can update it with sqlite3 after disabling SIP.
A1398% csrutil status
System Integrity Protection status: disabled.
A1398% sudo sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE settings ( name TEXT, value TEXT, PRIMARY KEY (name) );
CREATE TABLE kext_load_history_v3 ( path TEXT PRIMARY KEY, team_id TEXT, bundle_id TEXT, boot_uuid TEXT, created_at TEXT, last_seen TEXT, flags INTEGER , cdhash TEXT);
CREATE TABLE kext_policy ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, developer_name TEXT, flags INTEGER, PRIMARY KEY (team_id, bundle_id) );
CREATE TABLE kext_policy_mdm ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, payload_uuid TEXT, PRIMARY KEY (team_id, bundle_id) );
sqlite>
It contains 4 tables of which only kext_policy and kext_load_history_v3 are interesting (unless you use mdm presumably). For example these are my authorised kext:
sqlite> select * from kext_policy;
VBG97UB4TA|com.objective-see.lulu|1|Objective-See, LLC|1
Z3L495V9L4|com.intel.driver.EnergyDriver|1|Intel Corporation Apps|1
|com.rugarciap.DisableTurboBoost|1|Legacy Developer: Rugarciap|1
MLZF7K7B5R|at.obdev.nke.LittleSnitch|1|Objective Development Software GmbH|1
54GTJ2AU36|com.joshuawise.kexts.HoRNDIS|1|Joshua Wise|1
6HB5Y2QTA3|com.hp.kext.io.enabler.compound|1|HP Inc.|0
sqlite>
If you wanted to delete all of them you could use delete from kext_policy;
then to be tidy delete from kext_load_history_v3;
Alternatively you can delete a specific one by comparing one of the fields shown by the .schema
command. For example to delete LittleSnitch based on the second field bundle_id;
sqlite> delete from kext_policy where bundle_id = "at.obdev.nke.LittleSnitch";
sqlite> delete from kext_load_history_v3 where bundle_id = "at.obdev.nke.LittleSnitch";
sqlite> select * from kext_policy;
VBG97UB4TA|com.objective-see.lulu|1|Objective-See, LLC|1
Z3L495V9L4|com.intel.driver.EnergyDriver|1|Intel Corporation Apps|1
|com.rugarciap.DisableTurboBoost|1|Legacy Developer: Rugarciap|1
54GTJ2AU36|com.joshuawise.kexts.HoRNDIS|1|Joshua Wise|1
6HB5Y2QTA3|com.hp.kext.io.enabler.compound|1|HP Inc.|0
sqlite> .quit
I notice that this answer on stackoverflow suggests it may be necessary also to reset PRAM. Resetting PRAM automatically reenables SIP and as it is easier than booting into recovery is worth doing.
It is possible to do this using a GUI if preferred. After disabling SIP:
- Download and install DB Browser for SQLite
- Launch from terminal with
sudo /Applications/DB\ Browser\ for\ SQLite.app/Contents/MacOS/DB\ Browser\ for\ SQLite
- Open Database /var/db/SystemPolicyConfiguration/KextPolicy (press ⇧⌘. to show hidden files).
- On Browse Data tab in kext_policy table, right click and delete row(s) containing unwanted kexts. Here I'm deleting kext for LuLu firewall.
- Change table to kext_load_history_v3 and delete corresponding rows.
- Click on Write Changes
- Reboot and reset PRAM (⌘-⌥-P-R) which will reenable SIP automatically with no need to boot back into recovery.
- After reboot a System Extension Blocked message is received for the kext whose records were deleted:
- Allowing software from the developer in System Preferences updates the KextPolicy database and then further reboots are back to normal.