Move newrole to use libcap-ng

Signed-off-by: Steve Lawrence <slawrence@tresys.com>
This commit is contained in:
Daniel J Walsh 2010-12-17 15:13:31 -05:00 committed by Steve Lawrence
parent d17ed0d90d
commit 16d1c1cbe5
2 changed files with 32 additions and 96 deletions

View file

@ -50,7 +50,7 @@ ifeq (${NAMESPACE_PRIV},y)
endif
ifeq (${IS_SUID},y)
MODE := 4555
LDLIBS += -lcap
LDLIBS += -lcap-ng
else
MODE := 0555
endif

View file

@ -77,7 +77,7 @@
#endif
#if defined(AUDIT_LOG_PRIV) || (NAMESPACE_PRIV)
#include <sys/prctl.h>
#include <sys/capability.h>
#include <cap-ng.h>
#endif
#ifdef USE_NLS
#include <locale.h> /* for setlocale() */
@ -90,6 +90,9 @@
#define PACKAGE "policycoreutils" /* the name of this package lang translation */
#endif
#define TRUE 1
#define FALSE 0
/* USAGE_STRING describes the command-line args of this program. */
#define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]"
@ -538,69 +541,23 @@ static int restore_environment(int preserve_environment,
* Returns zero on success, non-zero otherwise
*/
#if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV)
static int drop_capabilities(void)
static int drop_capabilities(int full)
{
int rc = 0;
cap_t new_caps, tmp_caps;
cap_value_t cap_list[] = { CAP_AUDIT_WRITE };
cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID };
uid_t uid = getuid();
if (!uid)
return 0;
/* Non-root caller, suid root path */
new_caps = cap_init();
tmp_caps = cap_init();
if (!new_caps || !tmp_caps) {
fprintf(stderr, _("Error initializing capabilities, aborting.\n"));
capng_clear(CAPNG_SELECT_BOTH);
if (capng_lock() < 0)
return -1;
}
rc |= cap_set_flag(new_caps, CAP_PERMITTED, 1, cap_list, CAP_SET);
rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET);
rc |= cap_set_flag(tmp_caps, CAP_PERMITTED, 2, tmp_cap_list, CAP_SET);
rc |= cap_set_flag(tmp_caps, CAP_EFFECTIVE, 2, tmp_cap_list, CAP_SET);
if (rc) {
fprintf(stderr, _("Error setting capabilities, aborting\n"));
goto out;
}
/* Keep capabilities across uid change */
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
fprintf(stderr, _("Error setting KEEPCAPS, aborting\n"));
rc = -1;
goto out;
}
/* Does this temporary change really buy us much? */
/* We should still have root's caps, so drop most capabilities now */
if ((rc = cap_set_proc(tmp_caps))) {
fprintf(stderr, _("Error dropping capabilities, aborting\n"));
goto out;
}
uid_t uid = getuid();
if (!uid) return 0;
/* Change uid */
if ((rc = setresuid(uid, uid, uid))) {
if (setresuid(uid, uid, uid)) {
fprintf(stderr, _("Error changing uid, aborting.\n"));
goto out;
return -1;
}
/* Now get rid of this ability */
if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) {
fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n"));
goto out;
}
/* Finish dropping capabilities. */
if ((rc = cap_set_proc(new_caps))) {
fprintf(stderr,
_("Error dropping SETUID capability, aborting\n"));
goto out;
}
out:
if (cap_free(tmp_caps) || cap_free(new_caps))
fprintf(stderr, _("Error freeing caps\n"));
return rc;
if (! full)
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_AUDIT_WRITE);
return capng_apply(CAPNG_SELECT_BOTH);
}
#elif defined(NAMESPACE_PRIV)
/**
@ -616,50 +573,25 @@ static int drop_capabilities(void)
*
* Returns zero on success, non-zero otherwise
*/
static int drop_capabilities(void)
static int drop_capabilities(int full)
{
int rc = 0;
cap_t new_caps;
cap_value_t cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID,
CAP_SYS_ADMIN, CAP_FOWNER, CAP_CHOWN,
CAP_DAC_OVERRIDE
};
capng_clear(CAPNG_SELECT_BOTH);
if (capng_lock() < 0)
return -1;
if (!getuid())
return 0;
/* Non-root caller, suid root path */
new_caps = cap_init();
if (!new_caps) {
fprintf(stderr, _("Error initializing capabilities, aborting.\n"));
uid_t uid = getuid();
/* Change uid */
if (setresuid(uid, uid, uid)) {
fprintf(stderr, _("Error changing uid, aborting.\n"));
return -1;
}
rc |= cap_set_flag(new_caps, CAP_PERMITTED, 6, cap_list, CAP_SET);
rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 6, cap_list, CAP_SET);
if (rc) {
fprintf(stderr, _("Error setting capabilities, aborting\n"));
goto out;
}
/* Ensure that caps are dropped after setuid call */
if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) {
fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n"));
goto out;
}
/* We should still have root's caps, so drop most capabilities now */
if ((rc = cap_set_proc(new_caps))) {
fprintf(stderr, _("Error dropping capabilities, aborting\n"));
goto out;
}
out:
if (cap_free(new_caps))
fprintf(stderr, _("Error freeing caps\n"));
return rc;
if (! full)
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_SYS_ADMIN | CAP_FOWNER | CAP_CHOWN | CAP_DAC_OVERRIDE);
return capng_apply(CAPNG_SELECT_BOTH);
}
#else
static inline int drop_capabilities(void)
static inline int drop_capabilities(__attribute__ ((__unused__)) int full)
{
return 0;
}
@ -1098,7 +1030,7 @@ int main(int argc, char *argv[])
* if it makes sense to continue to run newrole, and setting up
* a scrubbed environment.
*/
if (drop_capabilities())
if (drop_capabilities(FALSE))
return -1;
if (set_signal_handles())
return -1;
@ -1334,11 +1266,15 @@ int main(int argc, char *argv[])
if (send_audit_message(1, old_context, new_context, ttyn))
goto err_close_pam_session;
freecon(old_context); old_context=NULL;
freecon(new_context); new_context=NULL;
#ifdef NAMESPACE_PRIV
if (transition_to_caller_uid())
goto err_close_pam_session;
#endif
drop_capabilities(TRUE);
/* Handle environment changes */
if (restore_environment(preserve_environment, old_environ, &pw)) {
fprintf(stderr, _("Unable to restore the environment, "