Last active
March 9, 2025 06:55
-
-
Save joevt/a4ef4cd2e1485d0dd595893007bdfd6a to your computer and use it in GitHub Desktop.
Commands for kexts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # joevt May 8, 2023 | |
| #10.4 Tiger to 10.13 High Sierra | |
| kextload=kextload | |
| # Later macOS versions | |
| command -v kextutil > /dev/null && kextload=kextutil | |
| getkextidentifier () { | |
| local thekextpath="$1" | |
| if [[ ! -f "$thekextpath/Contents/Info.plist" ]]; then | |
| echo "# Missing Info.plist." 1>&2 | |
| return 1 | |
| fi | |
| # Mac OS X 10.4 doesn't have PlistBuddy so just use perl | |
| perl -0777 -n -e 'if (m|<key>CFBundleIdentifier</key>\s*<string>(.+)</string>|) { print $1 }' "$thekextpath/Contents/Info.plist" | |
| } | |
| checkkext () { | |
| local thekextpath="$1" | |
| if [[ -d "$thekextpath" ]]; then | |
| if [[ -f "$thekextpath/Contents/Info.plist" ]]; then | |
| local kextname | |
| kextname="$(basename "$thekextpath")" | |
| if grep -q -E "\.kext$" <<< "$kextname"; then | |
| local kextidentifier="" | |
| kextidentifier="$(getkextidentifier "$thekextpath")" | |
| local theerr=$? | |
| if (( theerr == 0 )); then | |
| return 0 | |
| else | |
| echo "# Missing CFBundleIdentifier." 1>&2 | |
| return 1 | |
| fi | |
| else | |
| echo "# That's not a kext." 1>&2 | |
| return 1 | |
| fi | |
| else | |
| echo "# Missing Info.plist." 1>&2 | |
| return 1 | |
| fi | |
| else | |
| echo "# Expected a kext package directory." 1>&2 | |
| return 1 | |
| fi | |
| } | |
| unloadkext () { | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| local kextname | |
| kextname="$(basename "$thekextpath")" | |
| local kextidentifier | |
| kextidentifier="$(getkextidentifier "$thekextpath")" | |
| echo "# kextname: $kextname" | |
| echo "# kextidentifier: $kextidentifier" | |
| if ( kextstat 2> /dev/null | grep -q "$kextidentifier" ); then | |
| while : ; do | |
| echo "# Unloading ${kextname}." | |
| sudo kextunload -b "$kextidentifier" | |
| ( kextstat 2> /dev/null | grep -q "$kextidentifier" ) || break | |
| sleep 1 | |
| done | |
| echo "# Unloaded ${kextname}." | |
| else | |
| echo "# ${kextname} is not loaded." | |
| fi | |
| } | |
| checkkextpermissions () { | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| badpermissions="$(find "$thekextpath" -exec ls -ld {} \; | sed -E '/drwxr-xr-x.* root *wheel /d ; /-rw.r-.r-..* root *wheel /d')" | |
| if (( $(printf "%s" "$badpermissions" | wc -l) == 0 )); then | |
| return 0 | |
| fi | |
| echo "# Permissions are not correct for the following:" 1>&2 | |
| echo "$badpermissions" 1>&2 | |
| return 1 | |
| } | |
| fixkextpermissions () { | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| if checkkextpermissions "$thekextpath" 2> /dev/null ; then | |
| echo "# Permissions are good. No changes were required." | |
| return 0 | |
| fi | |
| sudo chown -R root:wheel "$thekextpath" | |
| sudo find "$thekextpath" -type d -exec /bin/chmod 0755 {} \; | |
| sudo find "$thekextpath" -type f -exec /bin/chmod 0644 {} \; | |
| if checkkextpermissions "$thekextpath" 2> /dev/null ; then | |
| echo "# Fixed permissions." | |
| return 0 | |
| fi | |
| echo "# Could not fix permissions." 1>&2 | |
| return 1 | |
| } | |
| loadkext () { | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| local kextname | |
| kextname="$(basename "$thekextpath")" | |
| local kextloadpath | |
| if fixkextpermissions "$thekextpath" > /dev/null 2>&1 ; then | |
| kextloadpath="$thekextpath" | |
| else | |
| echo "# Cannot fix permissions. Will load kext from temporary directory." 1>&2 | |
| local kexttmpdir | |
| kexttmpdir="$(mktemp -d /tmp/KextUtil_XXXXXXX)" | |
| kextloadpath="$kexttmpdir/$kextname" | |
| sudo cp -R "$thekextpath" "kextloadpath" | |
| if ! fixkextpermissions "kextloadpath" ; then | |
| return 1 | |
| fi | |
| fi | |
| unloadkext "$kextloadpath" | |
| if ( sudo "$kextload" "$kextloadpath" ); then | |
| echo "# Loaded ${kextname}." | |
| return 0 | |
| else | |
| echo "# $kextname was not loaded." 1>&2 | |
| return 1 | |
| fi | |
| } | |
| mountsystemrw () { | |
| mount | grep ' on / ' | grep -q 'read-only' && sudo mount -uw / | |
| } | |
| installkext () { | |
| local doload=0 | |
| local dosystem=0 | |
| while (( $# )); do | |
| if [[ "$1" == "-l" ]]; then | |
| doload=1 | |
| elif [[ "$1" == "-s" ]]; then | |
| dosystem=1 | |
| else | |
| break | |
| fi | |
| shift 1 | |
| done | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| local kextname | |
| kextname="$(basename "$thekextpath")" | |
| local kextinstalldir="/Library/Extensions" | |
| if ((dosystem)); then | |
| kextinstalldir="/System/Library/Extensions" | |
| fi | |
| local kextidentifier | |
| kextidentifier="$(getkextidentifier "$thekextpath")" | |
| if ((doload)); then | |
| # unloadkext will do these echo lines for us: | |
| # echo "# kextname: $kextname" | |
| # echo "# kextidentifier: $kextidentifier" | |
| unloadkext "$thekextpath" | |
| else | |
| echo "# kextname: $kextname" | |
| echo "# kextidentifier: $kextidentifier" | |
| fi | |
| local kexttmpdir | |
| kexttmpdir="$(mktemp -d /tmp/KextUtil_XXXXXXX)" | |
| kextloadpath="$kexttmpdir/$kextname" | |
| sudo cp -R "$thekextpath" "kextloadpath" | |
| if ! fixkextpermissions "kextloadpath" ; then | |
| return 1 | |
| fi | |
| if [[ -d "/System/Library/Extensions/$kextname" ]]; then | |
| mountsystemrw | |
| sudo rm -R "/System/Library/Extensions/$kextname" | |
| fi | |
| if [[ -d "/Library/Extensions/$kextname" ]]; then | |
| sudo rm -R "/Library/Extensions/$kextname" | |
| fi | |
| if ((dosystem)); then | |
| mountsystemrw | |
| fi | |
| sudo mv "kextloadpath" "$kextinstalldir" | |
| if ((doload)); then | |
| sudo "$kextload" "$kextinstalldir/$kextname" | |
| kextstat 2> /dev/null | grep "$kextidentifier" | |
| fi | |
| } | |
| removekext () { | |
| local thekextpath="$1" | |
| checkkext "$thekextpath" || return 1 | |
| if [[ -d "$thekextpath" ]]; then | |
| if [[ "$thekextpath" == /System/Library/* ]] ; then | |
| mountsystemrw | |
| fi | |
| sudo rm -R "$thekextpath" | |
| fi | |
| } | |
| rebuildkextcache () { | |
| sudo kextcache -i / | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Load the commands into the terminal like this:
source KextUtil.shUtility Functions
These utility functions are used by the main functions listed below.
getkextidentifierkextpathkextstator to unload the kext.checkkextkextpathstderr.checkkextbefore attempting to do anything.checkkextpermissionskextpathstderr.fixkextpermissionsto see if the permissions need to be fixed.fixkextpermissionskextpathloadkext,unloadkext, andinstallkext.Main Functions
loadkextkextpathunloadkextkextpathinstallkext[-s] [-l] kextpath/Library/Extensions. if-sis specified then the install location is/System/Library/Extensions. Do not use-sfor Big Sur and later.-lis specified. It will first unload previously loaded kext if necessary./System/Library/Extensionsif it exists there. It will mount the root volume as read/write if necessary (works in the case of Catalina; for later macOS it is expected that the kext will not be in/System)./Library/Extensionsif it exists there.removekextkextpath/System).Updates
Jun 12, 2024
kextutil.Feb 10, 2024
/Library/Extensionsif it doesn't exist (as in Mac OS X 10.4 Tiger).May 9, 2023
loadkextandinstallkext.checkkext,installkext, andremovekext.May 8, 2023
unloadkext.checkkextpermissionsso thatchownandchmodare not used unnecessarily.fixkextpermissionsnow returns a status if the permissions needed to be fixed but could not be fixed.loadkextwill now load a kext from its current location if possible. It may modify permissions if necessary. It will revert to using a temporary directory if necessary.mountsystemrwfor mounting the/root volume as read write. This is useful for Catalina.removekextnow mounts the root volume as read write if necessary.Jan 31, 2023
-soption forinstallkextto install to/System/Library/Extensions. This is required to load unsigned kexts in OS X 10.9 Mavericks.Jan 6, 2023
Dec 8, 2022