]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: fix lxc.cap.keep behavior
authorChristian Brauner <christian.brauner@ubuntu.com>
Tue, 12 Oct 2021 14:33:14 +0000 (16:33 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 12 Oct 2021 14:33:14 +0000 (16:33 +0200)
Fixes: ##3993
Fixes: 20ab75789eb9 ("conf: simplify and port caps to new list type")
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/conf.c
src/lxc/macro.h
src/lxc/pam/pam_cgfs.c

index 2fc30781295fc04e036c43d1fe830f5659d74d7e..68ab6088e46770f120d053a61a733042d06aa714 100644 (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
index 45b13b0862a62b0a0898836416ecb19977f8b3ae..a185acc5cbd4dd6334375b00663a452214a30e06 100644 (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);
 
+       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;
 }
index a1d189bbce00a29d9faef9855191cc04b81ee381..ab0950c7ef860c1d3d5ec815ea4adef473d3532b 100644 (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 */
index 31e671062ff5e965cd9d6fc6615bb4d864244c84..477e6c9b4e9bfac4ae18e8c4f63d898f553af2bb 100644 (file)
 #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);