chiark / gitweb /
exec: properly apply capability bounding set, add inverted bounding sets
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Mar 2011 02:13:15 +0000 (03:13 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 18 Mar 2011 03:52:45 +0000 (04:52 +0100)
TODO
man/systemd.exec.xml
src/dbus-execute.c
src/dbus-execute.h
src/execute.c
src/load-fragment.c

diff --git a/TODO b/TODO
index d2614b73cd18a4bc8483f0027375d8b1ea0c1453..620cdfff084524c75481e0078b8ef9ccbed875c1 100644 (file)
--- a/TODO
+++ b/TODO
@@ -23,23 +23,26 @@ F15:
 * 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
     (path: after installing inotify watches, recheck file again to fix race)
 
-* capability_bounding_set_drop not used
-
-* rework syslog.service being up logic in PID 1
-
 * rsyslog.service should hook itself into syslog.target?
 
 * syslog.target should be pulled in by multi-user.target?
 
 * pull in .service from meta .targers AND vice versa too. i.e. syslog.target ←→ rsyslog.service, rpcbind similarly
 
-* drop Names= option? Symlinks only should be used. We don't want to need to read all service files.
-
 Features:
+
+* hide passwords on TAB
+
+* add switch to systemctl to show enabled but not running services. Or
+  another switch that shows service that have been running since
+  booting but aren't running anymore.
+
+* reuse mkdtemp namespace dirs in /tmp?
+
 * don't strip facility from kmsg log messages as soon as that is possible.
     http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9d90c8d9cde929cbc575098e825d7c29d9f45054
 
-* recreate systemd'd D-Bus private socket file on SIGUSR2
+* recreate systemd's D-Bus private socket file on SIGUSR2
 
 * be more specific what failed:
     Unmounting file systems.
index f96d181a9e83ad82358dfe510f8a5955df70b674..fb8496f54ac825e4e7f42438fed4417c6108cf6d 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
-                                <term><varname>Capabilities=</varname></term>
-                                <listitem><para>Controls the
+                                <term><varname>CapabilityBoundingSet=</varname></term>
+
+                                <listitem><para>Controls which
+                                capabilities to include in the
+                                capability bounding set for the
+                                executed process. See
                                 <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-                                set for the executed process. Take a
-                                capability string as described in
-                                <citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
-                                Note that this capability set is
-                                usually influenced by the capabilities
-                                attached to the executed
-                                file.</para></listitem>
+                                for details. Takes a whitespace
+                                seperated list of capability names as
+                                read by
+                                <citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+                                Capabilities listed will be included
+                                in the bounding set, all others are
+                                removed. If the list of capabilities
+                                is prefixed with ~ all but the listed
+                                capabilities will be included, the
+                                effect of this assignment
+                                inverted. Note that this option does
+                                not actually set or unset any
+                                capabilities in the effective,
+                                permitted or inherited capability
+                                sets. That's what
+                                <varname>Capabilities=</varname> is
+                                for. If this option is not used the
+                                capability bounding set is not
+                                modified on process execution, hence
+                                no limits on the capabilities of the
+                                process are enforced.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                         </varlistentry>
 
                         <varlistentry>
-                                <term><varname>CapabilityBoundingSetDrop=</varname></term>
-
+                                <term><varname>Capabilities=</varname></term>
                                 <listitem><para>Controls the
-                                capability bounding set drop set for
-                                the executed process. See
                                 <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-                                for details. Takes a list of
-                                capability names as read by
-                                <citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
-                                </para></listitem>
+                                set for the executed process. Take a
+                                capability string describing the
+                                effective, permitted and inherited
+                                capability sets as documented in
+                                <citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+                                Note that these capability sets are
+                                usually influenced by the capabilities
+                                attached to the executed file. Due to
+                                that
+                                <varname>CapabilityBoundingSet=</varname>
+                                is probably the much more useful
+                                setting.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
index 504651fc9fca37fa12c1aaede32a98e800b62d6b..35e6d377eec15812c74b89608b2d6ff013502c55 100644 (file)
@@ -234,6 +234,24 @@ int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const ch
         return 0;
 }
 
+int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        uint64_t normal, inverted;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        /* We store this negated internally, to match the kernel, bu
+         * we expose it normalized. */
+
+        normal = *(uint64_t*) data;
+        inverted = ~normal;
+
+        return bus_property_append_uint64(m, i, property, &inverted);
+}
+
 int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) {
         ExecContext *c = data;
         char *t = NULL;
index 082456a9eceed39807b673c5486f88e9b5e19caf..8bfaaaf12086f43ef278c399d9264b3a923ff6f4 100644 (file)
         { interface, "SyslogLevelPrefix",             bus_property_append_bool,   "b",     &(context).syslog_level_prefix          }, \
         { interface, "Capabilities",                  bus_execute_append_capabilities, "s",&(context)                              }, \
         { interface, "SecureBits",                    bus_property_append_int,    "i",     &(context).secure_bits                  }, \
-        { interface, "CapabilityBoundingSetDrop",     bus_property_append_uint64, "t",     &(context).capability_bounding_set_drop }, \
+        { interface, "CapabilityBoundingSet",         bus_execute_append_capability_bs, "t", &(context).capability_bounding_set_drop }, \
         { interface, "User",                          bus_property_append_string, "s",     (context).user                          }, \
         { interface, "Group",                         bus_property_append_string, "s",     (context).group                         }, \
         { interface, "SupplementaryGroups",           bus_property_append_strv,   "as",    (context).supplementary_groups          }, \
@@ -167,6 +167,7 @@ int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const
 int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data);
 int bus_execute_append_kill_mode(Manager *m, DBusMessageIter *i, const char *property, void *data);
index c1edf61fb1677d1ecbe3a78560595ea755cfd5c9..a467411f7dab13c238a8094f480240e4b8ad7cb9 100644 (file)
@@ -1249,6 +1249,15 @@ 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 (context->user)
                                 if (enforce_user(context, uid) < 0) {
                                         r = EXIT_USER;
@@ -1664,15 +1673,15 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                         (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
 
         if (c->capability_bounding_set_drop) {
-                fprintf(f, "%sCapabilityBoundingSetDrop:", prefix);
+                fprintf(f, "%sCapabilityBoundingSet:", prefix);
 
                 for (i = 0; i <= CAP_LAST_CAP; i++)
-                        if (c->capability_bounding_set_drop & (1 << i)) {
+                        if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i))) {
                                 char *t;
 
                                 if ((t = cap_to_name(i))) {
                                         fprintf(f, " %s", t);
-                                        free(t);
+                                        cap_free(t);
                                 }
                         }
 
index 334bc713be8f691bcb65ba7ebf93d2ef31e5aab5..ac22b94509babea9412610f024a7c33e90025f35 100644 (file)
@@ -852,12 +852,24 @@ static int config_parse_bounding_set(
         char *w;
         size_t l;
         char *state;
+        bool invert = false;
+        uint64_t sum = 0;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(data);
 
+        if (rvalue[0] == '~') {
+                invert = true;
+                rvalue++;
+        }
+
+        /* Note that we store this inverted internally, since the
+         * kernel wants it like this. But we actually expose it
+         * non-inverted everywhere to have a fully normalized
+         * interface. */
+
         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t;
                 int r;
@@ -874,9 +886,14 @@ static int config_parse_bounding_set(
                         return 0;
                 }
 
-                c->capability_bounding_set_drop |= 1 << cap;
+                sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
         }
 
+        if (invert)
+                c->capability_bounding_set_drop |= sum;
+        else
+                c->capability_bounding_set_drop |= ~sum;
+
         return 0;
 }
 
@@ -1772,7 +1789,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "SyslogLevelPrefix",      config_parse_bool,            &(context).syslog_level_prefix,                  section   }, \
                 { "Capabilities",           config_parse_capabilities,    &(context),                                      section   }, \
                 { "SecureBits",             config_parse_secure_bits,     &(context),                                      section   }, \
-                { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context),                                      section   }, \
+                { "CapabilityBoundingSet",  config_parse_bounding_set,    &(context),                                      section   }, \
                 { "TimerSlackNSec",         config_parse_timer_slack_nsec,&(context),                                      section   }, \
                 { "LimitCPU",               config_parse_limit,           &(context).rlimit[RLIMIT_CPU],                   section   }, \
                 { "LimitFSIZE",             config_parse_limit,           &(context).rlimit[RLIMIT_FSIZE],                 section   }, \