]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: capabilities: export capget and __user_cap_header_struct
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Fri, 31 May 2024 16:01:07 +0000 (18:01 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 26 Jun 2024 05:38:21 +0000 (07:38 +0200)
To be able to show process capabilities before applying its configuration and
also at runtime in 'show dev' command output, we need to export the wrapper
around capget() syscall. It also seems more handy to place
__user_cap_header_struct in .data section and declare it as globally
accessible, as we always fill it with the same values. This avoids allocate
and fill these 8 bytes each time on the stack frame, when capget() or capset()
wrappers are called.

include/haproxy/linuxcap.h
src/linuxcap.c

index 9395b7b1ec1149e2c2b15b74a0f77b72d0616b27..34d4d9a6b3ef84a0e799b14f244739419881a51b 100644 (file)
@@ -1,6 +1,23 @@
 #ifndef _HAPROXY_LINUXCAP_H
 #define _HAPROXY_LINUXCAP_H
+#include <syscall.h>
+#include <linux/capability.h>
 
+/* for haproxy process itself, allocate this 8 byte-size struct only once in
+ * .data and makes it accessible from other compile-units, because we always
+ * fill it with the same values and because we could use it to collect
+ * capabilities for post_mortem debug info.
+ */
+extern struct __user_cap_header_struct cap_hdr_haproxy;
+
+/* provided by sys/capability.h on some distros, declared here, as could be used
+ * in debug.c, in order to collect info about process capabilities before
+ * applying its configuration and at runtime.
+ */
+static inline int capget(cap_user_header_t hdrp, const cap_user_data_t datap)
+{
+       return syscall(SYS_capget, hdrp, datap);
+}
 int prepare_caps_for_setuid(int from_uid, int to_uid);
 int finalize_caps_after_setuid(int from_uid, int to_uid);
 int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *program_name);
index 63a510f226e92d4e6a6caa60c71c801fe0c604d5..1e87aed6932bce83d4c79124a5f23a4a42d819dc 100644 (file)
@@ -14,7 +14,6 @@
  * libcap. Let's stick to what we need and the kernel documents (capset).
  * Note that prctl is needed here.
  */
-#include <linux/capability.h>
 #include <sys/prctl.h>
 #include <errno.h>
 #include <unistd.h>
 #include <haproxy/cfgparse.h>
 #include <haproxy/errors.h>
 #include <haproxy/global.h>
+#include <haproxy/linuxcap.h>
 #include <haproxy/tools.h>
 
+struct __user_cap_header_struct cap_hdr_haproxy = {
+       .pid = 0, /* current process */
+       .version = _LINUX_CAPABILITY_VERSION_1,
+};
+
 /* supported names, zero-terminated */
 static const struct {
        int cap;
@@ -47,12 +52,6 @@ static const struct {
        { 0, 0 }
 };
 
-/* provided by sys/capability.h on some distros */
-static inline int capget(cap_user_header_t hdrp, const cap_user_data_t datap)
-{
-       return syscall(SYS_capget, hdrp, datap);
-}
-
 /* provided by sys/capability.h on some distros */
 static inline int capset(cap_user_header_t hdrp, const cap_user_data_t datap)
 {
@@ -84,10 +83,6 @@ static uint32_t caplist;
 int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *program_name)
 {
        struct __user_cap_data_struct start_cap_data = { };
-       struct __user_cap_header_struct cap_hdr = {
-               .pid = 0, /* current process */
-               .version = _LINUX_CAPABILITY_VERSION_1,
-       };
 
        /* started as root */
        if (!from_uid)
@@ -102,7 +97,7 @@ int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *progra
         * these capabilities and the file effective bit on haproxy binary via
         * setcap, see capabilities man page for details.
         */
-       if (capget(&cap_hdr, &start_cap_data) == -1) {
+       if (capget(&cap_hdr_haproxy, &start_cap_data) == -1) {
                if (global.last_checks & (LSTCHK_NETADM | LSTCHK_SYSADM))
                        ha_diag_warning("Failed to get process capabilities using capget(): %s. "
                                        "Can't use capabilities that might be set on %s binary "
@@ -127,7 +122,7 @@ int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *progra
         */
        if (caplist && start_cap_data.permitted & caplist) {
                start_cap_data.effective |= start_cap_data.permitted & caplist;
-               if (capset(&cap_hdr, &start_cap_data) == 0) {
+               if (capset(&cap_hdr_haproxy, &start_cap_data) == 0) {
                        if (caplist & ((1 << CAP_NET_ADMIN)|(1 << CAP_NET_RAW)))
                                global.last_checks &= ~LSTCHK_NETADM;
                        if (caplist & (1 << CAP_SYS_ADMIN))
@@ -158,10 +153,6 @@ int prepare_caps_from_permitted_set(int from_uid, int to_uid, const char *progra
 int prepare_caps_for_setuid(int from_uid, int to_uid)
 {
        struct __user_cap_data_struct cap_data = { };
-       struct __user_cap_header_struct cap_hdr = {
-               .pid = 0, /* current process */
-               .version = _LINUX_CAPABILITY_VERSION_1,
-       };
 
        if (from_uid != 0)
                return 0;
@@ -178,7 +169,7 @@ int prepare_caps_for_setuid(int from_uid, int to_uid)
        }
 
        cap_data.effective = cap_data.permitted = caplist | (1 << CAP_SETUID);
-       if (capset(&cap_hdr, &cap_data) == -1) {
+       if (capset(&cap_hdr_haproxy, &cap_data) == -1) {
                ha_alert("Failed to preset the capabilities to preserve using capset(): %s\n", strerror(errno));
                return -1;
        }
@@ -189,7 +180,7 @@ int prepare_caps_for_setuid(int from_uid, int to_uid)
        }
 
        cap_data.effective = cap_data.permitted = caplist | (1 << CAP_SETUID);
-       if (capset(&cap_hdr, &cap_data) == -1) {
+       if (capset(&cap_hdr_haproxy, &cap_data) == -1) {
                ha_alert("Failed to set the final capabilities using capset(): %s\n", strerror(errno));
                return -1;
        }
@@ -211,10 +202,6 @@ 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 = { };
-       struct __user_cap_header_struct cap_hdr = {
-               .pid = 0, /* current process */
-               .version = _LINUX_CAPABILITY_VERSION_1,
-       };
 
        if (from_uid != 0)
                return 0;
@@ -226,7 +213,7 @@ int finalize_caps_after_setuid(int from_uid, int to_uid)
                return 0;
 
        cap_data.effective = cap_data.permitted = caplist;
-       if (capset(&cap_hdr, &cap_data) == -1) {
+       if (capset(&cap_hdr_haproxy, &cap_data) == -1) {
                ha_alert("Failed to drop the setuid capability using capset(): %s\n", strerror(errno));
                return -1;
        }