mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-12 03:41:13 +00:00
tree-wide: use __u32 for capabilities
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
parent
c5e7fbcadb
commit
7418b27f12
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user