caps: port to call_cleaner() based cleanup

parent e16ad728
...@@ -15,14 +15,17 @@ ...@@ -15,14 +15,17 @@
#include "file_utils.h" #include "file_utils.h"
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
#include "memory_utils.h"
lxc_log_define(caps, lxc); lxc_log_define(caps, lxc);
#if HAVE_LIBCAP #if HAVE_LIBCAP
define_cleanup_function(cap_t, cap_free);
int lxc_caps_down(void) int lxc_caps_down(void)
{ {
cap_t caps; call_cleaner(cap_free) cap_t caps = NULL;
int ret = -1; int ret = -1;
/* When we are root, we don't want to play with capabilities. */ /* When we are root, we don't want to play with capabilities. */
...@@ -30,34 +33,23 @@ int lxc_caps_down(void) ...@@ -30,34 +33,23 @@ int lxc_caps_down(void)
return 0; return 0;
caps = cap_get_proc(); caps = cap_get_proc();
if (!caps) { if (!caps)
SYSERROR("Failed to retrieve capabilities"); return log_error_errno(ret, errno, "Failed to retrieve capabilities");
return ret;
}
ret = cap_clear_flag(caps, CAP_EFFECTIVE); ret = cap_clear_flag(caps, CAP_EFFECTIVE);
if (ret) { if (ret)
SYSERROR("Failed to clear effective capabilities"); return log_error_errno(ret, errno, "Failed to clear effective capabilities");
goto on_error;
}
ret = cap_set_proc(caps); ret = cap_set_proc(caps);
if (ret) { if (ret)
SYSERROR("Failed to change effective capabilities"); return log_error_errno(ret, errno, "Failed to change effective capabilities");
goto on_error;
}
ret = 0; return 0;
on_error:
cap_free(caps);
return ret;
} }
int lxc_caps_up(void) int lxc_caps_up(void)
{ {
cap_t caps; call_cleaner(cap_free) cap_t caps = NULL;
cap_value_t cap; cap_value_t cap;
int ret = -1; int ret = -1;
...@@ -66,10 +58,8 @@ int lxc_caps_up(void) ...@@ -66,10 +58,8 @@ int lxc_caps_up(void)
return 0; return 0;
caps = cap_get_proc(); caps = cap_get_proc();
if (!caps) { if (!caps)
SYSERROR("Failed to retrieve capabilities"); return log_error_errno(ret, errno, "Failed to retrieve capabilities");
return ret;
}
for (cap = 0; cap <= CAP_LAST_CAP; cap++) { for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
cap_flag_value_t flag; cap_flag_value_t flag;
...@@ -80,49 +70,36 @@ int lxc_caps_up(void) ...@@ -80,49 +70,36 @@ int lxc_caps_up(void)
INFO("Last supported cap was %d", cap - 1); INFO("Last supported cap was %d", cap - 1);
break; break;
} else { } else {
SYSERROR("Failed to retrieve setting for " return log_error_errno(ret, errno, "Failed to retrieve setting for permitted capability %d", cap - 1);
"permitted capability %d", cap - 1);
goto on_error;
} }
} }
ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag); ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
if (ret) { if (ret)
SYSERROR("Failed to set effective capability %d", cap - 1); return log_error_errno(ret, errno, "Failed to set effective capability %d", cap - 1);
goto on_error;
}
} }
ret = cap_set_proc(caps); ret = cap_set_proc(caps);
if (ret) { if (ret)
SYSERROR("Failed to change effective capabilities"); return log_error_errno(ret, errno, "Failed to change effective capabilities");
goto on_error;
}
ret = 0;
on_error: return 0;
cap_free(caps);
return ret;
} }
int lxc_ambient_caps_up(void) int lxc_ambient_caps_up(void)
{ {
call_cleaner(cap_free) cap_t caps = NULL;
__do_free char *cap_names = NULL;
int ret; int ret;
cap_t caps;
cap_value_t cap; cap_value_t cap;
int last_cap = CAP_LAST_CAP; int last_cap = CAP_LAST_CAP;
char *cap_names = NULL;
if (!getuid() || geteuid()) if (!getuid() || geteuid())
return 0; return 0;
caps = cap_get_proc(); caps = cap_get_proc();
if (!caps) { if (!caps)
SYSERROR("Failed to retrieve capabilities"); return log_error_errno(-1, errno, "Failed to retrieve capabilities");
return -1;
}
for (cap = 0; cap <= CAP_LAST_CAP; cap++) { for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
cap_flag_value_t flag; cap_flag_value_t flag;
...@@ -135,51 +112,37 @@ int lxc_ambient_caps_up(void) ...@@ -135,51 +112,37 @@ int lxc_ambient_caps_up(void)
break; break;
} }
SYSERROR("Failed to retrieve capability flag"); return log_error_errno(ret, errno, "Failed to retrieve capability flag");
goto out;
} }
ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, flag); ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, flag);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set capability flag"); return log_error_errno(ret, errno, "Failed to set capability flag");
goto out;
}
} }
ret = cap_set_proc(caps); ret = cap_set_proc(caps);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set capabilities"); return log_error_errno(ret, errno, "Failed to set capabilities");
goto out;
}
for (cap = 0; cap <= last_cap; cap++) { for (cap = 0; cap <= last_cap; cap++) {
ret = prctl(PR_CAP_AMBIENT, prctl_arg(PR_CAP_AMBIENT_RAISE), ret = prctl(PR_CAP_AMBIENT, prctl_arg(PR_CAP_AMBIENT_RAISE),
prctl_arg(cap), prctl_arg(0), prctl_arg(0)); prctl_arg(cap), prctl_arg(0), prctl_arg(0));
if (ret < 0) { if (ret < 0)
SYSWARN("Failed to raise ambient capability %d", cap); return log_warn_errno(ret, errno, "Failed to raise ambient capability %d", cap);
goto out;
}
} }
cap_names = cap_to_text(caps, NULL); cap_names = cap_to_text(caps, NULL);
if (!cap_names) { if (!cap_names)
SYSWARN("Failed to convert capabilities %d", cap); return log_warn_errno(0, errno, "Failed to convert capabilities %d", cap);
goto out;
}
TRACE("Raised %s in inheritable and ambient capability set", cap_names); TRACE("Raised %s in inheritable and ambient capability set", cap_names);
out:
cap_free(cap_names);
cap_free(caps);
return 0; return 0;
} }
int lxc_ambient_caps_down(void) int lxc_ambient_caps_down(void)
{ {
call_cleaner(cap_free) cap_t caps = NULL;
int ret; int ret;
cap_t caps;
cap_value_t cap; cap_value_t cap;
if (!getuid() || geteuid()) if (!getuid() || geteuid())
...@@ -187,33 +150,23 @@ int lxc_ambient_caps_down(void) ...@@ -187,33 +150,23 @@ int lxc_ambient_caps_down(void)
ret = prctl(PR_CAP_AMBIENT, prctl_arg(PR_CAP_AMBIENT_CLEAR_ALL), ret = prctl(PR_CAP_AMBIENT, prctl_arg(PR_CAP_AMBIENT_CLEAR_ALL),
prctl_arg(0), prctl_arg(0), prctl_arg(0)); prctl_arg(0), prctl_arg(0), prctl_arg(0));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to clear ambient capability set"); return log_error_errno(-1, errno, "Failed to clear ambient capability set");
return -1;
}
caps = cap_get_proc(); caps = cap_get_proc();
if (!caps) { if (!caps)
SYSERROR("Failed to retrieve capabilities"); return log_error_errno(-1, errno, "Failed to retrieve capabilities");
return -1;
}
for (cap = 0; cap <= CAP_LAST_CAP; cap++) { for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, CAP_CLEAR); ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, CAP_CLEAR);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remove capability from inheritable set"); return log_error_errno(-1, errno, "Failed to clear capability");
goto out;
}
} }
ret = cap_set_proc(caps); ret = cap_set_proc(caps);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set capabilities"); return log_error_errno(ret, errno, "Failed to set capabilities");
goto out;
}
out:
cap_free(caps);
return 0; return 0;
} }
...@@ -233,29 +186,21 @@ int lxc_caps_init(void) ...@@ -233,29 +186,21 @@ int lxc_caps_init(void)
INFO("Command is run as setuid root (uid: %d)", uid); INFO("Command is run as setuid root (uid: %d)", uid);
ret = prctl(PR_SET_KEEPCAPS, prctl_arg(1)); ret = prctl(PR_SET_KEEPCAPS, prctl_arg(1));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set PR_SET_KEEPCAPS"); return log_error_errno(-1, errno, "Failed to set PR_SET_KEEPCAPS");
return -1;
}
gid = getgid(); gid = getgid();
ret = setresgid(gid, gid, gid); ret = setresgid(gid, gid, gid);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to change rgid, egid, and sgid to %d", gid); return log_error_errno(-1, errno, "Failed to change rgid, egid, and sgid to %d", gid);
return -1;
}
ret = setresuid(uid, uid, uid); ret = setresuid(uid, uid, uid);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to change ruid, euid, and suid to %d", uid); return log_error_errno(-1, errno, "Failed to change ruid, euid, and suid to %d", uid);
return -1;
}
ret = lxc_caps_up(); ret = lxc_caps_up();
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to restore capabilities"); return log_error_errno(-1, errno, "Failed to restore capabilities");
return -1;
}
} }
if (uid == euid) if (uid == euid)
...@@ -320,10 +265,8 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag) ...@@ -320,10 +265,8 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)
cap_flag_value_t flagval; cap_flag_value_t flagval;
ret = cap_get_flag(caps, cap, flag, &flagval); ret = cap_get_flag(caps, cap, flag, &flagval);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to retrieve current setting for capability %d", cap); return log_error_errno(false, errno, "Failed to retrieve current setting for capability %d", cap);
return false;
}
return flagval == CAP_SET; return flagval == CAP_SET;
} }
...@@ -331,8 +274,7 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag) ...@@ -331,8 +274,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) 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; call_cleaner(cap_free) cap_t caps = NULL;
cap_t caps;
caps = cap_get_file(path); caps = cap_get_file(path);
if (!caps) { if (!caps) {
...@@ -347,9 +289,7 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) ...@@ -347,9 +289,7 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
return false; return false;
} }
cap_is_set = lxc_cap_is_set(caps, cap, flag); return lxc_cap_is_set(caps, cap, flag);
cap_free(caps);
return cap_is_set;
#else #else
errno = ENODATA; errno = ENODATA;
return false; return false;
...@@ -358,17 +298,12 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) ...@@ -358,17 +298,12 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag) bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
{ {
bool cap_is_set; call_cleaner(cap_free) cap_t caps = NULL;
cap_t caps;
caps = cap_get_proc(); caps = cap_get_proc();
if (!caps) { if (!caps)
SYSERROR("Failed to retrieve capabilities"); return log_error_errno(false, errno, "Failed to retrieve capabilities");
return false;
}
cap_is_set = lxc_cap_is_set(caps, cap, flag); return lxc_cap_is_set(caps, cap, flag);
cap_free(caps);
return cap_is_set;
} }
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment