2
0
mirror of git://github.com/lxc/lxc synced 2025-08-31 21:29:27 +00:00

conf: fix lxc.cap.keep behavior

Fixes: ##3993
Fixes: 20ab75789e ("conf: simplify and port caps to new list type")
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner
2021-10-12 16:33:14 +02:00
parent 8305ff8ab0
commit cafcd2a751
4 changed files with 46 additions and 50 deletions

View File

@@ -178,26 +178,6 @@ int prepare_cgroup_fd(const struct cgroup_ops *ops, struct cgroup_fd *fd, bool l
return 0;
}
/* Taken over modified from the kernel sources. */
#define NBITS 32 /* bits in uint32_t */
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS)
static void set_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] |= (1 << (bit % NBITS));
}
static void clear_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] &= ~(1 << (bit % NBITS));
}
static bool is_set(unsigned bit, uint32_t *bitarr)
{
return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0;
}
/* Create cpumask from cpulist aka turn:
*
* 0,2-3

View File

@@ -3154,7 +3154,7 @@ bool has_cap(int cap, struct lxc_conf *conf)
return !cap_in_list;
}
static int setup_caps(struct lxc_conf *conf)
static int capabilities_deny(struct lxc_conf *conf)
{
struct cap_entry *cap;
@@ -3164,7 +3164,7 @@ static int setup_caps(struct lxc_conf *conf)
ret = prctl(PR_CAPBSET_DROP, prctl_arg(cap->cap), prctl_arg(0),
prctl_arg(0), prctl_arg(0));
if (ret < 0)
return log_error_errno(-1, errno, "Failed to remove %s capability", cap->cap_name);
return syserror("Failed to remove %s capability", cap->cap_name);
DEBUG("Dropped %s (%d) capability", cap->cap_name, cap->cap);
}
@@ -3173,10 +3173,12 @@ static int setup_caps(struct lxc_conf *conf)
return 0;
}
static int dropcaps_except(struct lxc_conf *conf)
static int capabilities_allow(struct lxc_conf *conf)
{
__do_free __u32 *keep_bits = NULL;
int numcaps;
struct cap_entry *cap;
size_t nr_u32;
numcaps = lxc_caps_last_cap() + 1;
if (numcaps <= 0 || numcaps > 200)
@@ -3184,20 +3186,31 @@ static int dropcaps_except(struct lxc_conf *conf)
TRACE("Found %d capabilities", numcaps);
list_for_each_entry(cap, &conf->caps.list, head) {
int ret;
nr_u32 = BITS_TO_LONGS(numcaps);
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)
continue;
ret = prctl(PR_CAPBSET_DROP, prctl_arg(cap->cap), prctl_arg(0),
set_bit(cap->cap, keep_bits);
DEBUG("Keeping %s (%d) capability", cap->cap_name, cap->cap);
}
for (int cap_bit = 0; cap_bit < numcaps; cap_bit++) {
int ret;
if (is_set(cap_bit, keep_bits))
continue;
ret = prctl(PR_CAPBSET_DROP, prctl_arg(cap_bit), prctl_arg(0),
prctl_arg(0), prctl_arg(0));
if (ret < 0)
return log_error_errno(-1, errno,
"Failed to remove capability %s (%d)",
cap->cap_name, cap->cap);
return syserror("Failed to remove capability %d", cap_bit);
DEBUG("Keep capability %s (%d)", cap->cap_name, cap->cap);
TRACE("Dropped capability %d", cap_bit);
}
DEBUG("Capabilities have been setup");
@@ -4259,11 +4272,11 @@ static int setcup_capabilities(struct lxc_conf *conf)
int ret;
if (conf->caps.keep)
ret = dropcaps_except(conf);
ret = capabilities_allow(conf);
else
ret = setup_caps(conf);
ret = capabilities_deny(conf);
if (ret < 0)
return log_error(-1, "Failed to %s capabilities", conf->caps.keep ? "keep" : "drop");
return syserror_ret(ret, "Failed to %s capabilities", conf->caps.keep ? "allow" : "deny");
return 0;
}

View File

@@ -765,4 +765,24 @@ static inline bool has_exact_flags(__u32 flags, __u32 mask)
typedef long long unsigned int llu;
/* Taken over modified from the kernel sources. */
#define NBITS 32 /* bits in uint32_t */
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS)
static inline void set_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] |= (1 << (bit % NBITS));
}
static inline void clear_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] &= ~(1 << (bit % NBITS));
}
static inline bool is_set(unsigned bit, uint32_t *bitarr)
{
return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0;
}
#endif /* __LXC_MACRO_H */

View File

@@ -53,11 +53,6 @@
#define pam_cgfs_debug(format, ...)
#endif /* DEBUG */
/* Taken over modified from the kernel sources. */
#define NBITS 32 /* bits in uint32_t */
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS)
static enum cg_mount_mode {
CGROUP_UNKNOWN = -1,
CGROUP_MIXED = 0,
@@ -70,18 +65,10 @@ static enum cg_mount_mode {
static void append_line(char **dest, size_t oldlen, char *new, size_t newlen);
static int append_null_to_list(void ***list);
static void batch_realloc(char **mem, size_t oldlen, size_t newlen);
static inline void clear_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] &= ~(1 << (bit % NBITS));
}
static char *copy_to_eol(char *s);
static char *get_mountpoint(char *line);
static bool get_uid_gid(const char *user, uid_t *uid, gid_t *gid);
static int handle_login(const char *user, uid_t uid, gid_t gid);
static inline bool is_set(unsigned bit, uint32_t *bitarr)
{
return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0;
}
static bool is_lxcfs(const char *line);
static bool is_cgv1(char *line);
static bool is_cgv2(char *line);
@@ -92,10 +79,6 @@ static void must_append_string(char ***list, char *entry);
static void mysyslog(int err, const char *format, ...) __attribute__((sentinel));
static char *read_file(char *fnam);
static int recursive_rmdir(char *dirname);
static inline void set_bit(unsigned bit, uint32_t *bitarr)
{
bitarr[bit / NBITS] |= (1 << (bit % NBITS));
}
static bool string_in_list(char **list, const char *entry);
static char *string_join(const char *sep, const char **parts, bool use_as_prefix);
static void trim(char *s);