chiark / gitweb /
bus: parse BusPolicy directive in service files
authorDaniel Mack <zonque@gmail.com>
Mon, 18 Aug 2014 20:42:28 +0000 (22:42 +0200)
committerDaniel Mack <daniel@zonque.org>
Mon, 8 Sep 2014 12:12:54 +0000 (14:12 +0200)
Add a new directive called BusPolicy to define custom endpoint policies. If
one such directive is given, an endpoint object in the service's ExecContext is
created and the given policy is added to it.

man/systemd.service.xml
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h

index c84a525..a82dfb2 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
+                                <term><varname>BusPolicy=</varname></term>
+
+                                <listitem><para>If specfied, a custom kdbus
+                                endpoint will be created and installed as the
+                                default bus node for the service. Such a custom
+                                endpoint can hold an own set of policy rules
+                                that are enforced on top of the bus-wide ones.
+                                The custom endpoint is named after the service
+                                it was created for, and its node will be
+                                bind-mounted over the default bus node
+                                location, so the service can only access the
+                                bus through its own endpoint. Note that custom
+                                bus endpoints default to a 'deny all' policy.
+                                Hence, if at least one
+                                <varname>BusPolicy=</varname> directive is
+                                given, you have to make sure to add explicit
+                                rules for everything the service should be able
+                                to do.</para>
+                                <para>The value of this directive is comprised
+                                of two parts; the bus name, and a verb to
+                                specify to granted access, which is one of
+                                <option>see</option>,
+                                <option>talk</option> or
+                                <option>own</option>.
+                                <option>talk</option> implies
+                                <option>see</option>, and <option>own</option>
+                                implies both <option>talk</option> and
+                                <option>see</option>.
+                                If multiple access levels are specified for the
+                                same bus name, the most powerful one takes
+                                effect.
+                                </para>
+                                <para>Examples:</para>
+                                <programlisting>BusPolicy=org.freedesktop.systemd1 talk</programlisting>
+                                <programlisting>BusPolicy=org.foo.bar see</programlisting>
+                                <para>This option is only available on kdbus enabled systems.</para>
+                                </listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><varname>ExecStart=</varname></term>
                                 <listitem><para>Commands with their
                                 arguments that are executed when this
index 24aa80d..e764d68 100644 (file)
@@ -205,6 +205,9 @@ Service.NonBlocking,             config_parse_bool,                  0,
 Service.BusName,                 config_parse_unit_string_printf,    0,                             offsetof(Service, bus_name)
 Service.NotifyAccess,            config_parse_notify_access,         0,                             offsetof(Service, notify_access)
 Service.Sockets,                 config_parse_service_sockets,       0,                             0
+m4_ifdef(`ENABLE_KDBUS',
+`Service.BusPolicy,              config_parse_bus_endpoint_policy,   0,                             offsetof(Service, exec_context)',
+`Service.BusPolicy,              config_parse_warn_compat,           0,                             0')
 EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
 CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
 KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
index b4da6a5..2f3acd7 100644 (file)
@@ -1752,6 +1752,62 @@ int config_parse_bus_policy(
         return 0;
 }
 
+int config_parse_bus_endpoint_policy(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_free_ char *name = NULL;
+        BusPolicyAccess access;
+        ExecContext *c = data;
+        char *access_str;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        name = strdup(rvalue);
+        if (!name)
+                return log_oom();
+
+        access_str = strpbrk(name, WHITESPACE);
+        if (!access_str) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Invalid endpoint policy value '%s'", rvalue);
+                return 0;
+        }
+
+        *access_str = '\0';
+        access_str++;
+        access_str += strspn(access_str, WHITESPACE);
+
+        access = bus_policy_access_from_string(access_str);
+        if (access <= _BUS_POLICY_ACCESS_INVALID ||
+            access >= _BUS_POLICY_ACCESS_MAX) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Invalid endpoint policy access type '%s'", access_str);
+                return 0;
+        }
+
+        if (!c->bus_endpoint) {
+                r = bus_endpoint_new(&c->bus_endpoint);
+
+                if (r < 0)
+                        return r;
+        }
+
+        return bus_endpoint_add_policy(c->bus_endpoint, name, access);
+}
+
 int config_parse_unit_env_file(const char *unit,
                                const char *filename,
                                unsigned line,
index 9a1d7c5..65100c9 100644 (file)
@@ -67,6 +67,7 @@ int config_parse_service_sockets(const char *unit, const char *filename, unsigne
 int config_parse_busname_service(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_bus_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_bus_policy_world(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_bus_endpoint_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_ip_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_unit_condition_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);