mirror of
git://github.com/lxc/lxc
synced 2025-09-02 12:09:33 +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:
@@ -178,26 +178,6 @@ int prepare_cgroup_fd(const struct cgroup_ops *ops, struct cgroup_fd *fd, bool l
|
|||||||
return 0;
|
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:
|
/* Create cpumask from cpulist aka turn:
|
||||||
*
|
*
|
||||||
* 0,2-3
|
* 0,2-3
|
||||||
|
@@ -3154,7 +3154,7 @@ bool has_cap(int cap, struct lxc_conf *conf)
|
|||||||
return !cap_in_list;
|
return !cap_in_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_caps(struct lxc_conf *conf)
|
static int capabilities_deny(struct lxc_conf *conf)
|
||||||
{
|
{
|
||||||
struct cap_entry *cap;
|
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),
|
ret = prctl(PR_CAPBSET_DROP, prctl_arg(cap->cap), prctl_arg(0),
|
||||||
prctl_arg(0), prctl_arg(0));
|
prctl_arg(0), prctl_arg(0));
|
||||||
if (ret < 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);
|
DEBUG("Dropped %s (%d) capability", cap->cap_name, cap->cap);
|
||||||
}
|
}
|
||||||
@@ -3173,10 +3173,12 @@ static int setup_caps(struct lxc_conf *conf)
|
|||||||
return 0;
|
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;
|
int numcaps;
|
||||||
struct cap_entry *cap;
|
struct cap_entry *cap;
|
||||||
|
size_t nr_u32;
|
||||||
|
|
||||||
numcaps = lxc_caps_last_cap() + 1;
|
numcaps = lxc_caps_last_cap() + 1;
|
||||||
if (numcaps <= 0 || numcaps > 200)
|
if (numcaps <= 0 || numcaps > 200)
|
||||||
@@ -3184,20 +3186,31 @@ static int dropcaps_except(struct lxc_conf *conf)
|
|||||||
|
|
||||||
TRACE("Found %d capabilities", numcaps);
|
TRACE("Found %d capabilities", numcaps);
|
||||||
|
|
||||||
list_for_each_entry(cap, &conf->caps.list, head) {
|
nr_u32 = BITS_TO_LONGS(numcaps);
|
||||||
int ret;
|
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 >= numcaps)
|
||||||
continue;
|
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));
|
prctl_arg(0), prctl_arg(0));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_error_errno(-1, errno,
|
return syserror("Failed to remove capability %d", cap_bit);
|
||||||
"Failed to remove capability %s (%d)",
|
|
||||||
cap->cap_name, cap->cap);
|
|
||||||
|
|
||||||
DEBUG("Keep capability %s (%d)", cap->cap_name, cap->cap);
|
TRACE("Dropped capability %d", cap_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Capabilities have been setup");
|
DEBUG("Capabilities have been setup");
|
||||||
@@ -4259,11 +4272,11 @@ static int setcup_capabilities(struct lxc_conf *conf)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (conf->caps.keep)
|
if (conf->caps.keep)
|
||||||
ret = dropcaps_except(conf);
|
ret = capabilities_allow(conf);
|
||||||
else
|
else
|
||||||
ret = setup_caps(conf);
|
ret = capabilities_deny(conf);
|
||||||
if (ret < 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -765,4 +765,24 @@ static inline bool has_exact_flags(__u32 flags, __u32 mask)
|
|||||||
|
|
||||||
typedef long long unsigned int llu;
|
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 */
|
#endif /* __LXC_MACRO_H */
|
||||||
|
@@ -53,11 +53,6 @@
|
|||||||
#define pam_cgfs_debug(format, ...)
|
#define pam_cgfs_debug(format, ...)
|
||||||
#endif /* DEBUG */
|
#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 {
|
static enum cg_mount_mode {
|
||||||
CGROUP_UNKNOWN = -1,
|
CGROUP_UNKNOWN = -1,
|
||||||
CGROUP_MIXED = 0,
|
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 void append_line(char **dest, size_t oldlen, char *new, size_t newlen);
|
||||||
static int append_null_to_list(void ***list);
|
static int append_null_to_list(void ***list);
|
||||||
static void batch_realloc(char **mem, size_t oldlen, size_t newlen);
|
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 *copy_to_eol(char *s);
|
||||||
static char *get_mountpoint(char *line);
|
static char *get_mountpoint(char *line);
|
||||||
static bool get_uid_gid(const char *user, uid_t *uid, gid_t *gid);
|
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 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_lxcfs(const char *line);
|
||||||
static bool is_cgv1(char *line);
|
static bool is_cgv1(char *line);
|
||||||
static bool is_cgv2(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 void mysyslog(int err, const char *format, ...) __attribute__((sentinel));
|
||||||
static char *read_file(char *fnam);
|
static char *read_file(char *fnam);
|
||||||
static int recursive_rmdir(char *dirname);
|
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 bool string_in_list(char **list, const char *entry);
|
||||||
static char *string_join(const char *sep, const char **parts, bool use_as_prefix);
|
static char *string_join(const char *sep, const char **parts, bool use_as_prefix);
|
||||||
static void trim(char *s);
|
static void trim(char *s);
|
||||||
|
Reference in New Issue
Block a user