ActionHelper.cpp

1. Overview

The ActionHelper.cpp file implements the privileged bastionguard-rootguard-action helper. It edits selected policy settings, replaces application-rule sections, restores protected metadata, quarantines protected files, and blocks/unblocks affected services while enforcing root privilege, path-policy coverage, filesystem identity checks, secure descriptor use, and atomic policy replacement.

The file integrates the following components, APIs, or runtime concepts:

  • PolicyLoader / PolicySecurity – secure policy validation
  • FileIdentityResolver – device/inode verification
  • SystemServiceControl – service containment
  • JsonEventSink – privileged action audit events
  • /var/lib/bastionguard/rootguard/quarantine – quarantine destination

2. Supported Commands

bastionguard-rootguard-action <set-protection|set-application-rules|restore|remove|block-service|unblock-service> [options]

The parser accepts policy path, affected path, original mode/UID/GID, device/inode baseline identity, protection state, and repeated trusted/denied application-rule options.


3. Root and Path Requirements

main() refuses to run unless effective UID is 0. Action paths must be absolute and normalized; parent traversal is rejected. Restore/remove/service actions must be covered by [protected-paths] and must not fall under an ignored rule.


4. Privileged Action Logging

logAction() creates the configured event-log parent directory if needed, builds an rg_event describing the helper action, records the helper executable from /proc/self/exe, and writes through JsonEventSink. Logging failure is non-fatal to the requested administrative action.


5. Immediate Protection Policy Rewrite

rewriteProtectionPolicy() edits only the engine keys needed for the UI protection switch. Enabling sets mode=enforce and metadata_action=block; disabling sets both to audit. It always forces global_metadata_action=audit and block_user_home=false.

The policy must be a regular non-symlink file. Rewrites occur through a PID-suffixed temporary file, original mode/ownership are preserved, and rename() atomically replaces the policy.


6. Application Rule Normalization

Rule entries must be absolute. Existing entries must be regular executable files. Missing paths are intentionally preserved for cross-distribution policy portability, while existing paths are canonicalized. Values are deduplicated and sorted.


7. Application Rule Section Replacement

Only [trusted-applications], [trusted-executables], and [denied-executables] are replaced. Other policy content is preserved. A path cannot be present in a trusted collection and denied collection simultaneously.


8. Validated Atomic Policy Installation

writePolicyAtomically() writes a temporary policy, reparses it with PolicyLoader::loadFromText(), refuses installation if invalid, preserves original mode/owner, and atomically renames the validated file over the existing policy.


9. Metadata Restore

Restore requires original mode, UID, and GID. The current object must still be the protected path, must not be a symlink, and—when supplied—must match the expected baseline device/inode.

The helper opens the object with O_NOFOLLOW plus directory/nonblocking flags as appropriate, verifies the open descriptor still refers to the same device/inode, then applies fchown() and fchmod(). Applicable systemd runtime masks are removed afterward, but services are not restarted.


10. Quarantine

Directory removal is not supported. For affected service definitions, the helper first attempts containment. OpenRC/SysV definitions are never executed as root unless supplied device/inode values match the current protected identity.

The object is moved with rename() into /var/lib/bastionguard/rootguard/quarantine, whose mode is set to 0700. Destination names include a timestamp, PID, and original filename. A manifest records original path, mode, ownership, device, and inode; the quarantined object itself is chmod 0000.


11. Service Block / Unblock Commands

Explicit block-service and unblock-service actions require protected-policy coverage. Script-based OpenRC/SysV containment adds the same identity-match safeguard before a root-owned script path can be executed.


12. Runtime and Security Considerations

  • Root-only execution: the helper is an administrative boundary intended to be launched through authorization tooling.
  • Policy coverage gate: restore, quarantine, and service actions cannot target arbitrary absolute paths.
  • Descriptor-based restore: metadata changes occur only after identity re-verification on the opened descriptor.
  • Atomic policy writes: edited policies are validated and renamed into place.
  • Quarantine isolation: moved files are placed in a root-controlled directory and made mode 0000.
  • Script-based init caution: OpenRC/SysV execution is conditioned on matching protected identity.