X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/06211b7c8fd329137ae9003818543912a87d9898..9b00664295d8dd1c4d1ee118fed3308af93723e0:/src/daemon/caps.c diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 2ea51c9f..25a09fdf 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -1,5 +1,3 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. @@ -26,20 +24,24 @@ #include #endif -#include #include #include #include #include -#ifdef HAVE_SYS_CAPABILITY_H -#include -#endif +#include +#include #include - #include +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + #include "caps.h" /* Glibc <= 2.2 has broken unistd.h */ @@ -57,16 +59,19 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log_info("dropping root rights."); + pa_log_info(_("Dropping root priviliges.")); #if defined(HAVE_SETRESUID) - setresuid(uid, uid, uid); + pa_assert_se(setresuid(uid, uid, uid) >= 0); #elif defined(HAVE_SETREUID) - setreuid(uid, uid); + pa_assert_se(setreuid(uid, uid) >= 0); #else - setuid(uid); - seteuid(uid); + pa_assert_se(setuid(uid) >= 0); + pa_assert_se(seteuid(uid) >= 0); #endif + + pa_assert_se(getuid() == uid); + pa_assert_se(geteuid() == uid); } #else @@ -76,77 +81,81 @@ void pa_drop_root(void) { #endif -#ifdef HAVE_SYS_CAPABILITY_H +#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H) -/* Limit capabilities set to CAPSYS_NICE */ -int pa_limit_caps(void) { - int r = -1; +/* Limit permitted capabilities set to CAPSYS_NICE */ +void pa_limit_caps(void) { cap_t caps; cap_value_t nice_cap = CAP_SYS_NICE; - /* Only drop caps when called SUID */ - if (getuid() == 0) - return 0; - - caps = cap_init(); - assert(caps); - - cap_clear(caps); - - cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); - cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET); + pa_assert_se(caps = cap_init()); + pa_assert_se(cap_clear(caps) == 0); + pa_assert_se(cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET) == 0); + pa_assert_se(cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET) == 0); if (cap_set_proc(caps) < 0) - goto fail; - - pa_log_info("dropped capabilities successfully."); + /* Hmm, so we couldn't limit our caps, which probably means we + * hadn't any in the first place, so let's just make sure of + * that */ + pa_drop_caps(); + else + pa_log_info(_("Limited capabilities successfully to CAP_SYS_NICE.")); - r = 0; + pa_assert_se(cap_free(caps) == 0); -fail: - cap_free (caps); - - return r; + pa_assert_se(prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == 0); } /* Drop all capabilities, effectively becoming a normal user */ -int pa_drop_caps(void) { +void pa_drop_caps(void) { cap_t caps; - int r = -1; - /* Only drop caps when called SUID */ - if (getuid() == 0) - return 0; +#ifndef __OPTIMIZE__ + /* Valgrind doesn't not know set_caps, so we bypass it here -- but + * only in development builds.*/ - caps = cap_init(); - assert(caps); + if (pa_in_valgrind() && !pa_have_caps()) + return; +#endif - cap_clear(caps); + pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0); - if (cap_set_proc(caps) < 0) { - pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); - goto fail; - } + pa_assert_se(caps = cap_init()); + pa_assert_se(cap_clear(caps) == 0); + pa_assert_se(cap_set_proc(caps) == 0); + pa_assert_se(cap_free(caps) == 0); - r = 0; + pa_assert_se(!pa_have_caps()); +} -fail: - cap_free (caps); +pa_bool_t pa_have_caps(void) { + cap_t caps; + cap_flag_value_t flag = CAP_CLEAR; - return r; +#ifdef __OPTIMIZE__ + pa_assert_se(caps = cap_get_proc()); +#else + if (!(caps = cap_get_proc())) + return FALSE; +#endif + pa_assert_se(cap_get_flag(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0); + pa_assert_se(cap_free(caps) == 0); + + return flag == CAP_SET; } #else /* NOOPs in case capabilities are not available. */ -int pa_limit_caps(void) { - return 0; +void pa_limit_caps(void) { } -int pa_drop_caps(void) { +void pa_drop_caps(void) { pa_drop_root(); - return 0; } -#endif +pa_bool_t pa_have_caps(void) { + return FALSE; +} +#endif