Skip to content

Commit

Permalink
Merge pull request #2508 from brauner/2018-08-04/cap_fixes
Browse files Browse the repository at this point in the history
macro: add new macro header, caps: bugfixes, log: bugfixes
  • Loading branch information
stgraber committed Aug 4, 2018
2 parents de7187b + 202a334 commit 1a64ff4
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 222 deletions.
3 changes: 3 additions & 0 deletions src/lxc/Makefile.am
Expand Up @@ -16,6 +16,7 @@ noinst_HEADERS = attach.h \
log.h \
lxc.h \
lxclock.h \
macro.h \
monitor.h \
namespace.h \
start.h \
Expand Down Expand Up @@ -99,6 +100,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
lxccontainer.c lxccontainer.h \
lxclock.c lxclock.h \
lxcseccomp.h \
macro.h \
mainloop.c mainloop.h \
namespace.c namespace.h \
nl.c nl.h \
Expand Down Expand Up @@ -342,6 +344,7 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \
error.c error.h \
initutils.c initutils.h \
log.c log.h \
macro.h \
namespace.c namespace.h \
parse.c parse.h

Expand Down
136 changes: 73 additions & 63 deletions src/lxc/caps.c
Expand Up @@ -33,6 +33,7 @@

#include "caps.h"
#include "log.h"
#include "macro.h"

lxc_log_define(caps, lxc);

Expand Down Expand Up @@ -66,51 +67,52 @@ lxc_log_define(caps, lxc);
int lxc_caps_down(void)
{
cap_t caps;
int ret;
int ret = -1;

/* when we are run as root, we don't want to play
* with the capabilities */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;

caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to cap_get_proc");
return -1;
SYSERROR("Failed to retrieve capabilities");
return ret;
}

ret = cap_clear_flag(caps, CAP_EFFECTIVE);
if (ret) {
SYSERROR("Failed to cap_clear_flag");
goto out;
SYSERROR("Failed to clear effective capabilities");
goto on_error;
}

ret = cap_set_proc(caps);
if (ret) {
SYSERROR("Failed to cap_set_proc");
goto out;
SYSERROR("Failed to change effective capabilities");
goto on_error;
}

out:
ret = 0;

on_error:
cap_free(caps);
return 0;

return ret;
}

int lxc_caps_up(void)
{
cap_t caps;
cap_value_t cap;
int ret;
int ret = -1;

/* when we are run as root, we don't want to play
* with the capabilities */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;

caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to cap_get_proc");
return -1;
SYSERROR("Failed to retrieve capabilities");
return ret;
}

for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
Expand All @@ -119,30 +121,34 @@ int lxc_caps_up(void)
ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
if (ret) {
if (errno == EINVAL) {
INFO("Last supported cap was %d", cap-1);
INFO("Last supported cap was %d", cap - 1);
break;
} else {
SYSERROR("Failed to cap_get_flag");
goto out;
SYSERROR("Failed to retrieve setting for "
"permitted capability %d", cap - 1);
goto on_error;
}
}

ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
if (ret) {
SYSERROR("Failed to cap_set_flag");
goto out;
SYSERROR("Failed to set effective capability %d", cap - 1);
goto on_error;
}
}

ret = cap_set_proc(caps);
if (ret) {
SYSERROR("Failed to cap_set_proc");
goto out;
SYSERROR("Failed to change effective capabilities");
goto on_error;
}

out:
ret = 0;

on_error:
cap_free(caps);
return 0;

return ret;
}

int lxc_ambient_caps_up(void)
Expand All @@ -153,7 +159,7 @@ int lxc_ambient_caps_up(void)
int last_cap = CAP_LAST_CAP;
char *cap_names = NULL;

/* When we are run as root, we don't want to play with the capabilities. */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;

Expand Down Expand Up @@ -220,7 +226,7 @@ int lxc_ambient_caps_down(void)
cap_t caps;
cap_value_t cap;

/* When we are run as root, we don't want to play with the capabilities. */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;

Expand Down Expand Up @@ -257,79 +263,84 @@ int lxc_ambient_caps_down(void)

int lxc_caps_init(void)
{
uid_t uid = getuid();
gid_t gid = getgid();
uid_t euid = geteuid();
uid_t euid, uid;

if (!uid) {
INFO("command is run as 'root'");
uid = getuid();
if (!uid)
return 0;
}

euid = geteuid();
if (uid && !euid) {
INFO("command is run as setuid root (uid : %d)", uid);
int ret;
gid_t gid;

INFO("Command is run as setuid root (uid: %d)", uid);

if (prctl(PR_SET_KEEPCAPS, 1)) {
SYSERROR("Failed to 'PR_SET_KEEPCAPS'");
ret = prctl(PR_SET_KEEPCAPS, 1);
if (ret < 0) {
SYSERROR("Failed to set PR_SET_KEEPCAPS");
return -1;
}

if (setresgid(gid, gid, gid)) {
SYSERROR("Failed to change gid to '%d'", gid);
gid = getgid();
ret = setresgid(gid, gid, gid);
if (ret < 0) {
SYSERROR("Failed to change rgid, egid, and sgid to %d", gid);
return -1;
}

if (setresuid(uid, uid, uid)) {
SYSERROR("Failed to change uid to '%d'", uid);
ret = setresuid(uid, uid, uid);
if (ret < 0) {
SYSERROR("Failed to change ruid, euid, and suid to %d", uid);
return -1;
}

if (lxc_caps_up()) {
ret = lxc_caps_up();
if (ret < 0) {
SYSERROR("Failed to restore capabilities");
return -1;
}
}

if (uid == euid)
INFO("command is run as user '%d'", uid);
INFO("Command is run with uid %d", uid);

return 0;
}

static int _real_caps_last_cap(void)
{
int fd;
int result = -1;
int fd, result = -1;

/* try to get the maximum capability over the kernel
* interface introduced in v3.2 */
fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
/* Try to get the maximum capability over the kernel interface
* introduced in v3.2.
*/
fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
char buf[32];
ssize_t n;
char *ptr;
int n;
char buf[LXC_NUMSTRLEN64 + 1];

again:
n = read(fd, buf, 31);
n = read(fd, buf, LXC_NUMSTRLEN64);
if (n < 0 && errno == EINTR) {
goto again;
} else if (n >= 0) {
buf[n] = '\0';
errno = 0;

errno = 0;
result = strtol(buf, &ptr, 10);
if (!ptr || (*ptr != '\0' && *ptr != '\n') || errno != 0)
result = -1;
}

close(fd);
}

/* try to get it manually by trying to get the status of
* each capability indiviually from the kernel */
if (result < 0) {
} else {
int cap = 0;

/* Try to get it manually by trying to get the status of each
* capability individually from the kernel.
*/
while (prctl(PR_CAPBSET_READ, cap) >= 0)
cap++;

Expand All @@ -356,7 +367,7 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)

ret = cap_get_flag(caps, cap, flag, &flagval);
if (ret < 0) {
SYSERROR("Failed to perform cap_get_flag()");
SYSERROR("Failed to retrieve current setting for capability %d", cap);
return false;
}

Expand All @@ -365,7 +376,7 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)

bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
{
#if LIBCAP_SUPPORTS_FILE_CAPABILITIES
#if LIBCAP_SUPPORTS_FILE_CAPABILITIES
bool cap_is_set;
cap_t caps;

Expand All @@ -377,18 +388,18 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
* case errno will be set to ENODATA.
*/
if (errno != ENODATA)
SYSERROR("Failed to perform cap_get_file()");
SYSERROR("Failed to retrieve capabilities for file %s", path);

return false;
}

cap_is_set = lxc_cap_is_set(caps, cap, flag);
cap_free(caps);
return cap_is_set;
#else
#else
errno = ENODATA;
return false;
#endif
#endif
}

bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
Expand All @@ -398,13 +409,12 @@ bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)

caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to perform cap_get_proc()");
SYSERROR("Failed to retrieve capabilities");
return false;
}

cap_is_set = lxc_cap_is_set(caps, cap, flag);
cap_free(caps);
return cap_is_set;
}

#endif

0 comments on commit 1a64ff4

Please sign in to comment.