daemon: Don't rely on prctl(PR_SET_KEEPCAPS, 0) for dropping caps.

Capability dropping when changing the user in the system
mode was previously implemented by calling
prctl(PR_SET_KEEPCAPS, 0), but that doesn't necessarily
work. It's possible that the KEEPCAPS flag is locked to 1,
in which case the prctl() call fails with EPERM (this
happens at least on Harmattan). This patch implements
explicit capability dropping after changing the user.
This commit is contained in:
Tanu Kaskinen 2012-04-05 15:37:19 +03:00 committed by Tanu Kaskinen
parent 7e6e3b7044
commit 6db3af6601
3 changed files with 18 additions and 15 deletions

View file

@ -36,10 +36,6 @@
#include <sys/capability.h>
#endif
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#include "caps.h"
/* Glibc <= 2.2 has broken unistd.h */
@ -78,17 +74,20 @@ void pa_drop_root(void) {
pa_assert_se(getegid() == gid);
#endif
#ifdef HAVE_SYS_PRCTL_H
pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
#endif
if (uid != 0)
pa_drop_caps();
}
void pa_drop_caps(void) {
#ifdef HAVE_SYS_CAPABILITY_H
if (uid != 0) {
cap_t caps;
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);
}
cap_t caps;
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);
#else
pa_log_warn("Normally all extra capabilities would be dropped now, but "
"that's impossible because this Pulseaudio was built without "
"libcap support.");
#endif
}

View file

@ -26,4 +26,6 @@
void pa_drop_root(void);
void pa_drop_caps(void);
#endif

View file

@ -251,6 +251,8 @@ static int change_user(void) {
return -1;
}
pa_drop_caps();
pa_set_env("USER", PA_SYSTEM_USER);
pa_set_env("USERNAME", PA_SYSTEM_USER);
pa_set_env("LOGNAME", PA_SYSTEM_USER);
@ -266,7 +268,7 @@ static int change_user(void) {
if (!getenv("PULSE_STATE_PATH"))
pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
pa_log_info(_("Successfully dropped root privileges."));
pa_log_info(_("Successfully changed user to \"" PA_SYSTEM_USER "\"."));
return 0;
}