From fba9ade8910510151b5d6141c6594da789d6a71b Mon Sep 17 00:00:00 2001 From: Valentine Krasnobaeva Date: Sat, 22 Jun 2024 01:03:38 +0200 Subject: [PATCH] MINOR: capabilities: use _LINUX_CAPABILITY_VERSION_3 Linux kernel shows the warning below, when _LINUX_CAPABILITY_VERSION_1 is used in capset() and capget(). [1710243.523230] capability: warning: `haproxy' uses 32-bit capabilities (legacy support in use) This triggers questions from users. Warning is shown by kernel, because since Linux 2.6.25, 64-bit capabilities support was introduced in _LINUX_CAPABILITY_VERSION_2. It's in order to be able to continiously extend capabilities list with the new ones. We can't use _LINUX_CAPABILITY_VERSION_2, because this version triggers another warning, according linux/kernel/capability.c (see also more details about it in comments from kernel sources and in man capset(2)). kernel/capability.c: ... static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) { __u32 version; if (get_user(version, &header->version)) return -EFAULT; switch (version) { case _LINUX_CAPABILITY_VERSION_1: warn_legacy_capability_use(); *tocopy = _LINUX_CAPABILITY_U32S_1; break; case _LINUX_CAPABILITY_VERSION_2: warn_deprecated_v2(); fallthrough; /* v3 is otherwise equivalent to v2 */ case _LINUX_CAPABILITY_VERSION_3: *tocopy = _LINUX_CAPABILITY_U32S_3; break; default: ... So, to avoid any warnings, lets use _LINUX_CAPABILITY_VERSION_3, which according to comments in linux/kernel/capability.c, has the same functionality as _LINUX_CAPABILITY_VERSION_2 (i.e. array of 2 __user_cap_data_struct with 32-bits integers for each capability set), but comes in Linux 2.6.26 with a header change, in order to protect legacy source code. For the moment, we don't authorize capabilities higher, than CAP_SYS_ADMIN (21-st bit), so we always check the "low" 32 bits, i.e. __user_cap_data_struct[0]. --- src/linuxcap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/linuxcap.c b/src/linuxcap.c index 6c2e5eb65..266467b0d 100644 --- a/src/linuxcap.c +++ b/src/linuxcap.c @@ -28,7 +28,7 @@ struct __user_cap_header_struct cap_hdr_haproxy = { .pid = 0, /* current process */ - .version = _LINUX_CAPABILITY_VERSION_1, + .version = _LINUX_CAPABILITY_VERSION_3, }; /* supported names, zero-terminated */ @@ -87,7 +87,7 @@ int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *progra * only _LINUX_CAPABILITY_U32S_1 * (sizeof(struct __user_cap_data_struct)), * i.e. only the __user_cap_data_struct[0]. */ - struct __user_cap_data_struct start_cap_data[_LINUX_CAPABILITY_U32S_1] = { }; + struct __user_cap_data_struct start_cap_data[_LINUX_CAPABILITY_U32S_3] = { }; /* started as root */ if (!from_uid) @@ -162,7 +162,7 @@ int prepare_caps_for_setuid(int from_uid, int to_uid) * only _LINUX_CAPABILITY_U32S_1 * (sizeof(struct __user_cap_data_struct)), * i.e. only the __user_cap_data_struct[0]. */ - struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_1] = { }; + struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3] = { }; if (from_uid != 0) return 0; @@ -211,7 +211,7 @@ int prepare_caps_for_setuid(int from_uid, int to_uid) */ int finalize_caps_after_setuid(int from_uid, int to_uid) { - struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_1] = { }; + struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3] = { }; if (from_uid != 0) return 0;