Skip to content

fix(install): stop requiring sudo when the driver install is already root - #305

Merged
volen-silo merged 1 commit into
mainfrom
install-driver-works-when-already-root
Sep 8, 2026
Merged

volen-silo merged 1 commit into
mainfrom
install-driver-works-when-already-root

Conversation

@volen-silo

@volen-silo volen-silo commented Aug 24, 2026 •

Copy link
Copy Markdown
Collaborator
  • If this PR fixes a bug, searched tests/e2e-cucumber/expectations.toml for the fixed ticket ID and removed/narrowed any now-stale xfail rows. — no such row exists on main yet; see Coordination.

Summary

rocm install driver --dkms built every command in its plan with a literal sudo prefix, applied unconditionally. As root that prefix is redundant; on a root host with no sudo binary it is fatal:

# id -u
0
# rocm install driver --dkms --yes
sh: 1: sudo: not found
Error: driver command failed: sudo apt-get update

Containers and minimal cloud images are exactly that shape — uid 0, no sudo — and this is the documented Linux driver path, so on those hosts it could not run at all.

Root cause: only the command generator was wrong. The command's own preflight already distinguished the two cases, promising sudo was needed "when not running as root". The preflight passed and execution then contradicted it.

What changed:

  • Privilege escalation is resolved into a prefix that is empty when already root, threaded through every distro plan builder (apt, dnf, zypper, and the RHEL kernel-header helper).
  • Resolution happens when the plan is built, not when it runs, so the plan --dry-run prints, the plan the approval prompt shows, and the commands recorded in state.json are all the commands that actually execute. Stripping the prefix at execution instead would leave all three misreporting what ran.
  • The preflight no longer claims a sudo binary is required when the plan has stopped using one.

Non-root behaviour is unchanged — all 25 pre-existing driver plan tests pass untouched under an explicit non-root escalation, rather than having their expectations rewritten.

Risk: low. No change to execution, approval, or the state-file shape; only the text of the generated commands, and only when already root.

Test plan

  • Five new tests. The primary one asserts the absence of sudo across all eight supported distro paths rather than checking commands one by one, so a templating site missed on some distro fails the suite instead of shipping. The others cover the inverse (off root, every privileged command still escalates), shell-pipeline integrity (| tee, | gpg — which a naive leading-prefix strip would miss), state.json agreement, and the preflight change.
  • I verified that sweep test can actually fail: reverting one templated site made it fail with rhel: a plan built as root must not invoke sudo, got 'sudo dnf clean all'. A green assertion that cannot fail would have been worse than none.
  • cargo test -p rocm 557 passed; clippy --workspace --all-targets -D warnings, fmt clean.
  • Rebased onto main after the repo_version / package_release split landed. The escalation parameter takes dnf_driver_plan and driver_plan_via_id_like to 8 arguments, so both carry #[allow(clippy::too_many_arguments)] — the same treatment five other builders in this file already have. Every parameter is one already-resolved fact the command templates read; a struct would move the same list one level out without shortening it.
  • Checked before designing that the --reconcile path never reads the persisted command strings, so plans differing by uid cannot break it.

Not verified locally, stated rather than skipped: the apt/DKMS path end to end. Every container on my machine inherits a WSL /proc/version, so is_wsl_host() matches and the plan short-circuits to the ROCDXG branch before distro dispatch — the DKMS path is unreachable here regardless of the container image. I confirmed that short-circuit still behaves after this change, but that is a guard on the branch above the fix, not evidence the fix works. End-to-end verification is the root-runner scenario described below.

Coordination

#291 adds a root-gated e2e scenario for this defect plus an expectations.toml xfail row. It is still open as of 2026-09-08, so there is no stale row for this PR to remove. Whichever merges second must reconcile:

…root

Every command in the native driver plan carried a literal `sudo ` prefix,
applied unconditionally. As root that prefix is redundant; on a root host
with no `sudo` binary it is fatal, and the first command dies with
`sudo: not found` before any driver work happens. Containers and minimal
cloud images are exactly that shape — root, no sudo — and `install driver`
is the documented Linux driver path, so on those hosts it could not run.

The command's own preflight already distinguished the two cases, promising
`sudo` was needed only "when not running as root". Only the generator
disagreed, so the preflight passed and execution then contradicted it.

Resolve the escalation into a prefix that is empty when already root, and
thread it through every distro plan builder. Resolution happens when the
plan is built rather than when it runs, so the plan `--dry-run` prints, the
plan the approval prompt shows, and the commands recorded in state.json are
all the commands that actually execute.

The preflight no longer claims a `sudo` binary is required when the plan
has stopped using one.

Non-root behaviour is unchanged: the existing plan tests pass untouched
under an explicit non-root escalation. The new coverage asserts the absence
of `sudo` across every supported distro rather than checking commands one
by one, so a templating site missed on some distro fails the suite instead
of shipping.

Signed-off-by: Eugene Volen <Eugene.Volen@amd.com>
@volen-silo
volen-silo force-pushed the install-driver-works-when-already-root branch from 95a3bc9 to fae3fef Compare September 8, 2026 09:21
@volen-silo
volen-silo marked this pull request as ready for review September 8, 2026 09:28
@volen-silo
volen-silo requested a review from a team as a code owner September 8, 2026 09:28
@volen-silo
volen-silo requested a review from johnl-amd September 8, 2026 09:29

@r0x0r r0x0r left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM.

Resolving the privilege escalation at plan-build time (via PrivilegeEscalation::detect()) rather than stripping a prefix at execution is the right design — it keeps --dry-run output, the approval prompt, and the commands persisted to state.json all consistent with what actually runs. The empty-prefix-when-already-root approach threads cleanly through every distro builder.

The test coverage is the strong point: the absence-of-sudo sweep across every distro from dkms_planning_os_releases(), the inverse off-root contract correctly scoped to Prepare/Execute (Verify probes stay unprivileged), and the mid-pipeline | sudo tee / | sudo gpg guard all mean a missed templating site fails the suite rather than shipping. The preflight correction (dropping the sudo-binary precondition when the plan won't use one) closes the stated-vs-actual contradiction. Platform gating on running_as_root() (#[cfg(target_os = "linux")], false elsewhere) checks out, and the off-Linux validate-only Windows path makes the default harmless.

Non-blocking: (1) the two self-hosted Strix Halo E2E lanes were still in progress at review time — worth confirming they finish green before merge; (2) please coordinate merge order with #291 so the shared xfail row doesn't XPASS the merge queue.

@volen-silo
volen-silo added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit f2c3477 Sep 8, 2026
26 of 27 checks passed
@volen-silo
volen-silo deleted the install-driver-works-when-already-root branch September 8, 2026 10:57
fredespi added a commit that referenced this pull request Sep 10, 2026
main's #305 (f2c3477) already fixed EAI-8053 — the driver install no
longer prepends `sudo` when it is already running as root — and shipped
unit tests over the install plan covering both the root and non-root
cases. The e2e scenario this branch carried is therefore redundant, and
no CI lane runs as uid 0, so it could never have executed anyway.
Remove the scenario, its `@requires-root` tag, the `is_root` capability
probe, the `mock-root` fixture and the expectations row.

What remains is the EAI-8051 ComfyUI contract:

- Register `comfyui.feature` in `FEATURE_KEYS` and renumber its scenario
  to `comfyui-01`, per the per-feature naming guard main added.
- Require the install to exit 0 before asserting runtime health. Since
  #298 it does; without that premise a bail-out (no managed runtime, a
  failed download) would leave the runtime trivially unchanged and the
  scenario would report green having installed nothing.
- Correct the now-stale comments claiming the install exits non-zero,
  and describe `find_venv_python` accurately: the documented layout is
  the first frontier entry, so the depth-capped walk is a fallback, not
  a cost the normal path pays.

Signed-off-by: fredespi <fredrik.espinoza@gmail.com>
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.

2 participants