Skip to content

Commit cdc27b3

Browse files
committed
feat: add support for disabling/enabling kext/sext
1 parent 475f5d8 commit cdc27b3

2 files changed

Lines changed: 129 additions & 13 deletions

File tree

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# maclaunch
33

4-
Lists and controls your macOS startup items and their startup policy.
4+
Lists and controls all your macOS startup items and their startup policy.
55

66
Take back control of your macOS system!
77

@@ -31,8 +31,13 @@ Take back control of your macOS system!
3131

3232
## How does it work?
3333

34-
Lists XML/json/binary plist files in LaunchAgents and LaunchDaemons folders which are loaded by launchctl.
35-
When disabling an item, it uses launchctl to natively stop loading that service.
34+
maclaunch will list 3 distinct types of entries on your macOS system that can be persistently installed:
35+
36+
1. Configuration files for LaunchAgents and LaunchDaemons which are loaded by launchctl.
37+
2. Kernel extensions loaded in the kernel.
38+
3. System extensions loaded in userspace.
39+
40+
When disabling an item, it uses `launchctl`, `kextutil` or `systemextensionsctl` to natively stop loading that service.
3641
It does **not** alter the contents in any way or moves the file, so it should work with practically any service.
3742

3843
The name you provide can either be specific to that service or function as a filter to work on multiple services simultaneously.

maclaunch.sh

Lines changed: 121 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#!/usr/bin/env bash
22

3-
#set -e
4-
#set -x
5-
63
startup_dirs=(/Library/LaunchAgents /Library/LaunchDaemons ~/Library/LaunchAgents ~/Library/LaunchDaemons)
74
system_dirs=(/System/Library/LaunchAgents /System/Library/LaunchDaemons)
85

@@ -12,6 +9,10 @@ YELLOW='\033[1;33m'
129
NC='\033[0m'
1310
BOLD='\033[1m'
1411

12+
#
13+
#--------------------------------------------------------------------------------------------------------------------------------------
14+
#
15+
1516
function join_by { local IFS="$1"; shift; echo "$*"; }
1617

1718
function usage {
@@ -59,7 +60,7 @@ function listKernelExtensions {
5960

6061
getKernelExtensions | while IFS= read -r kextLine; do
6162

62-
kextLoaded=$(echo "$kextLine" | cut -d ' ' -f 3)
63+
kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
6364
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"
6465
kextVersion="$(echo "$kextLine" | grep -o '\((.*)\)')"
6566

@@ -98,6 +99,56 @@ function listKernelExtensions {
9899
done
99100
}
100101

102+
function disableKernelExtensions {
103+
local filter="$1"
104+
105+
getKernelExtensions | while IFS= read -r kextLine; do
106+
107+
kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
108+
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"
109+
110+
if ! [[ "$kextName" =~ $filter ]]; then
111+
continue
112+
fi
113+
114+
if [ "$kextLoaded" == "0" ]; then
115+
#error "kernel extension is already unloaded"
116+
continue
117+
fi
118+
119+
if ! kmutil load -b "$kextName" 1>/dev/null; then
120+
error "could not disable kernel extension"
121+
fi
122+
123+
echo -e "${GREEN}Disabled ${STRONG}${kextName}${NC}"
124+
done
125+
}
126+
127+
function enableKernelExtensions {
128+
local filter="$1"
129+
130+
getKernelExtensions | while IFS= read -r kextLine; do
131+
132+
kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
133+
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"
134+
135+
if ! [[ "$kextName" =~ $filter ]]; then
136+
continue
137+
fi
138+
139+
if ! [ "$kextLoaded" == "0" ]; then
140+
#error "kernel extension is already loaded"
141+
continue
142+
fi
143+
144+
if ! kmutil unload -b "$kextName" 1>/dev/null; then
145+
error "could not disable kernel extension"
146+
fi
147+
148+
echo -e "${GREEN}Enabled ${STRONG}${kextName}${NC}"
149+
done
150+
}
151+
101152
function getSystemExtensions {
102153
systemextensionsctl list 2>/dev/null | tail -n+2 | grep -v '^---' | grep -v '^enabled' | tr -s ' '
103154
}
@@ -111,6 +162,10 @@ function listSystemExtensions {
111162
extName="$(echo "$fullName" | cut -d ' ' -f 1)"
112163
extVersion="$(echo "$fullName" | grep -o '\((.*)\)')"
113164

165+
if [ -n "$filter" ] && ! [[ "$extName" =~ $filter ]]; then
166+
continue
167+
fi
168+
114169
local loaded
115170
if [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
116171
loaded="${ORANGE}enabled${NC}"
@@ -126,7 +181,52 @@ function listSystemExtensions {
126181
done
127182
}
128183

129-
function listItems {
184+
function enableSystemExtensions {
185+
local filter="$1"
186+
187+
getSystemExtensions | while IFS= read -r extLine; do
188+
189+
extName="$(echo "$extLine" | cut -d$'\t' -f 4 | cut -d ' ' -f 1)"
190+
191+
if ! [[ "$extName" =~ $filter ]]; then
192+
continue
193+
fi
194+
195+
if [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
196+
# error "this system extension is already enabled"
197+
continue
198+
fi
199+
200+
#TODO: implement load system extension via CLI
201+
error "enabling system extensions is not yet implemented"
202+
done
203+
}
204+
205+
function disableSystemExtensions {
206+
local filter="$1"
207+
208+
getSystemExtensions | while IFS= read -r extLine; do
209+
210+
extName="$(echo "$extLine" | cut -d$'\t' -f 4 | cut -d ' ' -f 1)"
211+
212+
if ! [[ "$extName" =~ $filter ]]; then
213+
continue
214+
fi
215+
216+
if ! [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
217+
# error "this system extension is already disabled"
218+
continue
219+
fi
220+
221+
if ! systemextensionsctl uninstall '-' "$extName"; then
222+
error "could not disable system extension"
223+
fi
224+
225+
echo -e "${GREEN}Enabled ${STRONG}${extName}${NC}"
226+
done
227+
}
228+
229+
function listLaunchItems {
130230
local filter="$2"
131231

132232
itemDirectories=("${startup_dirs[@]}")
@@ -262,7 +362,7 @@ function listItems {
262362
done< <(find "${itemDirectories[@]}" -type f -iname '*.plist*' -print0 2>/dev/null)
263363
}
264364

265-
function enableItems {
365+
function enableLaunchItems {
266366
disabled_items="$(launchctl print-disabled user/"$(id -u)")"
267367

268368
while IFS= read -r -d '' startupFile; do
@@ -296,7 +396,7 @@ function enableItems {
296396
done< <(find "${startup_dirs[@]}" "${system_dirs[@]}" \( -iname "*$1*.plist" -o -iname "*$1*.plist.disabled" \) -print0 2>/dev/null)
297397
}
298398

299-
function disableItems {
399+
function disableLaunchItems {
300400
disabled_items="$(launchctl print-disabled user/"$(id -u)")"
301401

302402
while IFS= read -r -d '' startupFile; do
@@ -330,6 +430,10 @@ function disableItems {
330430
done< <(find "${startup_dirs[@]}" "${system_dirs[@]}" \( -iname "*$1*.plist" -o -iname "*$1*.plist.disabled" \) -print0 2>/dev/null)
331431
}
332432

433+
#
434+
#--------------------------------------------------------------------------------------------------------------------------------------
435+
#
436+
333437
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
334438
usage
335439
fi
@@ -341,22 +445,29 @@ case "$1" in
341445
usage
342446
fi
343447
fi
344-
listItems "$1" "$2"
448+
listLaunchItems "$1" "$2"
345449
listKernelExtensions "$2"
346450
listSystemExtensions "$2"
347451
;;
452+
348453
"disable")
349454
if [ $# -ne 2 ]; then
350455
usage
351456
fi
352-
disableItems "$2"
457+
disableLaunchItems "$2"
458+
disableKernelExtensions "$2"
459+
disableSystemExtensions "$2"
353460
;;
461+
354462
"enable")
355463
if [ $# -ne 2 ]; then
356464
usage
357465
fi
358-
enableItems "$2"
466+
enableLaunchItems "$2"
467+
enableKernelExtensions "$2"
468+
enableSystemExtensions "$2"
359469
;;
470+
360471
*)
361472
usage
362473
;;

0 commit comments

Comments
 (0)