< Back to all hacks

#35 Recovery After Boot Loop

Dirty COW
Problem
Removed com.motorola.android.providers.settings -> permanent boot loop. Framework NPE every 90s.
Solution
8 fix attempts all failed (SELinux blocks everything). Only fix: factory reset.
Lesson
NEVER remove Motorola provider packages. Test ONE at a time. Always backup before risky operations.

Context

During the aggressive debloat phase, com.motorola.android.providers.settings was disabled via pm disable. This package provides Motorola's custom settings database overlay — Android's Settings framework crashes with a NullPointerException without it. The phone enters a boot loop where system_server starts, tries to read Motorola settings, crashes, and restarts every 90 seconds.

ADB is available during the boot loop (the USB debug daemon starts before system_server), but the package manager is barely functional. 8 different recovery approaches were attempted before accepting that only a factory reset would work.

All failed attempts:

#ApproachResult
1pm install -r APKPM inaccessible (crash loop)
2pm install-existingDoesn't exist on API 23
3service call packageService not functional
4Safe modeSame crash (system-level)
5Root rm restrictions.xmlSELinux denied
6Dirty COW on restrictionsopen() blocked by SELinux
7Dirty COW on dex2oatCode runs but no write perm
8ndc, broadcast, settings putAll blocked

Implementation

The only working fix was factory reset:

# From ADB shell during boot loop:
# WARNING: This wipes ALL data (apps, settings, files)
adb shell recovery --wipe_data

# Or via Android recovery mode:
# 1. Power off
# 2. Hold Volume Down + Power
# 3. Select "Recovery mode"
# 4. At Android robot, hold Power + tap Volume Up
# 5. Select "Wipe data/factory reset"

After factory reset, the entire PocketClaw setup must be rebuilt from scratch. This event led to the creation of boot-debloat.sh (Hack #26) — an automated script that can restore the debloat configuration in one command.

Verification

# After factory reset, verify the package is back:
adb shell pm list packages | grep motorola.android.providers
# Expected: package:com.motorola.android.providers.settings

# Verify phone boots normally:
adb shell getprop sys.boot_completed
# Expected: 1

Gotchas

  • On Android 6, pm uninstall -k --user 0 is PERMANENT — there is no pm install-existing command to restore. The only path back is factory reset
  • pm disable (via root) is REVERSIBLE — it writes to package-restrictions.xml which can be edited or deleted. Always prefer pm disable over pm uninstall
  • SELinux on Android 6 blocks shell domain from writing to /data/system/ even with uid=0 root. The Dirty COW race bypasses read protections but not write protections in this directory
  • Safe mode doesn't help because the settings provider is a system-level dependency, not a third-party app
  • Always test package removals ONE AT A TIME with a reboot between each. This way you know exactly which package caused the issue

Result

MetricBeforeAfter
Phone stateBoot loopWorking (post factory reset)
Data lostN/AEverything
Recovery timeN/A~2 hours (full re-setup)
Lesson valueN/APriceless