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;
__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;
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)
__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
return 0;
}
-static inline int lxc_caps_last_cap(void)
+static inline int lxc_caps_last_cap(__u32 *cap)
{
return 0;
}
struct caps_opt {
char *name;
- int value;
+ __u32 value;
};
struct limit_opt {
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;
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;
return 0;
}
-static int setcup_capabilities(struct lxc_conf *conf)
+static int setup_capabilities(struct lxc_conf *conf)
{
int ret;
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");
struct cap_entry {
char *cap_name;
- int cap;
+ __u32 cap;
struct list_head head;
};
__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);
}
__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 */
*/
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)
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);
#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)