Skip to content

KernelSU hooks poll forever after the APK is uninstalled normally #24

Description

@LIghtJUNction

Summary

The KernelSU installation path writes identical hooks to both:

/data/adb/post-fs-data.d/0000liveboot
/data/adb/service.d/0000liveboot

Each hook starts an unbounded background loop that checks the app's device-protected files directory every 100 ms. If the LiveBoot APK is later removed through Android's normal package uninstaller, that directory no longer exists and neither hook can reach its exit condition. Both loops then survive for the entire uptime on every subsequent boot.

Steps to reproduce

  1. Install LiveBoot and select/install the KernelSU startup integration.
  2. Confirm the two 0000liveboot hooks exist.
  3. Uninstall eu.chainfire.liveboot through Android Settings or pm uninstall, rather than invoking LiveBoot's in-app cleanup path.
  4. Reboot.
  5. Inspect the processes and the two hook files.

Actual behavior

Both hooks contain the source-generated loop:

{
    while (true); do
        if [ -d "/data/user_de/0/eu.chainfire.liveboot/files" ]; then
            break
        fi
        sleep 0.1
    done
    /system/bin/sh /data/user_de/0/eu.chainfire.liveboot/files/liveboot
} &

With the package and data directory absent, two pollers remained alive for more than 1 day 9 hours. On the observed device they had accumulated approximately:

post-fs-data hook: 27m08s CPU, 1.3% lifetime CPU
service hook:      21m54s CPU, 1.0% lifetime CPU

Removing the two hooks and terminating the pollers immediately resolved the continuous CPU use.

Expected behavior

A stale startup hook should stop polling when the package is no longer installed. It should not remain active indefinitely after a normal APK uninstall.

Source location

The unbounded KernelSU loops are generated in Installer.java, lines 354-370.

The existing Installer.uninstall() cleanup does include the KernelSU paths, but Android's regular package removal does not execute this in-app method, so it cannot prevent the stale hooks in that removal path.

Suggested mitigation

  • Use a bounded wait (and preferably exponential backoff) instead of an infinite 100 ms poll.
  • If the files directory is still absent after the bounded direct-boot window, exit cleanly.
  • Once PackageManager is available, verify eu.chainfire.liveboot still exists and self-remove the stale hooks when it does not.
  • Consider avoiding two independent high-frequency pollers for the same condition.

Environment

  • Android 16 / SDK 36
  • OnePlus PHK110 / ColorOS 16
  • KernelSU userspace: ksud 3.2.5
  • Package eu.chainfire.liveboot: absent at diagnosis time

No personal log data is included.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions