This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new eeb4600d1d Add CAP_CHOWN to permitted capability set (#12908)
eeb4600d1d is described below
commit eeb4600d1dc03052699403893a62e6f04d189af3
Author: Bryan Call <[email protected]>
AuthorDate: Wed Mar 18 12:17:41 2026 -0700
Add CAP_CHOWN to permitted capability set (#12908)
Add CAP_CHOWN support to ATS privilege elevation path
Retain `CAP_CHOWN` in the permitted capability set after privilege drop
so plugins can set ownership on cert-related backup files (e.g. root:root
600 workflows). As with `CAP_DAC_OVERRIDE`, this remains permitted-only
and must be explicitly raised to effective before use.
Add `CHOWN_PRIVILEGE` (`0x10u`) to `ElevateAccess::privilege_level` and
wire it through `acquirePrivilege()` so plugins can request ownership
elevation via the standard ATS privilege API.
Also fix the `acquirePrivilege()` bounds assertion to compare against
array element count (not byte size).
---
include/tscore/ink_cap.h | 4 ++--
src/tscore/ink_cap.cc | 11 ++++++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/include/tscore/ink_cap.h b/include/tscore/ink_cap.h
index 86a8f31f4d..a18c3449ac 100644
--- a/include/tscore/ink_cap.h
+++ b/include/tscore/ink_cap.h
@@ -81,8 +81,8 @@ public:
FILE_PRIVILEGE = 0x1u, ///< Access filesystem objects with privilege
TRACE_PRIVILEGE = 0x2u, ///< Trace other processes with privilege
LOW_PORT_PRIVILEGE = 0x4u, ///< Bind to privilege ports.
- OWNER_PRIVILEGE = 0x8u ///< Bypass permission checks on operations
that normally require
- /// filesystem UID & process UID to match
+ OWNER_PRIVILEGE = 0x8u, ///< Owner-only operations on unowned files
(CAP_FOWNER)
+ CHOWN_PRIVILEGE = 0x10u ///< Change file ownership
};
ElevateAccess(unsigned level = FILE_PRIVILEGE);
diff --git a/src/tscore/ink_cap.cc b/src/tscore/ink_cap.cc
index f464daad3b..1e208f34cf 100644
--- a/src/tscore/ink_cap.cc
+++ b/src/tscore/ink_cap.cc
@@ -273,7 +273,7 @@ RestrictCapabilities()
cap_t caps_orig = cap_get_proc();
// Capabilities we need.
- cap_value_t perm_list[] = {CAP_NET_ADMIN, CAP_NET_BIND_SERVICE,
CAP_IPC_LOCK, CAP_DAC_OVERRIDE, CAP_FOWNER};
+ cap_value_t perm_list[] = {CAP_NET_ADMIN, CAP_NET_BIND_SERVICE,
CAP_IPC_LOCK, CAP_DAC_OVERRIDE, CAP_FOWNER, CAP_CHOWN};
static int const PERM_CAP_COUNT = sizeof(perm_list) / sizeof(*perm_list);
cap_value_t eff_list[] = {CAP_NET_ADMIN, CAP_NET_BIND_SERVICE,
CAP_IPC_LOCK};
static int const EFF_CAP_COUNT = sizeof(eff_list) / sizeof(*eff_list);
@@ -436,7 +436,7 @@ void
ElevateAccess::acquirePrivilege(unsigned priv_mask)
{
unsigned cap_count = 0;
- cap_value_t cap_list[3];
+ cap_value_t cap_list[4];
cap_t new_cap_state;
Dbg(dbg_ctl_privileges, "[acquirePrivilege] level= %x", level);
@@ -463,7 +463,12 @@ ElevateAccess::acquirePrivilege(unsigned priv_mask)
++cap_count;
}
- ink_release_assert(cap_count <= sizeof(cap_list));
+ if (priv_mask & ElevateAccess::CHOWN_PRIVILEGE) {
+ cap_list[cap_count] = CAP_CHOWN;
+ ++cap_count;
+ }
+
+ ink_release_assert(cap_count <= sizeof(cap_list) / sizeof(cap_list[0]));
if (cap_count > 0) {
this->cap_state = cap_get_proc(); // save current capabilities