Skip to content

selinux: restore missing ioctl/lock and gpg_exec_t in optional policy blocks#643

Merged
bfjelds merged 2 commits into
mainfrom
user/bfjelds/mjolnir/fix-selinux-optional-permissions
May 13, 2026
Merged

selinux: restore missing ioctl/lock and gpg_exec_t in optional policy blocks#643
bfjelds merged 2 commits into
mainfrom
user/bfjelds/mjolnir/fix-selinux-optional-permissions

Conversation

@bfjelds
Copy link
Copy Markdown
Member

@bfjelds bfjelds commented May 12, 2026

Problem

PR #636 replaced refpolicy interface macros with hand-expanded allow rules inside optional_policy blocks so the policy compiles on ACL images that lack those modules. However, the manual expansions had two permission gaps:

1. gpg_exec_t dropped entirely

The original gpg_entry_type(trident_t) macro expanded to domain_entry_file(trident_t, gpg_exec_t), granting trident access to the main gpg/gpg2 binary. The replacement only covered gpg_agent_exec_tgpg_exec_t was neither required nor referenced.

On full Azure Linux where GPG is installed, trident loses all permissions on the gpg binary (needed by tdnf/rpm for package signature verification).

2. ioctl and lock systematically dropped from all exec replacements

Six exec macro replacements (chronyd_exec_t, logrotate_exec_t, rpm_exec_t, sudo_exec_t, kadmind_exec_t, gpg_agent_exec_t) all used { getattr open read execute execute_no_trans map } but the original can_exec / domain_entry_file macros also grant ioctl and lock.

This creates a permission gap on full AZL that could cause AVC denials.

3. entrypoint used instead of execute_no_trans on gpg binaries

The pre-#636 policy used gpg_entry_type(trident_t) which grants entrypoint — meaning 'this binary is a valid entry point for transitioning INTO trident_t.' However, trident (and osmodifier, which trident calls) do not directly exec gpg. GPG is invoked indirectly by tdnf/rpm for package signature verification, running in trident_t via execute_no_trans. There is no type_transition rule for gpg → trident_t anywhere in the policy, so entrypoint was always a latent bug in the original policy. The correct permission is execute_no_trans (execute without domain transition), matching can_exec macro semantics.

Verified that all tools invoked by osmodifier (useradd, usermod, systemctl, openssl, sed, grub2-mkconfig, blkid, setfiles, semanage, chmod) are already covered by existing policy rules.

Fix

  • Add gpg_exec_t to the GPG optional block
  • Use execute_no_trans (not entrypoint) on both gpg_exec_t and gpg_agent_exec_t to match actual runtime behavior
  • Restore ioctl and lock on all six _exec_t allow rules to match upstream macro semantics

Review

Changes validated by 9-agent deep review (3 roles × 3 models: GPT-5.5, Opus, Sonnet). Finding #2 (entrypoint semantics) was flagged by all 3 skeptic models and 2 of 3 architect models.

Validation

PR #636 replaced refpolicy interface macros with hand-expanded allow
rules inside optional_policy blocks, but the expansions had two gaps:

1. gpg_entry_type(trident_t) was dropped entirely, losing all permissions
   on gpg_exec_t. The replacement only covered gpg_agent_exec_t. Restore
   gpg_exec_t with the full domain_entry_file permission set.

2. All six _exec_t replacements (chronyd, logrotate, rpm, sudo, kadmind,
   gpg_agent) used { getattr open read execute execute_no_trans map } but
   the original can_exec / domain_entry_file macros also grant ioctl and
   lock. Restore these two permissions to match upstream semantics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bfjelds bfjelds marked this pull request as ready for review May 12, 2026 03:24
@bfjelds bfjelds requested a review from a team as a code owner May 12, 2026 03:24
Copilot AI review requested due to automatic review settings May 12, 2026 03:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes SELinux policy permission regressions introduced when refpolicy interface macros were manually expanded inside optional_policy blocks (to support ACL images that remove certain SELinux modules). This PR restores missing permissions so Trident can execute GPG and other helper binaries without AVC denials on full Azure Linux images.

Changes:

  • Add gpg_exec_t back into the optional GPG policy block and grant Trident the expected executable access.
  • Restore ioctl and lock permissions on several _exec_t allow rules (chronyd, logrotate, rpm, sudo, kadmind, and gpg-agent) to align with prior macro-derived permissions.

The pre-#636 policy used gpg_entry_type(trident_t) which grants entrypoint
on gpg_exec_t. However, entrypoint means 'this binary is a valid entry
point for transitioning INTO trident_t' — the opposite of what is needed.

Trident execs gpg/gpg-agent and stays in its own domain (trident_t), so
the correct permission is execute_no_trans (execute without domain
transition), matching can_exec macro semantics.

The original macro choice was incorrect; fix it properly now rather than
faithfully restoring incorrect behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bfjelds
Copy link
Copy Markdown
Member Author

bfjelds commented May 12, 2026

/azp run [GITHUB]-trident-pr-e2e

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bfjelds bfjelds merged commit 9a51c88 into main May 13, 2026
96 checks passed
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.

3 participants