summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-05-25 20:35:30 +0000
committerLennart Poettering <lennart@poettering.net>2007-05-25 20:35:30 +0000
commit4d88fcd59da84ac4f09113855c8f15384a4e05c3 (patch)
treee144296f3a041204bbf15f90af0164707c8ffde1 /src
parent65e87616833252884e4ab6b87373f98939fc446a (diff)
when called with the setid bit change euid to uid sooner to make sure that we can access our own files even when we dropped most capabilities. (Closes #21)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1455 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src')
-rw-r--r--src/daemon/caps.c33
-rw-r--r--src/daemon/main.c29
-rw-r--r--src/pulsecore/core-util.c36
3 files changed, 66 insertions, 32 deletions
diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index 2ea51c9f..8043230c 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -35,6 +35,9 @@
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
#include <pulsecore/core-error.h>
@@ -76,35 +79,31 @@ 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 */
+/* Limit permitted capabilities set to CAPSYS_NICE */
int pa_limit_caps(void) {
int r = -1;
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);
if (cap_set_proc(caps) < 0)
goto fail;
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
+ goto fail;
+
pa_log_info("dropped capabilities successfully.");
-
- r = 0;
+
+ r = 1;
fail:
- cap_free (caps);
+ cap_free(caps);
return r;
}
@@ -114,24 +113,22 @@ int pa_drop_caps(void) {
cap_t caps;
int r = -1;
- /* Only drop caps when called SUID */
- if (getuid() == 0)
- return 0;
-
caps = cap_init();
assert(caps);
cap_clear(caps);
+ prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+
if (cap_set_proc(caps) < 0) {
pa_log("failed to drop capabilities: %s", pa_cstrerror(errno));
goto fail;
}
-
+
r = 0;
fail:
- cap_free (caps);
+ cap_free(caps);
return r;
}
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 211dd30c..72e47975 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -329,22 +329,29 @@ int main(int argc, char *argv[]) {
struct timeval tv;
#endif
- setlocale(LC_ALL, "");
-
- pa_limit_caps();
-
#ifdef HAVE_GETUID
real_root = getuid() == 0;
suid_root = !real_root && geteuid() == 0;
+#else
+ real_root = 0;
+ suid_root = 0;
+#endif
+
+ if (suid_root) {
+ if (pa_limit_caps() > 0)
+ /* We managed to drop capabilities except the needed
+ * ones. Hence we can drop the uid. */
+ pa_drop_root();
+ }
+
+ setlocale(LC_ALL, "");
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
+ pa_drop_caps();
pa_drop_root();
+ suid_root = real_root = 0;
}
-#else
- real_root = 0;
- suid_root = 0;
-#endif
LTDL_SET_PRELOADED_SYMBOLS();
@@ -381,10 +388,10 @@ int main(int argc, char *argv[]) {
if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
pa_raise_priority();
- pa_drop_caps();
-
- if (suid_root)
+ if (suid_root) {
+ pa_drop_caps();
pa_drop_root();
+ }
if (conf->dl_search_path)
lt_dlsetsearchpath(conf->dl_search_path);
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index cc0fb205..480ac3b7 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -51,6 +51,10 @@
#include <sys/resource.h>
#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
+
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
@@ -481,7 +485,23 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
sensible: set the nice level to -15 and enable realtime scheduling if
supported.*/
void pa_raise_priority(void) {
-
+#if defined(HAVE_SYS_CAPABILITY_H)
+ cap_t caps;
+
+ /* Temporarily acquire CAP_SYS_NICE in the effective set */
+ if ((caps = cap_get_proc())) {
+ cap_t caps_new;
+ cap_value_t nice_cap = CAP_SYS_NICE;
+
+ if ((caps_new = cap_dup(caps))) {
+ cap_set_flag(caps_new, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET);
+ cap_set_flag(caps_new, CAP_PERMITTED, 1, &nice_cap, CAP_SET);
+ cap_set_proc(caps_new);
+ cap_free(caps_new);
+ }
+ }
+#endif
+
#ifdef HAVE_SYS_RESOURCE_H
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
@@ -495,13 +515,13 @@ void pa_raise_priority(void) {
if (sched_getparam(0, &sp) < 0) {
pa_log("sched_getparam(): %s", pa_cstrerror(errno));
- return;
+ goto fail;
}
sp.sched_priority = 1;
if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) {
pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno));
- return;
+ goto fail;
}
pa_log_info("Successfully enabled SCHED_FIFO scheduling.");
@@ -514,6 +534,16 @@ void pa_raise_priority(void) {
else
pa_log_info("Successfully gained high priority class.");
#endif
+
+fail:
+
+#if defined(HAVE_SYS_CAPABILITY_H)
+ if (caps) {
+ /* Restore original caps */
+ cap_set_proc(caps);
+ cap_free(caps);
+ }
+#endif
}
/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */