Skip to content

Force-allow the ADB shell at boot (fix module-flash permission denied) + v3.3.0#62

Merged
RobThePCGuy merged 1 commit into
masterfrom
fix/adb-shell-auto-grant
Jul 21, 2026
Merged

Force-allow the ADB shell at boot (fix module-flash permission denied) + v3.3.0#62
RobThePCGuy merged 1 commit into
masterfrom
fix/adb-shell-auto-grant

Conversation

@RobThePCGuy

Copy link
Copy Markdown
Owner

What

Fixes the "permission denied" failure when flashing modules (ReZygisk / LSPosed) over ADB, and cuts v3.3.0.

Why it was happening

Magisk prompts for su on the first ADB module flash. If the prompt isn't tapped in time, magiskd auto-denies and caches that deny in the policies table — and the deny persists across cold boots (confirmed live). The previous online pre-grant couldn't help: it wrote the allow-policy through su, which is exactly what was being denied (chicken-and-egg).

The fix

The offline installer now plants a Magisk service.d script (00-bsrgui-adbgrant.sh) that runs as root at every boot and sets a permanent allow policy for the shell uid (2000). The shell can't set this itself; magiskd's service.d can. Scoped to the shell uid — apps still prompt normally.

  • magisk_system: _service_d_grant_commands + _grant_script_tempfile, wired into stage_databin (verified + rolled back with the DATABIN), removed on unstage, and creates /data/adb/service.d on a fresh instance.
  • adb_handler: _ensure_su_policy is now a silent belt-and-suspenders re-affirm; the flash message no longer tells the user to tap Grant.

Verified live (Android 13)

A fresh install grants the shell from first boot — no manager, no tap, ReZygisk flashes over ADB with no prompt, and a missed prompt can no longer lock ADB module installs out.

179 tests pass (+3).

…nied

The offline installer now plants a Magisk service.d script
(00-bsrgui-adbgrant.sh) that runs as root at every boot and sets a
permanent "allow" Superuser policy for the shell uid (2000). This fixes
the "permission denied" seen when flashing ReZygisk/LSPosed over ADB:
Magisk prompts for su, and if the prompt isn't tapped in time it
auto-DENIES and caches that deny across reboots, permanently locking out
ADB module installs.

The shell can't set this policy itself (it needs the very su it's being
denied), so the grant is planted offline via debugfs during
stage_databin and executed by magiskd at late_start. Scoped to the shell
uid only -- apps still prompt as normal. Verified live on Android 13: a
fresh install grants the shell from first boot with no manager and no
tap, and a missed prompt can no longer lock it out.

- magisk_system: _service_d_grant_commands + _grant_script_tempfile,
  wired into stage_databin (verified + rolled back with the DATABIN) and
  removed on unstage; creates /data/adb/service.d on a fresh instance.
- adb_handler: _ensure_su_policy demoted to a silent re-affirm; the flash
  message no longer tells the user to tap Grant.
- Version -> 3.3.0.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an offline Magisk service.d script (00-bsrgui-adbgrant.sh) to automatically grant root permissions to the ADB shell (UID 2000) at boot, preventing auto-denial issues during module flashing. This includes staging, unstaging, and verification logic in magisk_system.py, corresponding updates in adb_handler.py, and new unit tests. One high-severity issue was identified where staging could fail on fresh instances because the parent /adb directory does not exist and debugfs's mkdir is not recursive; a code suggestion was provided to resolve this.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread magisk_system.py
Comment on lines +433 to +436
svc_exists = "Inode:" in _es._stat_path(dev, _SERVICE_D, env)
script = (_clean_dir_commands(dev, _DATABIN, env)
+ _write_commands(tools) + _databin_extra_commands(extras)
+ _service_d_grant_commands(grant_script, svc_exists))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

On a fresh or newly cloned BlueStacks instance, the /data/adb directory (which maps to /adb in the ext4 filesystem of Data.vhdx) does not exist by default. If /adb is missing, both mkdir /adb/magisk (in _write_commands) and mkdir /adb/service.d (in _service_d_grant_commands) will fail because debugfs's mkdir is not recursive (it does not behave like mkdir -p).

To prevent staging failures on fresh instances, we should check if /adb exists and create it first if it is missing.

            adb_exists = "Inode:" in _es._stat_path(dev, "/adb", env)
            adb_cmds = []
            if not adb_exists:
                adb_cmds = ["mkdir /adb", "sif /adb mode 040700",
                            "sif /adb uid 0", "sif /adb gid 0",
                            "ea_set /adb security.selinux %s" % _SELINUX_CTX]
            svc_exists = adb_exists and "Inode:" in _es._stat_path(dev, _SERVICE_D, env)
            script = (adb_cmds
                      + _clean_dir_commands(dev, _DATABIN, env)
                      + _write_commands(tools) + _databin_extra_commands(extras)
                      + _service_d_grant_commands(grant_script, svc_exists))

@RobThePCGuy
RobThePCGuy merged commit 2b482d2 into master Jul 21, 2026
4 checks passed
@RobThePCGuy
RobThePCGuy deleted the fix/adb-shell-auto-grant branch July 21, 2026 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant