mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:07:04 +01:00
Extract android_guardian; heavy_job_lock goes to its installer
github.com/kuhyx/android-guardian, cloned to ~/android-guardian
periodic_background/utils/ held two unrelated things: the Magisk module
and heavy_job_lock.sh. Only the module was a unit, so the directory is
split rather than moved.
heavy_job_lock.sh goes to digital_wellbeing/, NOT to ~/utils. Measured
rather than assumed: of its consumers only install_pacman_wrapper.sh
reads the repo copy, while pacman_wrapper.sh, makepkg_capped.sh and
meta/scripts/run_with_heavy_lock.sh all read the installed
/usr/local/bin copy. A library belongs with whoever installs it, and
exporting it would have added a cross-repo edge for one caller.
Fixed a bug that predates the extraction: update_android_hosts.sh set
GUARDIAN_MODULE_DIR to "$SCRIPT_DIR/android_guardian", a sibling that
never existed at that path -- packaging could not have worked from this
checkout at all. It now reads ${ANDROID_GUARDIAN_DIR:-~/android-guardian}
and require_guardian_module() gates build_module(), the single funnel
every packaging path goes through, so a missing checkout names the clone
command instead of failing inside a cp four helpers deep.
Verified both directions: with no checkout the guard fires with
instructions; with one, the module builds -- 182331 blocked domains, a
1.1 MB zip. The subsequent adb push failed on device-side storage, which
this commit does not touch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
This commit is contained in:
parent
a1f8044a4a
commit
fe8629e104
2
.github/workflows/shell-tests.yml
vendored
2
.github/workflows/shell-tests.yml
vendored
@ -26,8 +26,6 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tests=(
|
||||
test_android_guardian_post_fs_data.sh
|
||||
test_android_guardian_service.sh
|
||||
test_i3blocks_persist_common.sh
|
||||
test_music_parallelism.sh
|
||||
test_setup_dns_blocker.sh
|
||||
|
||||
@ -30,7 +30,9 @@ Extracted to their own repos: [`steam-backlog-enforcer`](https://github.com/kuhy
|
||||
[`focus-owner`](https://github.com/kuhyx/focus-owner),
|
||||
[`mtk-root`](https://github.com/kuhyx/mtk-root),
|
||||
[`system-maintenance`](https://github.com/kuhyx/system-maintenance) (lives at
|
||||
`~/system-maintenance`).
|
||||
`~/system-maintenance`),
|
||||
[`android-guardian`](https://github.com/kuhyx/android-guardian) (lives at
|
||||
`~/android-guardian`).
|
||||
Archived work: [`testsAndMisc-archive`](https://github.com/kuhyx/testsAndMisc-archive).
|
||||
|
||||
## Adding a Flutter app
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"title": "Extract android_guardian and settle the heavy_job_lock seam",
|
||||
"objective": "Move the Magisk module to its own public repo. The directory it lived in also held heavy_job_lock.sh, a shared lock library that is NOT part of the module, so this extraction has to split the directory rather than move it wholesale. It also inherits a packaging script whose module path was already broken before the extraction.",
|
||||
"acceptance_criteria": [
|
||||
"The module and both its test suites are in the new public repo, tests passing from a clean clone, shellcheck exiting 0 with no severity filter.",
|
||||
"heavy_job_lock.sh lands where its installer is, justified by measuring which consumers read the repo copy versus the installed /usr/local/bin copy - not by the ad-hoc '>2 consumers' rule.",
|
||||
"install_pacman_wrapper.sh's relative path to heavy_job_lock.sh resolves after the move.",
|
||||
"update_android_hosts.sh points at a real location, and a missing checkout fails with an actionable message at a single funnel rather than a bare cp error deep in a helper.",
|
||||
"The module still builds end-to-end from the new checkout.",
|
||||
"shell-tests.yml names no removed suite; the coverage allowlist names no removed path.",
|
||||
"periodic_background/utils/ is fully emptied, not left as a one-file directory.",
|
||||
"pre-commit passes without --no-verify."
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Moving heavy_job_lock.sh to ~/utils: the measurement does not support it, and every consumer but the installer already reads the installed copy.",
|
||||
"The adb push half of update_android_hosts.sh, which needs a device in a writable state.",
|
||||
"digital_wellbeing itself, which is the next and last extraction."
|
||||
],
|
||||
"verifier": "bash tests/*.sh in the new repo passes; shellcheck exits 0 there; ANDROID_GUARDIAN_DIR=/nonexistent produces the guard message; a real run builds the zip (182331 domains); shellcheck and check_shell_coverage.sh --all clean here; check_directory_depth.sh --all continues to fall."
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
{
|
||||
"intent": "Extract the android_guardian Magisk module into its own public repo, settle where heavy_job_lock.sh belongs, and fix a pre-existing broken path in the packaging script rather than carrying it forward.",
|
||||
"scope": [
|
||||
"periodic_background/utils/android_guardian/ (5 files) -> github.com/kuhyx/android-guardian as module/, cloned to ~/android-guardian",
|
||||
"Its two test suites in linux_configuration/tests/ moved with it",
|
||||
"heavy_job_lock.sh moved to digital_wellbeing/, its only installer - NOT to ~/utils",
|
||||
"update_android_hosts.sh + lib/android_module.sh repointed and guarded",
|
||||
"shell-tests.yml, shell-coverage-allowlist.txt cleaned",
|
||||
"periodic_background/utils/ is now empty and removed"
|
||||
],
|
||||
"changes": [
|
||||
"Extracted the module and both suites in one filter-repo pass (4 commits), renaming the module directory to module/ and fixing the test paths that named the old monorepo location.",
|
||||
"Moved heavy_job_lock.sh into digital_wellbeing/ instead of ~/utils. Measured: of its consumers, only install_pacman_wrapper.sh reads the repo copy; pacman_wrapper.sh, makepkg_capped.sh and meta/scripts/run_with_heavy_lock.sh all read the installed /usr/local/bin path. It belongs with its installer.",
|
||||
"Fixed a pre-existing bug: update_android_hosts.sh set GUARDIAN_MODULE_DIR to $SCRIPT_DIR/android_guardian, a sibling directory that never existed at that path, so packaging could not have worked from this checkout. It now reads ${ANDROID_GUARDIAN_DIR:-$HOME/android-guardian}/module.",
|
||||
"Added require_guardian_module() and called it from build_module(), the single funnel every packaging path goes through, so a missing checkout fails with an actionable message instead of a bare 'cp: cannot stat' four helpers deep."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "bash tests/*.sh (extracted repo)",
|
||||
"result": "pass",
|
||||
"evidence": "Both suites pass after the path rewrite; shellcheck exits 0 over every script with .shellcheckrc carried across."
|
||||
},
|
||||
{
|
||||
"command": "ANDROID_GUARDIAN_DIR=/nonexistent bash update_android_hosts.sh install",
|
||||
"result": "pass",
|
||||
"evidence": "Stops at the guard with the clone command and the override variable named, rather than failing inside cp."
|
||||
},
|
||||
{
|
||||
"command": "bash update_android_hosts.sh install (with ~/android-guardian cloned)",
|
||||
"result": "pass",
|
||||
"evidence": "Module built: 182331 blocked domains, a 1149321-byte zip. It then failed at `adb push` with 'remote couldn't create file' - a device-side storage condition, not a path problem, and the build half is what this change touches."
|
||||
},
|
||||
{
|
||||
"command": "shellcheck on both edited scripts; check_shell_coverage.sh --all",
|
||||
"result": "pass",
|
||||
"evidence": "Both clean, exit 0."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"The adb push step was not verified end-to-end: the device refused to create the file on /sdcard. That path is unchanged by this commit, but it does mean the full install flow is unproven today.",
|
||||
"update_android_hosts.sh now depends on a sibling checkout. It fails loudly with instructions rather than silently, which is the tradeoff taken.",
|
||||
"heavy_job_lock.sh now sits inside digital_wellbeing, so it will move again when that subsystem is extracted; install_pacman_wrapper.sh's relative path was updated to match and stays correct through that move."
|
||||
],
|
||||
"rollback": [
|
||||
"git revert to restore the module, both tests and heavy_job_lock.sh's old location.",
|
||||
"Re-run check_shell_coverage.sh --all and the two suites to confirm the restored state."
|
||||
]
|
||||
}
|
||||
@ -41,7 +41,7 @@ WHITELIST_SOURCE="$(dirname "$0")/pacman_whitelist.txt"
|
||||
GREYLIST_SOURCE="$(dirname "$0")/pacman_greylist.txt"
|
||||
MAKEPKG_CAPPED_SOURCE="$(dirname "$0")/makepkg_capped.sh"
|
||||
MKPKG_SOURCE="$(dirname "$0")/mkpkg.sh"
|
||||
HEAVY_LOCK_SOURCE="$(dirname "$0")/../../utils/heavy_job_lock.sh"
|
||||
HEAVY_LOCK_SOURCE="$(dirname "$0")/../heavy_job_lock.sh"
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
WRAPPER_DEST="${INSTALL_DIR}/pacman_wrapper"
|
||||
LOCK_LIB_DEST="${INSTALL_DIR}/pacman_lock_lib.sh"
|
||||
|
||||
@ -1,206 +0,0 @@
|
||||
# Android Guardian - Blocked Apps List
|
||||
# One package name per line
|
||||
# Lines starting with # are comments
|
||||
|
||||
# ===== Food Delivery Apps =====
|
||||
# Uber Eats
|
||||
com.ubercab.eats
|
||||
com.ubercab
|
||||
|
||||
# Glovo
|
||||
com.glovo
|
||||
com.glovo.courier
|
||||
|
||||
# Wolt
|
||||
com.wolt.android
|
||||
|
||||
# Bolt Food / Bolt
|
||||
com.bolt.deliveryclient
|
||||
ee.mtakso.client
|
||||
ee.mtakso.food
|
||||
ee.mtakso
|
||||
|
||||
# Pyszne.pl / Takeaway
|
||||
com.takeaway.android
|
||||
com.pyszne.pl
|
||||
com.takeaway.android.pl
|
||||
|
||||
# Jush (Polish quick delivery)
|
||||
pl.jush.app
|
||||
pl.jush.android
|
||||
|
||||
# Delio (Polish delivery)
|
||||
pl.delio.app
|
||||
pl.delio.android
|
||||
com.delio.app
|
||||
|
||||
# Lisek (Polish quick delivery)
|
||||
pl.lisek.app
|
||||
com.lisek.app
|
||||
|
||||
# Stava (Polish delivery)
|
||||
pl.stava.app
|
||||
|
||||
# Barbora (Polish grocery delivery)
|
||||
pl.barbora.app
|
||||
com.barbora.pl
|
||||
|
||||
# Frisco (Polish grocery delivery)
|
||||
pl.frisco.app
|
||||
com.frisco.android
|
||||
|
||||
# Szama (Polish food delivery)
|
||||
pl.szama.app
|
||||
|
||||
# Biedronka online grocery
|
||||
pl.biedronka.app
|
||||
com.jeronimo.biedronka
|
||||
|
||||
# DoorDash
|
||||
com.dd.doordash
|
||||
|
||||
# Grubhub
|
||||
com.grubhub.android
|
||||
|
||||
# Deliveroo
|
||||
com.deliveroo.orderapp
|
||||
|
||||
# Just Eat
|
||||
com.justeat.app.uk
|
||||
com.justeat.android
|
||||
|
||||
# Postmates
|
||||
com.postmates.android
|
||||
|
||||
# Seamless
|
||||
com.seamless.consumer
|
||||
|
||||
# Foodpanda
|
||||
com.global.foodpanda.android
|
||||
|
||||
# Getir (quick delivery)
|
||||
com.getir
|
||||
com.getir.express
|
||||
|
||||
# Flink
|
||||
com.flink.android
|
||||
com.flink.consumer
|
||||
|
||||
# GoPuff
|
||||
com.gopuff.android
|
||||
|
||||
# Instacart
|
||||
com.instacart.client
|
||||
|
||||
# Gorillas
|
||||
com.gorillas.consumer
|
||||
|
||||
# ===== Browsers (to prevent bypassing blocks) =====
|
||||
# Firefox (allowed - hosts blocking is sufficient)
|
||||
# org.mozilla.firefox
|
||||
# org.mozilla.firefox_beta
|
||||
# org.mozilla.fenix
|
||||
|
||||
# Chrome (comment out if needed for some functionality)
|
||||
# com.android.chrome
|
||||
|
||||
# Opera
|
||||
com.opera.browser
|
||||
com.opera.mini.native
|
||||
com.opera.gx
|
||||
|
||||
# Brave
|
||||
com.brave.browser
|
||||
|
||||
# Samsung Internet
|
||||
com.sec.android.app.sbrowser
|
||||
|
||||
# Microsoft Edge
|
||||
com.microsoft.emmx
|
||||
|
||||
# DuckDuckGo
|
||||
com.duckduckgo.mobile.android
|
||||
|
||||
# Kiwi Browser
|
||||
com.kiwibrowser.browser
|
||||
|
||||
# Vivaldi
|
||||
com.vivaldi.browser
|
||||
|
||||
# UC Browser
|
||||
com.UCMobile.intl
|
||||
|
||||
# Tor Browser
|
||||
org.torproject.torbrowser
|
||||
|
||||
# ===== YouTube Apps =====
|
||||
com.google.android.youtube
|
||||
com.vanced.android.youtube
|
||||
app.revanced.android.youtube
|
||||
app.revanced.android.apps.youtube.music
|
||||
|
||||
# ===== Alternative YouTube Frontend Apps =====
|
||||
# NewPipe
|
||||
org.schabi.newpipe
|
||||
org.schabi.newpipelegacy
|
||||
|
||||
# LibreTube
|
||||
com.github.libretube
|
||||
|
||||
# SkyTube
|
||||
free.rm.skytube.oss
|
||||
free.rm.skytube.extra
|
||||
|
||||
# Clipious (Invidious client)
|
||||
com.github.lamarios.clipious
|
||||
|
||||
# Hyperion (YouTube client)
|
||||
us.spotco.hyperion
|
||||
|
||||
# GrayJay
|
||||
com.futo.platformplayer
|
||||
|
||||
# PipePipe
|
||||
InfinityLoop1309.NewPipeEnhanced
|
||||
|
||||
# Materialious
|
||||
com.materialious.app
|
||||
|
||||
# VueTube
|
||||
app.vuetube.app
|
||||
|
||||
# ===== Fast Food Apps =====
|
||||
# McDonald's
|
||||
com.mcdonalds.app
|
||||
com.mcdonalds.mobileapp
|
||||
|
||||
# KFC
|
||||
com.yum.kfcpolska
|
||||
com.kfc.app
|
||||
|
||||
# Burger King
|
||||
com.emn8.mobilem8.nativeapp.bk
|
||||
com.burgerking
|
||||
|
||||
# Pizza Hut
|
||||
com.pizzahut.app
|
||||
|
||||
# Domino's
|
||||
com.dominospizza
|
||||
|
||||
# Subway
|
||||
com.subway.mobile
|
||||
|
||||
# ===== Other Distracting Apps =====
|
||||
# TikTok
|
||||
com.zhiliaoapp.musically
|
||||
com.ss.android.ugc.trill
|
||||
|
||||
# Instagram (optional - comment out if needed)
|
||||
# com.instagram.android
|
||||
|
||||
# Facebook (optional)
|
||||
# com.facebook.katana
|
||||
|
||||
# Twitter/X
|
||||
# com.twitter.android
|
||||
@ -1,6 +0,0 @@
|
||||
id=android_guardian
|
||||
name=Android Guardian (Hosts + App Blocker)
|
||||
version=1.1
|
||||
versionCode=2
|
||||
author=linux-configuration
|
||||
description=Persistent hosts blocking and app installation guard. Protected by watchdog - cannot be disabled from Magisk UI. Only controllable via ADB.
|
||||
@ -1,101 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
# Runs early in boot - set up hosts file and start watchdog
|
||||
# MODDIR is set by Magisk and points to this module's directory
|
||||
GUARDIAN_DIR="${ANDROID_GUARDIAN_DIR:-/data/adb/android_guardian}"
|
||||
WATCHDOG_SCRIPT="${ANDROID_GUARDIAN_WATCHDOG_SCRIPT:-$GUARDIAN_DIR/watchdog.sh}"
|
||||
LOG_FILE="$GUARDIAN_DIR/guardian.log"
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] post-fs-data: $*" >>"$LOG_FILE"
|
||||
}
|
||||
|
||||
write_watchdog_script() {
|
||||
cat >"$WATCHDOG_SCRIPT" <<'WATCHDOG'
|
||||
#!/system/bin/sh
|
||||
# Secondary watchdog - runs independently of module state
|
||||
# Even if module is "disabled" in Magisk UI, this keeps running and undoes it
|
||||
GUARDIAN_DIR="${ANDROID_GUARDIAN_DIR:-/data/adb/android_guardian}"
|
||||
MODULE_DIR="${ANDROID_GUARDIAN_MODULE_DIR:-/data/adb/modules/android_guardian}"
|
||||
LOG_FILE="$GUARDIAN_DIR/watchdog.log"
|
||||
CONTROL_FILE="$GUARDIAN_DIR/control"
|
||||
HOSTS_BACKUP="$GUARDIAN_DIR/hosts.backup"
|
||||
MODULE_HOSTS="$MODULE_DIR/system/etc/hosts"
|
||||
LOOP_SLEEP_SECONDS=3
|
||||
HOSTS_CHECK_EVERY_TICKS=10
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >>"$LOG_FILE"
|
||||
}
|
||||
|
||||
is_enabled() {
|
||||
if [ ! -f "$CONTROL_FILE" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
IFS= read -r guardian_state < "$CONTROL_FILE" || guardian_state=""
|
||||
[ "$guardian_state" = "ENABLED" ]
|
||||
}
|
||||
|
||||
protect_module_flags() {
|
||||
if [ -f "$MODULE_DIR/disable" ]; then
|
||||
log "ALERT: Module disable detected via Magisk UI - removing disable flag"
|
||||
rm -f "$MODULE_DIR/disable"
|
||||
fi
|
||||
|
||||
if [ -f "$MODULE_DIR/remove" ]; then
|
||||
log "ALERT: Module removal detected via Magisk UI - removing remove flag"
|
||||
rm -f "$MODULE_DIR/remove"
|
||||
fi
|
||||
}
|
||||
|
||||
protect_hosts() {
|
||||
if [ ! -f "$HOSTS_BACKUP" ] || [ ! -f "$MODULE_HOSTS" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if ! cmp -s "$MODULE_HOSTS" "$HOSTS_BACKUP"; then
|
||||
log "ALERT: Hosts tampering detected - restoring"
|
||||
cp "$HOSTS_BACKUP" "$MODULE_HOSTS"
|
||||
fi
|
||||
}
|
||||
|
||||
log "=== Watchdog starting ==="
|
||||
|
||||
tick_count=0
|
||||
while true; do
|
||||
protect_module_flags
|
||||
|
||||
if is_enabled; then
|
||||
if [ $((tick_count % HOSTS_CHECK_EVERY_TICKS)) -eq 0 ]; then
|
||||
protect_hosts
|
||||
fi
|
||||
fi
|
||||
|
||||
tick_count=$((tick_count + 1))
|
||||
sleep "$LOOP_SLEEP_SECONDS"
|
||||
done
|
||||
WATCHDOG
|
||||
}
|
||||
|
||||
start_watchdog() {
|
||||
nohup sh "$WATCHDOG_SCRIPT" >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
post_fs_main() {
|
||||
mkdir -p "$GUARDIAN_DIR"
|
||||
log "Guardian module loading"
|
||||
write_watchdog_script
|
||||
chmod 755 "$WATCHDOG_SCRIPT"
|
||||
|
||||
if [ "${ANDROID_GUARDIAN_POST_FS_SKIP_WATCHDOG_START:-0}" -ne 1 ]; then
|
||||
start_watchdog
|
||||
log "Watchdog started"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Watchdog generation complete (start skipped)"
|
||||
}
|
||||
|
||||
if [ "${ANDROID_GUARDIAN_POST_FS_SKIP_MAIN:-0}" -ne 1 ]; then
|
||||
post_fs_main
|
||||
fi
|
||||
@ -1,143 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
# Android Guardian Service - runs at boot
|
||||
# This service:
|
||||
# 1. Monitors and protects the hosts file
|
||||
# 2. Blocks installation of forbidden apps
|
||||
# 3. Prevents module from being disabled via Magisk UI
|
||||
# 4. Can only be stopped via ADB with the correct command
|
||||
|
||||
MODDIR=${0%/*}
|
||||
GUARDIAN_DIR="${ANDROID_GUARDIAN_DIR:-/data/adb/android_guardian}"
|
||||
LOG_FILE="$GUARDIAN_DIR/guardian.log"
|
||||
BLOCKED_APPS_FILE="$GUARDIAN_DIR/blocked_apps.txt"
|
||||
CONTROL_FILE="$GUARDIAN_DIR/control"
|
||||
HOSTS_BACKUP="$GUARDIAN_DIR/hosts.backup"
|
||||
MODULE_DIR="${ANDROID_GUARDIAN_MODULE_DIR:-/data/adb/modules/android_guardian}"
|
||||
SYSTEM_HOSTS_FILE="${ANDROID_GUARDIAN_SYSTEM_HOSTS_FILE:-/system/etc/hosts}"
|
||||
MODULE_HOSTS_FILE="${ANDROID_GUARDIAN_MODULE_HOSTS_FILE:-$MODDIR/system/etc/hosts}"
|
||||
DISABLE_FILE="$MODULE_DIR/disable"
|
||||
REMOVE_FILE="$MODULE_DIR/remove"
|
||||
LOOP_SLEEP_SECONDS=5
|
||||
HOSTS_CHECK_EVERY_TICKS=6
|
||||
APPS_CHECK_EVERY_TICKS=12
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >>"$LOG_FILE"
|
||||
}
|
||||
|
||||
initialize_service() {
|
||||
mkdir -p "$GUARDIAN_DIR"
|
||||
|
||||
if [ ! -f "$CONTROL_FILE" ]; then
|
||||
echo "ENABLED" >"$CONTROL_FILE"
|
||||
fi
|
||||
|
||||
log "=== Android Guardian starting ==="
|
||||
|
||||
# Enable wireless ADB on boot (persistent port 5555)
|
||||
setprop service.adb.tcp.port 5555
|
||||
stop adbd
|
||||
start adbd
|
||||
log "Wireless ADB enabled on port 5555"
|
||||
}
|
||||
|
||||
# Function to check if guardian is enabled (via ADB control, not Magisk UI)
|
||||
is_enabled() {
|
||||
[ "$(cat "$CONTROL_FILE" 2>/dev/null)" = "ENABLED" ]
|
||||
}
|
||||
|
||||
# Function to protect module from being disabled via Magisk UI
|
||||
protect_module() {
|
||||
# Remove disable file if someone tried to disable via Magisk
|
||||
if [ -f "$DISABLE_FILE" ]; then
|
||||
log "Module disable attempt detected via Magisk UI! Re-enabling..."
|
||||
rm -f "$DISABLE_FILE"
|
||||
log "Module re-enabled"
|
||||
fi
|
||||
|
||||
# Remove remove file if someone tried to uninstall via Magisk
|
||||
if [ -f "$REMOVE_FILE" ]; then
|
||||
log "Module removal attempt detected via Magisk UI! Blocking..."
|
||||
rm -f "$REMOVE_FILE"
|
||||
log "Module removal blocked"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to restore hosts file if tampered
|
||||
protect_hosts() {
|
||||
if [ -f "$HOSTS_BACKUP" ]; then
|
||||
if ! cmp -s "$SYSTEM_HOSTS_FILE" "$HOSTS_BACKUP"; then
|
||||
log "Hosts file tampering detected! Restoring..."
|
||||
cp "$HOSTS_BACKUP" "$MODULE_HOSTS_FILE"
|
||||
log "Hosts file restored"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to uninstall blocked apps
|
||||
check_blocked_apps() {
|
||||
if [ ! -f "$BLOCKED_APPS_FILE" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
installed_packages=$(pm list packages 2>/dev/null) || installed_packages=""
|
||||
if [ -z "$installed_packages" ]; then
|
||||
return
|
||||
fi
|
||||
installed_packages="
|
||||
$installed_packages
|
||||
"
|
||||
|
||||
while IFS= read -r package || [ -n "$package" ]; do
|
||||
# Skip comments and empty lines
|
||||
case "$package" in
|
||||
\#* | "") continue ;;
|
||||
esac
|
||||
|
||||
# Check if package is installed
|
||||
case "$installed_packages" in
|
||||
*"
|
||||
package:$package
|
||||
"*)
|
||||
log "Blocked app detected: $package - Uninstalling..."
|
||||
if pm uninstall "$package" 2>/dev/null; then
|
||||
log "Uninstalled: $package"
|
||||
else
|
||||
log "Failed to uninstall: $package"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done <"$BLOCKED_APPS_FILE"
|
||||
}
|
||||
|
||||
guardian_loop() {
|
||||
tick_count=0
|
||||
while true; do
|
||||
# ALWAYS protect module from UI disabling (even if guardian is "disabled" via ADB)
|
||||
# This ensures only ADB can control the guardian
|
||||
protect_module
|
||||
|
||||
if is_enabled; then
|
||||
if [ $((tick_count % HOSTS_CHECK_EVERY_TICKS)) -eq 0 ]; then
|
||||
protect_hosts
|
||||
fi
|
||||
|
||||
if [ $((tick_count % APPS_CHECK_EVERY_TICKS)) -eq 0 ]; then
|
||||
check_blocked_apps
|
||||
fi
|
||||
fi
|
||||
|
||||
tick_count=$((tick_count + 1))
|
||||
sleep "$LOOP_SLEEP_SECONDS"
|
||||
done
|
||||
}
|
||||
|
||||
service_main() {
|
||||
initialize_service
|
||||
guardian_loop &
|
||||
log "Guardian service started (PID: $!)"
|
||||
}
|
||||
|
||||
if [ "${ANDROID_GUARDIAN_SKIP_MAIN:-0}" -ne 1 ]; then
|
||||
service_main
|
||||
fi
|
||||
@ -1,16 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
# Cleanup when module is uninstalled
|
||||
GUARDIAN_DIR="/data/adb/android_guardian"
|
||||
|
||||
# Only allow uninstall if control file says DISABLED
|
||||
if [ -f "$GUARDIAN_DIR/control" ]; then
|
||||
status=$(cat "$GUARDIAN_DIR/control")
|
||||
if [ "$status" != "DISABLED" ]; then
|
||||
echo "Guardian is still enabled! Use ADB to disable first:"
|
||||
echo " adb shell 'echo DISABLED > /data/adb/android_guardian/control'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up guardian data
|
||||
rm -rf "$GUARDIAN_DIR"
|
||||
@ -9,6 +9,8 @@ build_module() {
|
||||
local tmp_dir="$WORK_DIR/guardian_module"
|
||||
local module_zip="$WORK_DIR/android_guardian.zip"
|
||||
|
||||
require_guardian_module
|
||||
|
||||
echo "[BUILD] Building Android Guardian module..." >&2
|
||||
|
||||
rm -rf "$tmp_dir"
|
||||
|
||||
@ -10,10 +10,25 @@ source "$SCRIPT_DIR/../../lib/common.sh"
|
||||
# shellcheck source=../../lib/android.sh
|
||||
source "$SCRIPT_DIR/../../lib/android.sh"
|
||||
|
||||
GUARDIAN_MODULE_DIR="$SCRIPT_DIR/android_guardian"
|
||||
# The module moved to github.com/kuhyx/android-guardian. This pointed at a
|
||||
# sibling directory that never existed here even before the extraction, so the
|
||||
# script could not have packaged a module from this path; prefer a checkout and
|
||||
# say so loudly rather than failing later inside zip.
|
||||
GUARDIAN_MODULE_DIR="${ANDROID_GUARDIAN_DIR:-$HOME/android-guardian}/module"
|
||||
GUARDIAN_DATA_DIR="/data/adb/android_guardian"
|
||||
MODULE_DEST="/data/adb/modules/android_guardian"
|
||||
|
||||
# Fail here, not four helpers deep inside a cp. Every packaging step below
|
||||
# reads GUARDIAN_MODULE_DIR unguarded, so an absent checkout would otherwise
|
||||
# surface as a bare "cp: cannot stat".
|
||||
require_guardian_module() {
|
||||
[[ -f "$GUARDIAN_MODULE_DIR/module.prop" ]] && return 0
|
||||
die "android-guardian module not found at ${GUARDIAN_MODULE_DIR}.
|
||||
It lives in its own repo now:
|
||||
git clone https://github.com/kuhyx/android-guardian ~/android-guardian
|
||||
Or point this script elsewhere with ANDROID_GUARDIAN_DIR."
|
||||
}
|
||||
|
||||
# Ensure android-tools (adb) is installed
|
||||
ensure_adb_installed() {
|
||||
if command -v adb &>/dev/null; then
|
||||
@ -90,7 +105,6 @@ source "$SCRIPT_DIR/lib/android_module.sh"
|
||||
# shellcheck source=lib/android_commands.sh
|
||||
source "$SCRIPT_DIR/lib/android_commands.sh"
|
||||
|
||||
|
||||
# Main
|
||||
# Initialize Android script (handles sudo, sets WORK_DIR)
|
||||
init_android_script "$@"
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Regression tests for android_guardian post-fs-data watchdog generation.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
REPO_DIR=$(cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
TARGET_SCRIPT="$REPO_DIR/scripts/periodic_background/utils/android_guardian/post-fs-data.sh"
|
||||
|
||||
fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_file_contains() {
|
||||
local file_path="$1"
|
||||
local pattern="$2"
|
||||
local context="$3"
|
||||
grep -q -- "$pattern" "$file_path" || fail "$context"
|
||||
}
|
||||
|
||||
assert_file_not_contains() {
|
||||
local file_path="$1"
|
||||
local pattern="$2"
|
||||
local context="$3"
|
||||
if grep -q -- "$pattern" "$file_path"; then
|
||||
fail "$context"
|
||||
fi
|
||||
}
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
cleanup() {
|
||||
rm -rf "$TMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
GUARDIAN_DIR="$TMP_DIR/guardian"
|
||||
MODULE_DIR="$TMP_DIR/module"
|
||||
WATCHDOG_SCRIPT="$GUARDIAN_DIR/watchdog.sh"
|
||||
mkdir -p "$GUARDIAN_DIR" "$MODULE_DIR/system/etc"
|
||||
|
||||
printf 'Generating watchdog script in a temp Android guardian directory...\n'
|
||||
ANDROID_GUARDIAN_DIR="$GUARDIAN_DIR" \
|
||||
ANDROID_GUARDIAN_MODULE_DIR="$MODULE_DIR" \
|
||||
ANDROID_GUARDIAN_WATCHDOG_SCRIPT="$WATCHDOG_SCRIPT" \
|
||||
ANDROID_GUARDIAN_POST_FS_SKIP_WATCHDOG_START=1 \
|
||||
sh "$TARGET_SCRIPT"
|
||||
|
||||
[[ -f "$WATCHDOG_SCRIPT" ]] || fail 'watchdog script should be generated'
|
||||
[[ -x "$WATCHDOG_SCRIPT" ]] || fail 'watchdog script should be executable'
|
||||
|
||||
printf 'Checking generated watchdog cadence and lower-fork host protection...\n'
|
||||
assert_file_contains "$WATCHDOG_SCRIPT" '^HOSTS_CHECK_EVERY_TICKS=10$' \
|
||||
'watchdog should throttle host protection to every 10 ticks'
|
||||
assert_file_contains "$WATCHDOG_SCRIPT" '^LOOP_SLEEP_SECONDS=3$' \
|
||||
'watchdog should keep the 3 second base sleep'
|
||||
assert_file_contains "$WATCHDOG_SCRIPT" 'cmp -s' \
|
||||
'watchdog should use cmp for host integrity checks'
|
||||
assert_file_not_contains "$WATCHDOG_SCRIPT" 'md5sum' \
|
||||
'watchdog should not use md5sum in the hot loop anymore'
|
||||
assert_file_not_contains "$WATCHDOG_SCRIPT" 'cut -d' \
|
||||
'watchdog should not pipe hashes through cut anymore'
|
||||
|
||||
printf 'Checking test hooks and generation log entry...\n'
|
||||
assert_file_contains "$TARGET_SCRIPT" 'ANDROID_GUARDIAN_POST_FS_SKIP_MAIN' \
|
||||
'post-fs-data should support skipping main for tests'
|
||||
assert_file_contains "$TARGET_SCRIPT" 'ANDROID_GUARDIAN_POST_FS_SKIP_WATCHDOG_START' \
|
||||
'post-fs-data should support generating without starting the watchdog'
|
||||
assert_file_contains "$GUARDIAN_DIR/guardian.log" 'Watchdog generation complete (start skipped)' \
|
||||
'post-fs-data should log skipped watchdog starts during tests'
|
||||
|
||||
printf 'android_guardian post-fs-data regression checks passed.\n'
|
||||
@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Regression tests for android_guardian service loop cadence.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
REPO_DIR=$(cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
TARGET_SCRIPT="$REPO_DIR/scripts/periodic_background/utils/android_guardian/service.sh"
|
||||
|
||||
fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_equals() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local context="$3"
|
||||
if [[ "$expected" != "$actual" ]]; then
|
||||
fail "$context (expected: '$expected', actual: '$actual')"
|
||||
fi
|
||||
}
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
cleanup() {
|
||||
rm -rf "$TMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
WORKTREE="$TMP_DIR/worktree"
|
||||
mkdir -p "$WORKTREE/scripts/periodic_background/utils/android_guardian"
|
||||
cp "$TARGET_SCRIPT" "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh"
|
||||
|
||||
printf 'Checking skip-main avoids boot side effects...\n'
|
||||
SKIP_MAIN_GUARDIAN_DIR="$TMP_DIR/skip-main-guardian"
|
||||
ANDROID_GUARDIAN_SKIP_MAIN=1 \
|
||||
ANDROID_GUARDIAN_DIR="$SKIP_MAIN_GUARDIAN_DIR" \
|
||||
ANDROID_GUARDIAN_MODULE_DIR="$TMP_DIR/skip-main-module" \
|
||||
sh "$TARGET_SCRIPT"
|
||||
|
||||
[[ ! -d "$SKIP_MAIN_GUARDIAN_DIR" ]] ||
|
||||
fail 'skip-main should prevent guardian boot setup side effects'
|
||||
|
||||
printf 'Checking guardian loop cadence constants...\n'
|
||||
hosts_ticks=$(grep '^HOSTS_CHECK_EVERY_TICKS=' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" | cut -d= -f2)
|
||||
apps_ticks=$(grep '^APPS_CHECK_EVERY_TICKS=' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" | cut -d= -f2)
|
||||
sleep_seconds=$(grep '^LOOP_SLEEP_SECONDS=' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" | cut -d= -f2)
|
||||
|
||||
assert_equals '6' "$hosts_ticks" 'hosts protection should run every 6 ticks'
|
||||
assert_equals '12' "$apps_ticks" 'blocked-app scan should run every 12 ticks'
|
||||
assert_equals '5' "$sleep_seconds" 'guardian loop should keep the 5 second base sleep'
|
||||
|
||||
printf 'Checking guardian loop protects module every tick...\n'
|
||||
grep -q 'protect_module' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" ||
|
||||
fail 'guardian loop must always protect the module each tick'
|
||||
|
||||
printf 'Checking blocked-app scans are cached per pass...\n'
|
||||
# Literal search pattern: the $ must reach grep as text, not be expanded
|
||||
# by this shell.
|
||||
# shellcheck disable=SC2016
|
||||
grep -q 'installed_packages=$(pm list packages 2>/dev/null)' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" ||
|
||||
fail 'guardian service should cache installed packages once per blocked-app scan'
|
||||
|
||||
if grep -q 'pm list packages 2>/dev/null | grep -q' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh"; then
|
||||
fail 'guardian service should not re-run pm list packages through grep for every blocked app'
|
||||
fi
|
||||
|
||||
printf 'Checking guardian loop uses skip-main guard for tests...\n'
|
||||
grep -q 'ANDROID_GUARDIAN_SKIP_MAIN' "$WORKTREE/scripts/periodic_background/utils/android_guardian/service.sh" ||
|
||||
fail 'guardian service should support skip-main testing'
|
||||
|
||||
printf 'android_guardian service regression checks passed.\n'
|
||||
Loading…
Reference in New Issue
Block a user