]> git.proxmox.com Git - mirror_lxc.git/commitdiff
tree-wide: use __u32 for capabilities
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 13 Oct 2021 16:51:48 +0000 (18:51 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 14 Oct 2021 09:04:06 +0000 (11:04 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/attach.c
src/lxc/caps.c
src/lxc/caps.h
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/tests/capabilities_allow.c

index d6409accb80e224044cf7145c7ee32cc9de4b910..454f39c8bdbc2fcd75ee2f18bbf4f232a174440c 100644 (file)
@@ -775,10 +775,14 @@ int lxc_attach_remount_sys_proc(void)
 
 static int drop_capabilities(struct attach_context *ctx)
 {
-       int last_cap;
+       int ret;
+       __u32 last_cap;
+
+       ret = lxc_caps_last_cap(&last_cap);
+       if (ret)
+               return ret;
 
-       last_cap = lxc_caps_last_cap();
-       for (int cap = 0; cap <= last_cap; cap++) {
+       for (__u32 cap = 0; cap <= last_cap; cap++) {
                if (ctx->capability_mask & (1LL << cap))
                        continue;
 
index 08dd62364f143d267cb67219ab9d3b01e44375fc..2f34a9ca17bf5a4858d1f7d8680802fe8a54f9d1 100644 (file)
@@ -90,7 +90,7 @@ int lxc_ambient_caps_up(void)
        __do_free char *cap_names = NULL;
        int ret;
        cap_value_t cap;
-       int last_cap = CAP_LAST_CAP;
+       cap_value_t last_cap = CAP_LAST_CAP;
 
        if (!getuid() || geteuid())
                return 0;
@@ -207,55 +207,62 @@ int lxc_caps_init(void)
        return 0;
 }
 
-static long int _real_caps_last_cap(void)
+static int __caps_last_cap(__u32 *cap)
 {
        __do_close int fd = -EBADF;
-       __s32 result = -1;
 
-       /* Try to get the maximum capability over the kernel interface
+       /*
+        * Try to get the maximum capability over the kernel interface
         * introduced in v3.2.
         */
-       fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY | O_CLOEXEC);
+       fd = open_at(-EBADF,
+                    "/proc/sys/kernel/cap_last_cap",
+                    PROTECT_OPEN,
+                    PROTECT_LOOKUP_ABSOLUTE,
+                    0);
        if (fd >= 0) {
-               ssize_t n;
-               char *ptr;
-               char buf[INTTYPE_TO_STRLEN(int)] = {0};
-
-               n = lxc_read_nointr(fd, buf, STRARRAYLEN(buf));
-               if (n >= 0) {
-                       errno = 0;
-                       result = strtol(buf, &ptr, 10);
-                       if (!ptr || (*ptr != '\0' && *ptr != '\n') || errno != 0)
-                               result = -1;
-               }
+               ssize_t ret;
+               unsigned res;
+               char buf[INTTYPE_TO_STRLEN(__u32)] = {0};
+
+               ret = lxc_read_nointr(fd, buf, STRARRAYLEN(buf));
+               if (ret <= 0)
+                       return ret_errno(EINVAL);
+
+               ret = lxc_safe_uint(buf, &res);
+               if (ret < 0)
+                       return ret;
 
-               close(fd);
+               *cap = (__u32)res;
        } else {
-               __s32 cap = 0;
+               __u32 cur_cap = 0;
 
-               /* Try to get it manually by trying to get the status of each
+               /*
+                * Try to get it manually by trying to get the status of each
                 * capability individually from the kernel.
                 */
-               while (prctl(PR_CAPBSET_READ, prctl_arg(cap)) >= 0)
-                       cap++;
+               while (prctl(PR_CAPBSET_READ, prctl_arg(cur_cap)) >= 0)
+                       cur_cap++;
 
-               result = cap - 1;
+               *cap = cur_cap - 1;
        }
 
-       return result;
+       return 0;
 }
 
-int lxc_caps_last_cap(void)
+int lxc_caps_last_cap(__u32 *cap)
 {
-       static __s32 last_cap = -1;
+       static int ret = -1;
+       static __u32 last_cap = 0;
 
-       if (last_cap < 0) {
-               last_cap = _real_caps_last_cap();
-               if (last_cap < 0 || last_cap > INT_MAX)
-                       last_cap = -1;
+       if (ret < 0) {
+               ret = __caps_last_cap(&last_cap);
+               if (ret)
+                       return ret;
        }
 
-       return last_cap;
+       *cap = last_cap;
+       return 0;
 }
 
 static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)
index 2f8d802fd6bd07e38d413720b12df572f71e0206..fd1456b810104e0a824e413f58606b63d751eb2c 100644 (file)
@@ -18,7 +18,7 @@ __hidden extern int lxc_caps_up(void);
 __hidden extern int lxc_ambient_caps_up(void);
 __hidden extern int lxc_ambient_caps_down(void);
 __hidden extern int lxc_caps_init(void);
-__hidden extern int lxc_caps_last_cap(void);
+__hidden extern int lxc_caps_last_cap(__u32 *cap);
 __hidden extern bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag);
 __hidden extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag);
 #else
@@ -47,7 +47,7 @@ static inline int lxc_caps_init(void)
        return 0;
 }
 
-static inline int lxc_caps_last_cap(void)
+static inline int lxc_caps_last_cap(__u32 *cap)
 {
        return 0;
 }
index ad4c5ca149ea5c713b30d7d102c53d595cb948cb..db6c0434a59b3153fd9c23c89f08e308bfb7e105 100644 (file)
@@ -133,7 +133,7 @@ struct mount_opt {
 
 struct caps_opt {
        char *name;
-       int value;
+       __u32 value;
 };
 
 struct limit_opt {
@@ -3097,44 +3097,45 @@ out:
        return fret;
 }
 
-int parse_cap(const char *cap)
+int parse_cap(const char *cap_name, __u32 *cap)
 {
-       size_t i;
-       int capid = -1;
        size_t end = sizeof(caps_opt) / sizeof(caps_opt[0]);
-       char *ptr = NULL;
+       int ret;
+       unsigned int res;
+       __u32 last_cap;
 
-       if (strequal(cap, "none"))
+       if (strequal(cap_name, "none"))
                return -2;
 
-       for (i = 0; i < end; i++) {
-               if (!strequal(cap, caps_opt[i].name))
+       for (size_t i = 0; i < end; i++) {
+               if (!strequal(cap_name, caps_opt[i].name))
                        continue;
 
-               capid = caps_opt[i].value;
-               break;
+               *cap = caps_opt[i].value;
+               return 0;
        }
 
-       if (capid < 0) {
-               /* Try to see if it's numeric, so the user may specify
-                * capabilities that the running kernel knows about but we
-                * don't
-                */
-               errno = 0;
-               capid = strtol(cap, &ptr, 10);
-               if (!ptr || *ptr != '\0' || errno != 0)
-                       /* not a valid number */
-                       capid = -1;
-               else if (capid > lxc_caps_last_cap())
-                       /* we have a number but it's not a valid
-                        * capability */
-                       capid = -1;
-       }
-
-       return capid;
+       /*
+        * Try to see if it's numeric, so the user may specify
+        * capabilities that the running kernel knows about but we
+        * don't.
+        */
+       ret = lxc_safe_uint(cap_name, &res);
+       if (ret < 0)
+               return -1;
+
+       ret = lxc_caps_last_cap(&last_cap);
+       if (ret)
+               return -1;
+
+       if ((__u32)res > last_cap)
+               return -1;
+
+       *cap = (__u32)res;
+       return 0;
 }
 
-bool has_cap(int cap, struct lxc_conf *conf)
+bool has_cap(__u32 cap, struct lxc_conf *conf)
 {
        bool cap_in_list = false;
        struct cap_entry *cap_entry;
@@ -3176,32 +3177,30 @@ static int capabilities_deny(struct lxc_conf *conf)
 static int capabilities_allow(struct lxc_conf *conf)
 {
        __do_free __u32 *keep_bits = NULL;
-       __s32 numcaps;
+       int ret;
        struct cap_entry *cap;
-       size_t nr_u32;
+       __u32 last_cap, nr_u32;
 
-       numcaps = lxc_caps_last_cap();
-       if (numcaps <= 0 || numcaps > 200)
+       ret = lxc_caps_last_cap(&last_cap);
+       if (ret || last_cap > 200)
                return ret_errno(EINVAL);
 
-       TRACE("Found %d capabilities", numcaps);
+       TRACE("Found %d capabilities", last_cap);
 
-       nr_u32 = BITS_TO_LONGS(numcaps);
+       nr_u32 = BITS_TO_LONGS(last_cap);
        keep_bits = zalloc(nr_u32 * sizeof(__u32));
        if (!keep_bits)
                return ret_errno(ENOMEM);
 
        list_for_each_entry(cap, &conf->caps.list, head) {
-               if (cap->cap > numcaps)
+               if (cap->cap > last_cap)
                        continue;
 
                set_bit(cap->cap, keep_bits);
                DEBUG("Keeping %s (%d) capability", cap->cap_name, cap->cap);
        }
 
-       for (__s32 cap_bit = 0; cap_bit <= numcaps; cap_bit++) {
-               int ret;
-
+       for (__u32 cap_bit = 0; cap_bit <= last_cap; cap_bit++) {
                if (is_set(cap_bit, keep_bits))
                        continue;
 
@@ -4267,7 +4266,7 @@ int lxc_sync_fds_child(struct lxc_handler *handler)
        return 0;
 }
 
-static int setcup_capabilities(struct lxc_conf *conf)
+static int setup_capabilities(struct lxc_conf *conf)
 {
        int ret;
 
@@ -4423,7 +4422,7 @@ int lxc_setup(struct lxc_handler *handler)
        if (ret < 0)
                return log_error(-1, "Failed to setup sysctl parameters");
 
-       ret = setcup_capabilities(lxc_conf);
+       ret = setup_capabilities(lxc_conf);
        if (ret < 0)
                return log_error(-1, "Failed to setup capabilities");
 
index 12c26d98d7e311aa98f778df827ffca7c670360a..a41b4787e47d442338916e5738b5f5d3730d068d 100644 (file)
@@ -343,7 +343,7 @@ struct environment_entry {
 
 struct cap_entry {
        char *cap_name;
-       int cap;
+       __u32 cap;
        struct list_head head;
 };
 
@@ -579,10 +579,17 @@ __hidden extern int run_script(const char *name, const char *section, const char
 __hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section,
                                    const char *script, const char *hookname, char **argsin);
 
-__hidden extern bool has_cap(int cap, struct lxc_conf *conf);
-static inline bool lxc_wants_cap(int cap, struct lxc_conf *conf)
+__hidden extern bool has_cap(__u32 cap, struct lxc_conf *conf);
+static inline bool lxc_wants_cap(__u32 cap, struct lxc_conf *conf)
 {
-       if (lxc_caps_last_cap() < cap)
+       __u32 last_cap;
+       int ret;
+
+       ret = lxc_caps_last_cap(&last_cap);
+       if (ret)
+               return false;
+
+       if (last_cap < cap)
                return false;
 
        return has_cap(cap, conf);
@@ -662,6 +669,6 @@ static inline int lxc_personality(personality_t persona)
 }
 
 __hidden extern int lxc_set_environment(const struct lxc_conf *conf);
-__hidden extern int parse_cap(const char *cap);
+__hidden extern int parse_cap(const char *cap_name, __u32 *cap);
 
 #endif /* __LXC_CONF_H */
index 5d2c99f8ae1dc2712ded09e56f0c545dc02fb08d..fafcc7ba947b3a2054abbcdb3c34e771472e7b61 100644 (file)
@@ -2390,7 +2390,8 @@ static int add_cap_entry(struct lxc_conf *conf, char *caps, bool keep)
         */
        lxc_iterate_parts(token, caps, " \t") {
                __do_free struct cap_entry *new_cap = NULL;
-               int cap;
+               int ret;
+               __u32 cap;
 
                if (strequal(token, "none")) {
                        if (!keep)
@@ -2400,9 +2401,9 @@ static int add_cap_entry(struct lxc_conf *conf, char *caps, bool keep)
                        continue;
                }
 
-               cap = parse_cap(token);
-               if (cap < 0) {
-                       if (cap != -2)
+               ret = parse_cap(token, &cap);
+               if (ret < 0) {
+                       if (ret != -2)
                                return syserror_set(-EINVAL, "Invalid capability specified");
 
                        INFO("Ignoring unknown capability \"%s\"", token);
index 643a4e8503ab1460fb573da48c8a790643d4b681..24b57ed78b6fa055933838e465e68e85af18257c 100644 (file)
 #if HAVE_LIBCAP
 static int capabilities_allow(void *payload)
 {
-       int last_cap;
+       int ret;
+       __u32 last_cap;
+
+       ret = lxc_caps_last_cap(&last_cap);
+       if (ret) {
+               lxc_error("%s\n", "Failed to retrieve last capability");
+               return EXIT_FAILURE;
+       }
 
-       last_cap = lxc_caps_last_cap();
-       for (int cap = 0; cap <= last_cap; cap++) {
+       for (__u32 cap = 0; cap <= last_cap; cap++) {
                bool bret;
 
                if (cap == CAP_MKNOD)