Files
driver-manager/scripts/ko_manager.sh
sssnake b88141a9c5 Driver Manager v2.0.0 - LSPosed-style rewrite
Complete rewrite with:
- Per-app driver scoping via mount namespace isolation (LSPosed-style)
- System-wide driver mode selection
- .ko kernel module manager with autoload and dependency tracking
- Driver integrity protection (monitor/enforce modes)
- Driver registry with auto-discovery and SHA256 hashing
- LSPosed-style dark WebUI with 6 tabs: Dashboard, Drivers, Apps, Modules, Protection, Logs
- RESTful API handler for WebUI communication
- Zygote process monitor for auto-applying scopes to new app launches

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 06:01:07 -07:00

229 lines
7.1 KiB
Bash

#!/system/bin/sh
# Driver Manager v2 - Kernel Module (.ko) Manager
# Load, unload, and manage kernel modules
MODDIR=${MODDIR:-/data/adb/modules/driver-manager}
. "$MODDIR/scripts/core.sh"
log_init "$LOGDIR/ko.log"
MODULESDIR="$MODDIR/modules"
AUTOLOAD="$CONFIGDIR/autoload.conf"
KERNEL_VER=$(uname -r 2>/dev/null)
# --- List available .ko files and their status ---
list_modules() {
echo '{"modules":['
local first=true
# List .ko files in our modules directory
for ko in "$MODULESDIR"/*.ko; do
[ -f "$ko" ] || continue
local name=$(basename "$ko" .ko)
local modname=$(modinfo -F name "$ko" 2>/dev/null || echo "$name")
local desc=$(modinfo -F description "$ko" 2>/dev/null || echo "")
local ver=$(modinfo -F version "$ko" 2>/dev/null || echo "")
local author=$(modinfo -F author "$ko" 2>/dev/null || echo "")
local depends=$(modinfo -F depends "$ko" 2>/dev/null || echo "")
local vermagic=$(modinfo -F vermagic "$ko" 2>/dev/null || echo "")
local sz=$(file_size "$ko")
# Check if loaded
local loaded="false"
lsmod 2>/dev/null | grep -q "^${modname} " && loaded="true"
# Check if in autoload
local autoload="false"
grep -qx "$name.ko" "$AUTOLOAD" 2>/dev/null && autoload="true"
# Check kernel version compatibility
local compatible="unknown"
if [ -n "$vermagic" ]; then
local mod_kver=$(echo "$vermagic" | awk '{print $1}')
[ "$mod_kver" = "$KERNEL_VER" ] && compatible="true" || compatible="false"
fi
[ "$first" = true ] && first=false || echo ","
cat << ENTRY
{
"filename": "$(basename "$ko")",
"name": "$modname",
"description": "$desc",
"version": "$ver",
"author": "$author",
"depends": "$depends",
"vermagic": "$vermagic",
"size": $sz,
"loaded": $loaded,
"autoload": $autoload,
"compatible": $compatible
}
ENTRY
done
echo ']}'
}
# --- Load a kernel module ---
load_module() {
local ko="$1"
local params="$2"
# Accept either filename or path
if [ ! -f "$ko" ]; then
ko="$MODULESDIR/$ko"
fi
if [ ! -f "$ko" ]; then
echo '{"status": "error", "message": "Module file not found"}'
return 1
fi
local name=$(basename "$ko" .ko)
local modname=$(modinfo -F name "$ko" 2>/dev/null || echo "$name")
# Check if already loaded
if lsmod 2>/dev/null | grep -q "^${modname} "; then
echo "{\"status\": \"already_loaded\", \"module\": \"$modname\"}"
return 0
fi
# Check kernel version
local vermagic=$(modinfo -F vermagic "$ko" 2>/dev/null)
if [ -n "$vermagic" ]; then
local mod_kver=$(echo "$vermagic" | awk '{print $1}')
if [ "$mod_kver" != "$KERNEL_VER" ]; then
log_error "Kernel mismatch: module=$mod_kver running=$KERNEL_VER"
echo "{\"status\": \"error\", \"message\": \"Kernel version mismatch: module built for $mod_kver, running $KERNEL_VER\"}"
return 1
fi
fi
# Load dependencies first
local depends=$(modinfo -F depends "$ko" 2>/dev/null)
if [ -n "$depends" ]; then
local IFS=','
for dep in $depends; do
if ! lsmod 2>/dev/null | grep -q "^${dep} "; then
local dep_ko="$MODULESDIR/${dep}.ko"
if [ -f "$dep_ko" ]; then
log "Loading dependency: $dep"
insmod "$dep_ko" 2>> "$LOGDIR/ko.log"
else
log "Dependency $dep not in modules dir, trying modprobe"
modprobe "$dep" 2>> "$LOGDIR/ko.log"
fi
fi
done
fi
# Load the module
log "Loading module: $ko $params"
local output
output=$(insmod "$ko" $params 2>&1)
if [ $? -eq 0 ]; then
log "Loaded: $modname"
# Capture relevant dmesg
local dmesg_out=$(dmesg | tail -5 2>/dev/null)
echo "{\"status\": \"ok\", \"module\": \"$modname\", \"dmesg\": \"$(echo "$dmesg_out" | tr '\n' '|' | sed 's/"/\\"/g')\"}"
else
log_error "Failed to load $modname: $output"
echo "{\"status\": \"error\", \"module\": \"$modname\", \"message\": \"$(echo "$output" | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
return 1
fi
}
# --- Unload a kernel module ---
unload_module() {
local name="$1"
name=$(echo "$name" | sed 's/\.ko$//')
if ! lsmod 2>/dev/null | grep -q "^${name} "; then
echo "{\"status\": \"not_loaded\", \"module\": \"$name\"}"
return 0
fi
log "Unloading module: $name"
local output
output=$(rmmod "$name" 2>&1)
if [ $? -eq 0 ]; then
log "Unloaded: $name"
echo "{\"status\": \"ok\", \"module\": \"$name\"}"
else
log_error "Failed to unload $name: $output"
echo "{\"status\": \"error\", \"module\": \"$name\", \"message\": \"$(echo "$output" | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
return 1
fi
}
# --- Unload all managed modules ---
unload_all() {
log "Unloading all managed modules"
for ko in "$MODULESDIR"/*.ko; do
[ -f "$ko" ] || continue
local name=$(basename "$ko" .ko)
local modname=$(modinfo -F name "$ko" 2>/dev/null || echo "$name")
if lsmod 2>/dev/null | grep -q "^${modname} "; then
rmmod "$modname" 2>/dev/null
log "Unloaded: $modname"
fi
done
echo '{"status": "ok"}'
}
# --- Get detailed info for a module ---
info_module() {
local ko="$1"
if [ ! -f "$ko" ]; then
ko="$MODULESDIR/$ko"
fi
[ ! -f "$ko" ] && { echo '{"error": "not found"}'; return 1; }
modinfo "$ko" 2>/dev/null
}
# --- Toggle autoload for a module ---
set_autoload() {
local ko_filename="$1"
local enabled="$2"
if [ "$enabled" = "true" ] || [ "$enabled" = "1" ]; then
if ! grep -qx "$ko_filename" "$AUTOLOAD" 2>/dev/null; then
echo "$ko_filename" >> "$AUTOLOAD"
log "Autoload enabled: $ko_filename"
fi
echo "{\"status\": \"ok\", \"autoload\": true, \"module\": \"$ko_filename\"}"
else
sed -i "/^${ko_filename}$/d" "$AUTOLOAD" 2>/dev/null
log "Autoload disabled: $ko_filename"
echo "{\"status\": \"ok\", \"autoload\": false, \"module\": \"$ko_filename\"}"
fi
}
# --- Load all autoload modules ---
autoload_modules() {
[ ! -f "$AUTOLOAD" ] && return 0
log "Loading autoload modules"
while IFS= read -r ko; do
[ -z "$ko" ] && continue
[ "${ko#\#}" != "$ko" ] && continue
local kofile="$MODULESDIR/$ko"
if [ -f "$kofile" ]; then
load_module "$kofile" >/dev/null 2>&1
else
log_error "Autoload module not found: $ko"
fi
done < "$AUTOLOAD"
}
# --- Main ---
case "$1" in
list) list_modules ;;
load) load_module "$2" "$3" ;;
unload) unload_module "$2" ;;
unload_all) unload_all ;;
info) info_module "$2" ;;
autoload) autoload_modules ;;
set_autoload) set_autoload "$2" "$3" ;;
*) echo "Usage: ko_manager.sh {list|load|unload|unload_all|info|autoload|set_autoload} [args]" ;;
esac