tree-wide: use __u32 for capabilities

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2021-10-13 18:51:48 +02:00
parent c5e7fbcadb
commit 7418b27f12
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
7 changed files with 109 additions and 85 deletions

View File

@ -775,10 +775,14 @@ int lxc_attach_remount_sys_proc(void)
static int drop_capabilities(struct attach_context *ctx) static int drop_capabilities(struct attach_context *ctx)
{ {
int last_cap; int ret;
__u32 last_cap;
last_cap = lxc_caps_last_cap(); ret = lxc_caps_last_cap(&last_cap);
for (int cap = 0; cap <= last_cap; cap++) { if (ret)
return ret;
for (__u32 cap = 0; cap <= last_cap; cap++) {
if (ctx->capability_mask & (1LL << cap)) if (ctx->capability_mask & (1LL << cap))
continue; continue;

View File

@ -90,7 +90,7 @@ int lxc_ambient_caps_up(void)
__do_free char *cap_names = NULL; __do_free char *cap_names = NULL;
int ret; int ret;
cap_value_t cap; cap_value_t cap;
int last_cap = CAP_LAST_CAP; cap_value_t last_cap = CAP_LAST_CAP;
if (!getuid() || geteuid()) if (!getuid() || geteuid())
return 0; return 0;
@ -207,55 +207,62 @@ int lxc_caps_init(void)
return 0; return 0;
} }
static long int _real_caps_last_cap(void) static int __caps_last_cap(__u32 *cap)
{ {
__do_close int fd = -EBADF; __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. * 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) { if (fd >= 0) {
ssize_t n; ssize_t ret;
char *ptr; unsigned res;
char buf[INTTYPE_TO_STRLEN(int)] = {0}; char buf[INTTYPE_TO_STRLEN(__u32)] = {0};
n = lxc_read_nointr(fd, buf, STRARRAYLEN(buf)); ret = lxc_read_nointr(fd, buf, STRARRAYLEN(buf));
if (n >= 0) { if (ret <= 0)
errno = 0; return ret_errno(EINVAL);
result = strtol(buf, &ptr, 10);
if (!ptr || (*ptr != '\0' && *ptr != '\n') || errno != 0)
result = -1;
}
close(fd); ret = lxc_safe_uint(buf, &res);
if (ret < 0)
return ret;
*cap = (__u32)res;
} else { } 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. * capability individually from the kernel.
*/ */
while (prctl(PR_CAPBSET_READ, prctl_arg(cap)) >= 0) while (prctl(PR_CAPBSET_READ, prctl_arg(cur_cap)) >= 0)
cap++; 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) { if (ret < 0) {
last_cap = _real_caps_last_cap(); ret = __caps_last_cap(&last_cap);
if (last_cap < 0 || last_cap > INT_MAX) if (ret)
last_cap = -1; 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) static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)

View 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_up(void);
__hidden extern int lxc_ambient_caps_down(void); __hidden extern int lxc_ambient_caps_down(void);
__hidden extern int lxc_caps_init(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_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); __hidden extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag);
#else #else
@ -47,7 +47,7 @@ static inline int lxc_caps_init(void)
return 0; return 0;
} }
static inline int lxc_caps_last_cap(void) static inline int lxc_caps_last_cap(__u32 *cap)
{ {
return 0; return 0;
} }

View File

@ -133,7 +133,7 @@ struct mount_opt {
struct caps_opt { struct caps_opt {
char *name; char *name;
int value; __u32 value;
}; };
struct limit_opt { struct limit_opt {
@ -3097,44 +3097,45 @@ out:
return fret; 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]); 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; return -2;
for (i = 0; i < end; i++) { for (size_t i = 0; i < end; i++) {
if (!strequal(cap, caps_opt[i].name)) if (!strequal(cap_name, caps_opt[i].name))
continue; continue;
capid = caps_opt[i].value; *cap = caps_opt[i].value;
break; return 0;
} }
if (capid < 0) { /*
/* Try to see if it's numeric, so the user may specify * Try to see if it's numeric, so the user may specify
* capabilities that the running kernel knows about but we * capabilities that the running kernel knows about but we
* don't * don't.
*/ */
errno = 0; ret = lxc_safe_uint(cap_name, &res);
capid = strtol(cap, &ptr, 10); if (ret < 0)
if (!ptr || *ptr != '\0' || errno != 0) return -1;
/* 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; 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; bool cap_in_list = false;
struct cap_entry *cap_entry; 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) static int capabilities_allow(struct lxc_conf *conf)
{ {
__do_free __u32 *keep_bits = NULL; __do_free __u32 *keep_bits = NULL;
__s32 numcaps; int ret;
struct cap_entry *cap; struct cap_entry *cap;
size_t nr_u32; __u32 last_cap, nr_u32;
numcaps = lxc_caps_last_cap(); ret = lxc_caps_last_cap(&last_cap);
if (numcaps <= 0 || numcaps > 200) if (ret || last_cap > 200)
return ret_errno(EINVAL); 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)); keep_bits = zalloc(nr_u32 * sizeof(__u32));
if (!keep_bits) if (!keep_bits)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
list_for_each_entry(cap, &conf->caps.list, head) { list_for_each_entry(cap, &conf->caps.list, head) {
if (cap->cap > numcaps) if (cap->cap > last_cap)
continue; continue;
set_bit(cap->cap, keep_bits); set_bit(cap->cap, keep_bits);
DEBUG("Keeping %s (%d) capability", cap->cap_name, cap->cap); DEBUG("Keeping %s (%d) capability", cap->cap_name, cap->cap);
} }
for (__s32 cap_bit = 0; cap_bit <= numcaps; cap_bit++) { for (__u32 cap_bit = 0; cap_bit <= last_cap; cap_bit++) {
int ret;
if (is_set(cap_bit, keep_bits)) if (is_set(cap_bit, keep_bits))
continue; continue;
@ -4267,7 +4266,7 @@ int lxc_sync_fds_child(struct lxc_handler *handler)
return 0; return 0;
} }
static int setcup_capabilities(struct lxc_conf *conf) static int setup_capabilities(struct lxc_conf *conf)
{ {
int ret; int ret;
@ -4423,7 +4422,7 @@ int lxc_setup(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
return log_error(-1, "Failed to setup sysctl parameters"); return log_error(-1, "Failed to setup sysctl parameters");
ret = setcup_capabilities(lxc_conf); ret = setup_capabilities(lxc_conf);
if (ret < 0) if (ret < 0)
return log_error(-1, "Failed to setup capabilities"); return log_error(-1, "Failed to setup capabilities");

View File

@ -343,7 +343,7 @@ struct environment_entry {
struct cap_entry { struct cap_entry {
char *cap_name; char *cap_name;
int cap; __u32 cap;
struct list_head head; 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, __hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section,
const char *script, const char *hookname, char **argsin); const char *script, const char *hookname, char **argsin);
__hidden extern bool has_cap(int cap, struct lxc_conf *conf); __hidden extern bool has_cap(__u32 cap, struct lxc_conf *conf);
static inline bool lxc_wants_cap(int 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 false;
return has_cap(cap, conf); 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 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 */ #endif /* __LXC_CONF_H */

View File

@ -2390,7 +2390,8 @@ static int add_cap_entry(struct lxc_conf *conf, char *caps, bool keep)
*/ */
lxc_iterate_parts(token, caps, " \t") { lxc_iterate_parts(token, caps, " \t") {
__do_free struct cap_entry *new_cap = NULL; __do_free struct cap_entry *new_cap = NULL;
int cap; int ret;
__u32 cap;
if (strequal(token, "none")) { if (strequal(token, "none")) {
if (!keep) if (!keep)
@ -2400,9 +2401,9 @@ static int add_cap_entry(struct lxc_conf *conf, char *caps, bool keep)
continue; continue;
} }
cap = parse_cap(token); ret = parse_cap(token, &cap);
if (cap < 0) { if (ret < 0) {
if (cap != -2) if (ret != -2)
return syserror_set(-EINVAL, "Invalid capability specified"); return syserror_set(-EINVAL, "Invalid capability specified");
INFO("Ignoring unknown capability \"%s\"", token); INFO("Ignoring unknown capability \"%s\"", token);

View File

@ -40,10 +40,16 @@
#if HAVE_LIBCAP #if HAVE_LIBCAP
static int capabilities_allow(void *payload) static int capabilities_allow(void *payload)
{ {
int last_cap; int ret;
__u32 last_cap;
last_cap = lxc_caps_last_cap(); ret = lxc_caps_last_cap(&last_cap);
for (int cap = 0; cap <= last_cap; cap++) { if (ret) {
lxc_error("%s\n", "Failed to retrieve last capability");
return EXIT_FAILURE;
}
for (__u32 cap = 0; cap <= last_cap; cap++) {
bool bret; bool bret;
if (cap == CAP_MKNOD) if (cap == CAP_MKNOD)