]> git.proxmox.com Git - mirror_lxc.git/commitdiff
caps: add lxc_{proc,file}_cap_is_set()
authorChristian Brauner <christian.brauner@ubuntu.com>
Sat, 15 Apr 2017 13:00:14 +0000 (15:00 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sat, 15 Apr 2017 20:50:50 +0000 (22:50 +0200)
Add two new helpers that allow to determine whether a given proc or file has a
capability in the given set and move lxc_cap_is_set() to static function that
both call internally.

Closes #296.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/caps.c
src/lxc/caps.h
src/lxc/start.c

index 1d46c4567ca03eafcabe9f41aac47920993dfd7f..705ac9446d05d14cb3924c2b24c20bd9e7ec3783 100644 (file)
@@ -209,27 +209,56 @@ int lxc_caps_last_cap(void)
        return last_cap;
 }
 
-bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag)
+static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)
 {
        int ret;
-       cap_t caps;
        cap_flag_value_t flagval;
 
-       caps = cap_get_proc();
+       ret = cap_get_flag(caps, cap, flag, &flagval);
+       if (ret < 0) {
+               ERROR("Failed to perform cap_get_flag(): %s.", strerror(errno));
+               return false;
+       }
+
+       return flagval == CAP_SET;
+}
+
+bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
+{
+       bool cap_is_set;
+       cap_t caps;
+
+       caps = cap_get_file(path);
        if (!caps) {
-               ERROR("Failed to perform cap_get_proc(): %s.", strerror(errno));
+               /* This is undocumented in the manpage but the source code show
+                * that cap_get_file() may return NULL when successful for the
+                * case where it didn't detect any file capabilities. In this
+                * case errno will be set to ENODATA.
+                */
+               if (errno != ENODATA)
+                       ERROR("Failed to perform cap_get_file(): %s.\n", strerror(errno));
                return false;
        }
 
-       ret = cap_get_flag(caps, cap, flag, &flagval);
-       if (ret < 0) {
-               ERROR("Failed to perform cap_get_flag(): %s.", strerror(errno));
-               cap_free(caps);
+       cap_is_set = lxc_cap_is_set(caps, cap, flag);
+       cap_free(caps);
+       return cap_is_set;
+}
+
+bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
+{
+       bool cap_is_set;
+       cap_t caps;
+
+       caps = cap_get_proc();
+       if (!caps) {
+               ERROR("Failed to perform cap_get_proc(): %s.\n", strerror(errno));
                return false;
        }
 
+       cap_is_set = lxc_cap_is_set(caps, cap, flag);
        cap_free(caps);
-       return flagval == CAP_SET;
+       return cap_is_set;
 }
 
 #endif
index 8d60fdc8d16a643f66f7ed06f967b329da93517b..3aa87d16276fdbe478a30ad25a8bbda2484d6b18 100644 (file)
@@ -36,7 +36,8 @@ extern int lxc_caps_init(void);
 
 extern int lxc_caps_last_cap(void);
 
-extern bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag);
+extern bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag);
+extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag);
 #else
 static inline int lxc_caps_down(void) {
        return 0;
@@ -54,7 +55,11 @@ static inline int lxc_caps_last_cap(void) {
 
 typedef int cap_value_t;
 typedef int cap_flag_t;
-static inline bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag) {
+static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag) {
+       return true;
+}
+
+static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) {
        return true;
 }
 #endif
index 35d2ed5f40b04dba238c67c2b2b0d45201d45f4c..61d268ad0d4041c59a46b211548ac326c408da9d 100644 (file)
@@ -899,7 +899,7 @@ static int do_start(void *data)
                 * have necessary privilege.
                 */
                #if HAVE_LIBCAP
-               have_cap_setgid = lxc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
+               have_cap_setgid = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
                #else
                have_cap_setgid = false;
                #endif