Skip to content

feat(linux): service actions go through the helper: a refusal for want of authorization retries there, and Authenticate and retry starts it (#2728) - #3013

Merged
mgradwohl merged 6 commits into
mainfrom
feat/brokered-service-actions-2728
Oct 26, 2026
Merged

mgradwohl merged 6 commits into
mainfrom
feat/brokered-service-actions-2728

Conversation

@mgradwohl

Copy link
Copy Markdown
Owner

Description

Part of #2728: slice 3 of 3 for service actions through the helper, after #2984 and #3002. With this, service actions need no polkit password per action once the helper runs.

  • BrokeredServiceActions: decorates TaskSmack's own IServiceActions.
    • A refused action (needsAuthorization: systemd would allow it with a password) is retried through a running helper with no prompt. Other failures, such as the running-dependents refusal, stay TaskSmack's own.
    • Authenticate and retry starts the helper (one password, held for the session or a few minutes) and acts through it, instead of letting polkit prompt per action. A dismissed password reports authorizationUnavailable, and nothing is sent.
    • A helper that answers with an error (one without service actions) leaves the refusal, and polkit's own prompt, as they were.
    • capabilities() offers Authenticate and retry wherever the inner actions or the helper can.
  • PanelPlatforms: composes it on Linux only. Windows' helper doesn't do service actions, so Windows keeps its own.
  • User guide (Services): what Authenticate and retry does when the helper is installed.

That completes #2728's Linux list: the session hold, the access choice, the chip and title, FD counts and I/O, network attribution, hidepid listing, and now service actions.

PR Size

⚠️ Medium (~360 lines, 7 files; a third of it tests).

Type of Change

  • New feature (non-breaking change that adds functionality)

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the project's coding standards
  • I have run clang-tidy and addressed any warnings
  • I have run clang-format on my changes
  • I have run pre-commit run --all-files or installed pre-commit hooks
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass
  • I have updated documentation as needed

Testing

TASKSMACK_REQUIRE_DISPLAY=1 TASKSMACK_REQUIRE_SDBUS=1 xvfb-run -a env -u WAYLAND_DISPLAY ctest --preset debug -j 4   # 684/684

New tests/Platform/test_BrokeredServiceActionsTest.* (a recording inner actions object plus FakeBroker):

  • a refusal for want of authorization goes to a running helper, never prompting;
  • other failures, and no running helper, leave TaskSmack's own answer;
  • Authenticate and retry starts the helper once and acts through it, with polkit never asked;
  • a helper without service actions leaves polkit's prompt and the refusal;
  • a dismissed password says so, and nothing is sent.

Additional Notes

v0.10.0, no backport.

🤖 Generated with Claude Code

mgradwohl and others added 5 commits October 25, 2026 21:30
…p, and can borrow one held system bus connection (#2728)

The first slice of service actions through the helper (the maintainer chose:
the helper opens the system bus as root before its privilege drop and seccomp
sandbox, and keeps that one connection). startUnit(), stopUnit() and
setUnitStartType() and their waits move out of SystemdUnits.cpp so the helper
can link them alone, not the services read. holdSystemBusForActions() opens
the system bus and keeps it; openForAction() then borrows that connection
(Bus::borrow(), which drops its reference without closing it) instead of
opening one per action. TaskSmack itself never holds one: no behavior change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…services over the system bus it opens as root before its sandbox (#2728)

The second slice of service actions through the helper. ServiceActionRequest
(an action, a unit, SetStartType's start type) and ServiceActionReply (the
ServiceActionResult). The helper, before dropping root and installing its
seccomp filter, holds the system bus (SystemdBus::holdSystemBusForActions())
where systemd runs; each request then goes over that connection as root, so
systemd asks for no password. Only a service's unit name is accepted
(SystemdActions::isServiceUnitName()). A service action puts off the idle exit
like any action; Windows' helper answers it with an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…services over the system bus it opens as root before its sandbox (#2728)

The second slice of service actions through the helper. ServiceActionRequest
(an action, a unit, SetStartType's start type) and ServiceActionReply (the
ServiceActionResult). The helper, before dropping root and installing its
seccomp filter, holds the system bus (SystemdBus::holdSystemBusForActions())
where systemd runs; each request then goes over that connection as root, so
systemd asks for no password. Only a service's unit name is accepted
(SystemdActions::isServiceUnitName()). A service action puts off the idle exit
like any action; Windows' helper answers it with an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t of authorization retries there, and Authenticate and retry starts it (#2728)

The third slice of service actions through the helper. BrokeredServiceActions
decorates TaskSmack's own (Linux only; Windows' helper doesn't do them): an
action systemd refuses only for want of authorization goes to a running helper
with no prompt; Authenticate and retry starts the helper (one password, held
for the session or a few minutes) and acts through it instead of letting
polkit prompt per action; a helper that answers with an error leaves the
refusal and polkit's own prompt as they were. The user guide says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t of authorization retries there, and Authenticate and retry starts it (#2728)

The third slice of service actions through the helper. BrokeredServiceActions
decorates TaskSmack's own (Linux only; Windows' helper doesn't do them): an
action systemd refuses only for want of authorization goes to a running helper
with no prompt; Authenticate and retry starts the helper (one password, held
for the session or a few minutes) and acts through it instead of letting
polkit prompt per action; a helper that answers with an error leaves the
refusal and polkit's own prompt as they were. The user guide says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mgradwohl mgradwohl added this to the v0.10.0 milestone Oct 26, 2026
@mgradwohl mgradwohl added enhancement New feature or request linux testing Platform agent:WSL Owned by the Linux/WSL Claude session (bug-fix conveyor) labels Oct 26, 2026
@mgradwohl
mgradwohl enabled auto-merge (squash) October 26, 2026 04:04
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies tooling Developer tooling, CI, editor config, and automation labels Oct 26, 2026
…nly, where it's used (#2728)

Windows' clang-tidy found it unused there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:WSL Owned by the Linux/WSL Claude session (bug-fix conveyor) dependencies documentation Improvements or additions to documentation enhancement New feature or request linux Platform testing tooling Developer tooling, CI, editor config, and automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant