]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: capabilities: use _LINUX_CAPABILITY_VERSION_3
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Fri, 21 Jun 2024 23:03:38 +0000 (01:03 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 26 Jun 2024 05:38:21 +0000 (07:38 +0200)
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

index 6c2e5eb65039cdb3ba4d3a4fa5163934c056e117..266467b0d159e841f9856af22006c47befae4ef2 100644 (file)
@@ -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;