From: Christian Brauner Date: Wed, 13 Oct 2021 16:51:48 +0000 (+0200) Subject: tree-wide: use __u32 for capabilities X-Git-Tag: lxc-5.0.0~74^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7418b27f1;p=thirdparty%2Flxc.git tree-wide: use __u32 for capabilities Signed-off-by: Christian Brauner --- diff --git a/src/lxc/attach.c b/src/lxc/attach.c index d6409accb..454f39c8b 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -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; diff --git a/src/lxc/caps.c b/src/lxc/caps.c index 08dd62364..2f34a9ca1 100644 --- a/src/lxc/caps.c +++ b/src/lxc/caps.c @@ -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) diff --git a/src/lxc/caps.h b/src/lxc/caps.h index 2f8d802fd..fd1456b81 100644 --- a/src/lxc/caps.h +++ b/src/lxc/caps.h @@ -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; } diff --git a/src/lxc/conf.c b/src/lxc/conf.c index ad4c5ca14..db6c0434a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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"); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 12c26d98d..a41b4787e 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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 */ diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 5d2c99f8a..fafcc7ba9 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -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); diff --git a/src/tests/capabilities_allow.c b/src/tests/capabilities_allow.c index 643a4e850..24b57ed78 100644 --- a/src/tests/capabilities_allow.c +++ b/src/tests/capabilities_allow.c @@ -40,10 +40,16 @@ #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)