From: Christian Brauner Date: Tue, 12 Oct 2021 14:33:14 +0000 (+0200) Subject: conf: fix lxc.cap.keep behavior X-Git-Tag: lxc-5.0.0~75^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cafcd2a7517529843bbc52c47658b7d3d32b73d6;p=thirdparty%2Flxc.git conf: fix lxc.cap.keep behavior Fixes: ##3993 Fixes: 20ab75789eb9 ("conf: simplify and port caps to new list type") Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 2fc307812..68ab6088e 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -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 diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 45b13b086..a185acc5c 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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); + 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; + + 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 (cap->cap >= numcaps) + if (is_set(cap_bit, keep_bits)) continue; - ret = prctl(PR_CAPBSET_DROP, prctl_arg(cap->cap), prctl_arg(0), + 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; } diff --git a/src/lxc/macro.h b/src/lxc/macro.h index a1d189bbc..ab0950c7e 100644 --- a/src/lxc/macro.h +++ b/src/lxc/macro.h @@ -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 */ diff --git a/src/lxc/pam/pam_cgfs.c b/src/lxc/pam/pam_cgfs.c index 31e671062..477e6c9b4 100644 --- a/src/lxc/pam/pam_cgfs.c +++ b/src/lxc/pam/pam_cgfs.c @@ -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);