Skip to content

Add CAP_CHOWN to permitted capability set#12908

Open
bryancall wants to merge 2 commits intoapache:masterfrom
bryancall:add-cap-chown-to-permitted
Open

Add CAP_CHOWN to permitted capability set#12908
bryancall wants to merge 2 commits intoapache:masterfrom
bryancall:add-cap-chown-to-permitted

Conversation

@bryancall
Copy link
Contributor

Summary

Add CAP_CHOWN to the permitted capability set retained by RestrictCapabilities() after the privilege drop from root to the unprivileged user.

This enables plugins that manage TLS certificate files to set root:root ownership on backup copies they write to disk, supporting deployments where cert files are restricted to root:root 600 inside root:root 700 directories.

Changes

  • src/tscore/ink_cap.cc -- Added CAP_CHOWN to perm_list in RestrictCapabilities(). Like CAP_DAC_OVERRIDE and CAP_FOWNER, it is retained in the permitted set only (not effective). A plugin must explicitly promote it to the effective set before use.

Security Considerations

CAP_CHOWN allows changing file ownership. It follows the same security model as CAP_DAC_OVERRIDE (already retained): held in the permitted set but not in the effective set during normal operation. A plugin must use RAII-style elevation to briefly promote it, then drop it immediately after the fchown() call.

Testing

Verified on Fedora 43 with libcap 2.76:

  • CAP_CHOWN appears in CapPrm but not CapEff after startup
  • fchown() succeeds when the capability is elevated
  • No change to steady-state behavior

Add CAP_CHOWN to the permitted capability set retained after privilege
drop. This allows plugins that perform cert file backup writes to set
root ownership on newly created files when certs are restricted to
root:root 600.

Like CAP_DAC_OVERRIDE, CAP_CHOWN is held in the permitted set only and
must be explicitly promoted to the effective set before use. It is not
active during normal operation.
@bryancall bryancall added this to the 10.2.0 milestone Feb 23, 2026
@bryancall bryancall self-assigned this Feb 23, 2026
@bryancall bryancall modified the milestones: 10.2.0, 11.0.0 Feb 23, 2026
@bryancall bryancall requested a review from Copilot February 23, 2026 21:30
Copy link
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

This PR adds CAP_CHOWN to the permitted capability set to enable plugins to change file ownership, specifically to support TLS certificate management plugins that need to set root:root ownership on backup certificate files.

Changes:

  • Added CAP_CHOWN to the perm_list array in RestrictCapabilities(), making it available in the permitted set (but not the effective set) after privilege drop

cmcfarlen
cmcfarlen previously approved these changes Mar 3, 2026
Copy link
Contributor

@cmcfarlen cmcfarlen left a comment

Choose a reason for hiding this comment

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

Seems ok, but copilot raised some issue.

Add CHOWN_PRIVILEGE (0x10u) to the ElevateAccess privilege_level enum
and wire up CAP_CHOWN in acquirePrivilege() so plugins can elevate
file ownership capability through the standard ATS privilege API.
Copy link
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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

++cap_count;
}

ink_release_assert(cap_count <= sizeof(cap_list));
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The bounds-check assertion at line 471 compares cap_count (the number of capabilities, max 4) against sizeof(cap_list) (the byte size of the array, which is 4 * sizeof(cap_value_t) = 16 bytes on typical platforms). This means the assertion is effectively cap_count <= 16, which will never catch an actual out-of-bounds write. It should use the element count instead: cap_count <= sizeof(cap_list) / sizeof(cap_list[0]).

This PR brings cap_count up to a potential maximum of 4, exactly matching the array dimension, so the array is not overflowed now — but the guard is broken. Any future capability addition will silently overflow cap_list without the assertion firing.

Suggested change
ink_release_assert(cap_count <= sizeof(cap_list));
ink_release_assert(cap_count <= sizeof(cap_list) / sizeof(cap_list[0]));

Copilot uses AI. Check for mistakes.
OWNER_PRIVILEGE = 0x8u ///< Bypass permission checks on operations that normally require
OWNER_PRIVILEGE = 0x8u, ///< Bypass permission checks on operations that normally require
/// filesystem UID & process UID to match
CHOWN_PRIVILEGE = 0x10u ///< Change file ownership
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The CHOWN_PRIVILEGE entry is not aligned to the same column as the other enum values. All previous entries use column-aligned spacing before = to keep the values visually aligned (e.g., FILE_PRIVILEGE = 0x1u, OWNER_PRIVILEGE = 0x8u), but CHOWN_PRIVILEGE = 0x10u has only a single space before =, breaking the alignment pattern.

Suggested change
CHOWN_PRIVILEGE = 0x10u ///< Change file ownership
CHOWN_PRIVILEGE = 0x10u ///< Change file ownership

Copilot uses AI. Check for mistakes.
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