summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-04-19 06:06:41 +0200
committerLennart Poettering <lennart@poettering.net>2011-04-19 06:06:41 +0200
commit73090dc815390f4fca4e3ed8a7e1d3806605daaa (patch)
treec27e4fdbafcbe75f1277d91484d7f64b06b7fc87
parent8024c3a71a57fd5ff09d022e998d302898606919 (diff)
execute: when we run as PID 1 the kernel doesn't give us CAP_SETPCAP by default. Get that temporarily when dropping capabilities for good
-rw-r--r--TODO11
-rw-r--r--src/execute.c73
2 files changed, 77 insertions, 7 deletions
diff --git a/TODO b/TODO
index 80faf0fa3f..b4a5e3ab94 100644
--- a/TODO
+++ b/TODO
@@ -32,8 +32,16 @@ F15:
* don't trim empty cgroups
https://bugzilla.redhat.com/show_bug.cgi?id=678555
+* drop cap bounding set in logger, hostnamed, readahead, ...
+
+* timeout value is incorrectly parsed in /etc/fstab
+
Features:
+* Add ListenSpecial to .socket units for /proc/kmsg and similar friends?
+
+* avoid DefaultStandardOutput=syslog to have any effect on StandardInput=socket services
+
* use pivot_root on shutdown so that we can unmount the root directory.
* fix alsa mixer restore to not print error when no config is stored
@@ -43,8 +51,11 @@ Features:
* write blog stories about:
- enabling dbus services
- status update
+ - the new configuration files
- you are a distro: why switch?
+* maybe add tiny dbus services similar to hostnamed for locale?
+
* allow port = 0 in .socket units
* rename systemd-logger to systemd-stdio-syslog-bridge
diff --git a/src/execute.c b/src/execute.c
index 1e376ff89e..745dcfcdb8 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -904,6 +904,68 @@ fail:
}
#endif
+static int do_capability_bounding_set_drop(uint64_t drop) {
+ unsigned long i;
+ cap_t old_cap = NULL, new_cap = NULL;
+ cap_flag_value_t fv;
+ int r;
+
+ /* If we are run as PID 1 we will lack CAP_SETPCAP by default
+ * in the effective set (yes, the kernel drops that when
+ * executing init!), so get it back temporarily so that we can
+ * call PR_CAPBSET_DROP. */
+
+ old_cap = cap_get_proc();
+ if (!old_cap)
+ return -errno;
+
+ if (cap_get_flag(old_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (fv != CAP_SET) {
+ static const cap_value_t v = CAP_SETPCAP;
+
+ new_cap = cap_dup(old_cap);
+ if (!new_cap) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (cap_set_flag(new_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (cap_set_proc(new_cap) < 0) {
+ r = -errno;
+ goto finish;
+ }
+ }
+
+ for (i = 0; i <= CAP_LAST_CAP; i++)
+ if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
+ if (prctl(PR_CAPBSET_DROP, i) < 0) {
+ r = -errno;
+ goto finish;
+ }
+ }
+
+ r = 0;
+
+finish:
+ if (new_cap)
+ cap_free(new_cap);
+
+ if (old_cap) {
+ cap_set_proc(old_cap);
+ cap_free(old_cap);
+ }
+
+ return r;
+}
+
int exec_spawn(ExecCommand *command,
char **argv,
const ExecContext *context,
@@ -1251,13 +1313,10 @@ int exec_spawn(ExecCommand *command,
}
if (context->capability_bounding_set_drop)
- for (i = 0; i <= CAP_LAST_CAP; i++)
- if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) {
- if (prctl(PR_CAPBSET_DROP, i) < 0) {
- r = EXIT_CAPABILITIES;
- goto fail_child;
- }
- }
+ if (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) {
+ r = EXIT_CAPABILITIES;
+ goto fail_child;
+ }
if (context->user)
if (enforce_user(context, uid) < 0) {