From: Christian Brauner Date: Sat, 15 Apr 2017 13:00:14 +0000 (+0200) Subject: caps: add lxc_{proc,file}_cap_is_set() X-Git-Tag: lxc-2.1.0~159^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=207c4c71ee7b18bca65b02cffe11d65831d85342;p=thirdparty%2Flxc.git caps: add lxc_{proc,file}_cap_is_set() 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 --- diff --git a/src/lxc/caps.c b/src/lxc/caps.c index 1d46c4567..705ac9446 100644 --- a/src/lxc/caps.c +++ b/src/lxc/caps.c @@ -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 diff --git a/src/lxc/caps.h b/src/lxc/caps.h index 8d60fdc8d..3aa87d162 100644 --- a/src/lxc/caps.h +++ b/src/lxc/caps.h @@ -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 diff --git a/src/lxc/start.c b/src/lxc/start.c index 35d2ed5f4..61d268ad0 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -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