Merge pull request #2618 from zonque/busproxy-removal

remove bus-proxyd
This commit is contained in:
Lennart Poettering 2016-02-15 14:54:09 +01:00
commit 8eff97a103
30 changed files with 303 additions and 4731 deletions

2
.gitignore vendored
View File

@ -55,7 +55,6 @@
/systemd-binfmt
/systemd-bootchart
/systemd-bootx64.efi
/systemd-bus-proxyd
/systemd-cat
/systemd-cgls
/systemd-cgroups-agent
@ -150,7 +149,6 @@
/test-bus-match
/test-bus-objects
/test-bus-policy
/test-bus-proxy
/test-bus-server
/test-bus-signature
/test-bus-zero-copy

View File

@ -97,8 +97,6 @@ MANPAGES += \
man/systemd-analyze.1 \
man/systemd-ask-password-console.service.8 \
man/systemd-ask-password.1 \
man/systemd-bus-proxyd.8 \
man/systemd-bus-proxyd.service.8 \
man/systemd-cat.1 \
man/systemd-cgls.1 \
man/systemd-cgtop.1 \
@ -421,7 +419,6 @@ MANPAGES_ALIAS += \
man/systemd-ask-password-console.path.8 \
man/systemd-ask-password-wall.path.8 \
man/systemd-ask-password-wall.service.8 \
man/systemd-bus-proxyd.socket.8 \
man/systemd-fsck-root.service.8 \
man/systemd-fsck.8 \
man/systemd-hibernate-resume.8 \
@ -751,7 +748,6 @@ man/system.conf.d.5: man/systemd-system.conf.5
man/systemd-ask-password-console.path.8: man/systemd-ask-password-console.service.8
man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8
man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8
man/systemd-bus-proxyd.socket.8: man/systemd-bus-proxyd.service.8
man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8
man/systemd-fsck.8: man/systemd-fsck@.service.8
man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
@ -1571,9 +1567,6 @@ man/systemd-ask-password-wall.path.html: man/systemd-ask-password-console.servic
man/systemd-ask-password-wall.service.html: man/systemd-ask-password-console.service.html
$(html-alias)
man/systemd-bus-proxyd.socket.html: man/systemd-bus-proxyd.service.html
$(html-alias)
man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html
$(html-alias)
@ -2580,8 +2573,6 @@ EXTRA_DIST += \
man/systemd-backlight@.service.xml \
man/systemd-binfmt.service.xml \
man/systemd-bootchart.xml \
man/systemd-bus-proxyd.service.xml \
man/systemd-bus-proxyd.xml \
man/systemd-cat.xml \
man/systemd-cgls.xml \
man/systemd-cgtop.xml \

View File

@ -393,7 +393,6 @@ rootlibexec_PROGRAMS = \
systemd-ac-power \
systemd-sysctl \
systemd-sleep \
systemd-bus-proxyd \
systemd-socket-proxyd \
systemd-update-done
@ -1467,7 +1466,6 @@ tests += \
test-ratelimit \
test-condition \
test-uid-range \
test-bus-policy \
test-locale-util \
test-execute \
test-copy \
@ -1925,14 +1923,11 @@ test_unaligned_SOURCES = \
test_tables_SOURCES = \
src/test/test-tables.c \
src/shared/test-tables.h \
src/bus-proxyd/bus-xml-policy.c \
src/bus-proxyd/bus-xml-policy.h \
src/journal/journald-server.c \
src/journal/journald-server.h
test_tables_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(top_srcdir)/src/bus-proxyd
$(AM_CPPFLAGS)
test_tables_CFLAGS = \
$(AM_CFLAGS) \
@ -2173,13 +2168,6 @@ test_conf_parser_SOURCES = \
test_conf_parser_LDADD = \
libshared.la
test_bus_policy_SOURCES = \
src/bus-proxyd/test-bus-xml-policy.c
test_bus_policy_LDADD = \
libbus-proxy-core.la \
libshared.la
test_af_list_SOURCES = \
src/test/test-af-list.c
@ -2944,59 +2932,12 @@ systemd_run_LDADD = \
libshared.la
# ------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
libbus-proxy-core.la
libbus_proxy_core_la_SOURCES = \
src/bus-proxyd/bus-xml-policy.c \
src/bus-proxyd/bus-xml-policy.h \
src/bus-proxyd/driver.c \
src/bus-proxyd/driver.h \
src/bus-proxyd/proxy.c \
src/bus-proxyd/proxy.h \
src/bus-proxyd/synthesize.c \
src/bus-proxyd/synthesize.h
libbus_proxy_core_la_LIBADD = \
libshared.la
systemd_bus_proxyd_SOURCES = \
src/bus-proxyd/bus-proxyd.c
systemd_bus_proxyd_LDADD = \
libbus-proxy-core.la \
libshared.la
systemd_stdio_bridge_SOURCES = \
src/bus-proxyd/stdio-bridge.c
src/stdio-bridge/stdio-bridge.c
systemd_stdio_bridge_LDADD = \
libbus-proxy-core.la \
libshared.la
nodist_systemunit_DATA += \
units/systemd-bus-proxyd.service
dist_systemunit_DATA += \
units/systemd-bus-proxyd.socket
nodist_userunit_DATA += \
units/user/systemd-bus-proxyd.service
dist_userunit_DATA += \
units/user/systemd-bus-proxyd.socket
EXTRA_DIST += \
units/systemd-bus-proxyd.service.m4.in \
units/user/systemd-bus-proxyd.service.in
if HAVE_SMACK
bus-proxyd-set-cap-hook:
-$(SETCAP) cap_mac_admin+ei $(DESTDIR)$(rootlibexecdir)/systemd-bus-proxyd
INSTALL_EXEC_HOOKS += bus-proxyd-set-cap-hook
endif
# ------------------------------------------------------------------------------
systemd_tty_ask_password_agent_SOURCES = \
src/tty-ask-password-agent/tty-ask-password-agent.c
@ -3159,7 +3100,6 @@ tests += \
test-bus-cleanup \
test-bus-server \
test-bus-match \
test-bus-proxy \
test-bus-kernel \
test-bus-kernel-bloom \
test-bus-zero-copy \
@ -3252,12 +3192,6 @@ test_bus_match_SOURCES = \
test_bus_match_LDADD = \
libshared.la
test_bus_proxy_SOURCES = \
src/libsystemd/sd-bus/test-bus-proxy.c
test_bus_proxy_LDADD = \
libshared.la
test_bus_kernel_SOURCES = \
src/libsystemd/sd-bus/test-bus-kernel.c

3
README
View File

@ -200,9 +200,6 @@ USERS AND GROUPS:
Similarly, the name resolution daemon requires the
"systemd-resolve" system user and group to exist.
Similarly, the kdbus dbus1 proxy daemon requires the
"systemd-bus-proxy" system user and group to exist.
Similarly, the coredump support requires the
"systemd-coredump" system user and group to exist.

4
TODO
View File

@ -322,10 +322,6 @@ Features:
- path escaping
- update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now
- test bloom filter generation indexes
- bus-proxy: when passing messages from kdbus, make sure we properly
handle the case where a large number of fds is appended that we
cannot pass into sendmsg() of the AF_UNIX sokcet (which only accepts
253 messages)
- kdbus: introduce a concept of "send-only" connections
- kdbus: add counter for refused unicast messages that is passed out via the RECV ioctl. SImilar to the counter for dropped multicast messages we already have.

View File

@ -473,7 +473,6 @@ o "/org/freedesktop/systemd1/job/42684"</programlisting>
<ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-bus-proxyd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='die-net'><refentrytitle>wireshark</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>

View File

@ -1,80 +0,0 @@
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2013 Zbigniew Jędrzejewski-Szmek
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-bus-proxyd.service">
<refentryinfo>
<title>systemd-bus-proxyd.service</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-bus-proxyd.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-bus-proxyd.service</refname>
<refname>systemd-bus-proxyd.socket</refname>
<refpurpose>Proxy classic D-Bus clients to kdbus</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-bus-proxyd.service</filename></para>
<para><filename>systemd-bus-proxyd.socket</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>systemd-bus-proxyd.socket</filename> will launch
<filename>systemd-bus-proxyd.service</filename> for connections
to the classic D-Bus socket in
<filename>/var/run/dbus/system_bus_socket</filename>.</para>
<para><filename>systemd-bus-proxyd.service</filename> is launched
for an existing D-Bus connection and will use
<command>systemd-bus-proxyd</command> to proxy messages from this
connection to the system bus (either kdbus or classic D-Bus).
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd-bus-proxyd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='dbus'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>
</para>
</refsect1>
</refentry>

View File

@ -1,108 +0,0 @@
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2013 Zbigniew Jędrzejewski-Szmek
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-bus-proxyd"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-bus-proxyd</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-bus-proxyd</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-bus-proxyd</refname>
<refpurpose>Connect STDIO or a socket to a given bus address</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>/usr/lib/systemd/systemd-bus-proxyd</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt"><replaceable>PLACEHOLDER</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-bus-proxyd</command> will proxy D-Bus
messages to and from a bus. The will be either the system bus or
the bus specified with <option>--address</option> when that option
is given. Messages will be proxied to/from standard input and
output, or the socket received through socket activation.</para>
<para>This program can be used to connect a program using classic
D-Bus to kdbus.</para>
</refsect1>
<refsect1>
<title>Options and Arguments</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--address=<replaceable>ADDRESS</replaceable><optional>:<replaceable>ADDRESS...</replaceable></optional></option></term>
<listitem>
<para>Connect to the bus specified by
<replaceable>ADDRESS</replaceable>. Multiple colon-separated
addresses can be specified, in which case
<command>systemd-bus-proxyd</command> will attempt to
connect to them in turn.</para>
</listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
<para><replaceable>PLACEHOLDER</replaceable>, if given, must be a string
of <literal>x</literal> and will be used to display information about
the process that <command>systemd-bus-proxyd</command> is forwarding
messages for.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry project='dbus'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>
</para>
</refsect1>
</refentry>

View File

@ -1 +0,0 @@
../Makefile

View File

@ -1,328 +0,0 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2013 Daniel Mack
Copyright 2014 Kay Sievers
Copyright 2015 David Herrmann
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <getopt.h>
#include <pthread.h>
#include <stddef.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include "sd-daemon.h"
#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-xml-policy.h"
#include "capability-util.h"
#include "def.h"
#include "fd-util.h"
#include "formats-util.h"
#include "log.h"
#include "proxy.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
static char *arg_address = NULL;
static char **arg_configuration = NULL;
typedef struct {
int fd;
SharedPolicy *policy;
uid_t bus_uid;
} ClientContext;
static ClientContext *client_context_free(ClientContext *c) {
if (!c)
return NULL;
safe_close(c->fd);
free(c);
return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(ClientContext*, client_context_free);
static int client_context_new(ClientContext **out) {
_cleanup_(client_context_freep) ClientContext *c = NULL;
c = new0(ClientContext, 1);
if (!c)
return -ENOMEM;
c->fd = -1;
*out = c;
c = NULL;
return 0;
}
static void *run_client(void *userdata) {
_cleanup_(client_context_freep) ClientContext *c = userdata;
_cleanup_(proxy_freep) Proxy *p = NULL;
char comm[16];
int r;
r = proxy_new(&p, c->fd, c->fd, arg_address);
c->fd = -1;
if (r < 0)
goto exit;
/* set comm to "p$PIDu$UID" and suffix with '*' if truncated */
r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid);
if (r >= (ssize_t)sizeof(comm))
comm[sizeof(comm) - 2] = '*';
(void) prctl(PR_SET_NAME, comm);
r = proxy_set_policy(p, c->policy, arg_configuration);
if (r < 0)
goto exit;
r = proxy_hello_policy(p, c->bus_uid);
if (r < 0)
goto exit;
r = proxy_run(p);
exit:
return NULL;
}
static int loop_clients(int accept_fd, uid_t bus_uid) {
_cleanup_(shared_policy_freep) SharedPolicy *sp = NULL;
pthread_attr_t attr;
int r;
r = pthread_attr_init(&attr);
if (r != 0)
return log_error_errno(r, "Cannot initialize pthread attributes: %m");
r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (r != 0) {
r = log_error_errno(r, "Cannot mark pthread attributes as detached: %m");
goto finish;
}
r = shared_policy_new(&sp);
if (r < 0)
goto finish;
for (;;) {
ClientContext *c;
pthread_t tid;
int fd;
fd = accept4(accept_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (fd < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
r = log_error_errno(errno, "accept4() failed: %m");
goto finish;
}
r = client_context_new(&c);
if (r < 0) {
log_oom();
close(fd);
continue;
}
c->fd = fd;
c->policy = sp;
c->bus_uid = bus_uid;
r = pthread_create(&tid, &attr, run_client, c);
if (r != 0) {
log_warning_errno(r, "Cannot spawn thread, ignoring: %m");
client_context_free(c);
continue;
}
}
finish:
pthread_attr_destroy(&attr);
return r;
}
static int help(void) {
printf("%s [OPTIONS...]\n\n"
"DBus proxy server.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --configuration=PATH Configuration file or directory\n"
" --machine=MACHINE Connect to specified machine\n"
" --address=ADDRESS Connect to the bus specified by ADDRESS\n"
" (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_ADDRESS,
ARG_CONFIGURATION,
ARG_MACHINE,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "address", required_argument, NULL, ARG_ADDRESS },
{ "configuration", required_argument, NULL, ARG_CONFIGURATION },
{ "machine", required_argument, NULL, ARG_MACHINE },
{},
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
return version();
case ARG_ADDRESS:
r = free_and_strdup(&arg_address, optarg);
if (r < 0)
return log_oom();
break;
case ARG_CONFIGURATION:
r = strv_extend(&arg_configuration, optarg);
if (r < 0)
return log_oom();
break;
case ARG_MACHINE: {
_cleanup_free_ char *e = NULL;
char *a;
e = bus_address_escape(optarg);
if (!e)
return log_oom();
a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
if (!a)
return log_oom();
free(arg_address);
arg_address = a;
break;
}
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
if (argc > optind) {
log_error("Too many arguments");
return -EINVAL;
}
if (!arg_address) {
arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
if (!arg_address)
return log_oom();
}
return 1;
}
int main(int argc, char *argv[]) {
int r, accept_fd;
uid_t uid, bus_uid;
gid_t gid;
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_parse_environment();
log_open();
bus_uid = getuid();
if (geteuid() == 0) {
const char *user = "systemd-bus-proxy";
r = get_user_creds(&user, &uid, &gid, NULL, NULL);
if (r < 0) {
log_error_errno(r, "Cannot resolve user name %s: %m", user);
goto finish;
}
r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
if (r < 0) {
log_error_errno(r, "Cannot drop privileges: %m");
goto finish;
}
}
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = sd_listen_fds(0);
if (r != 1) {
log_error("Illegal number of file descriptors passed");
goto finish;
}
accept_fd = SD_LISTEN_FDS_START;
r = fd_nonblock(accept_fd, false);
if (r < 0) {
log_error_errno(r, "Cannot mark accept-fd non-blocking: %m");
goto finish;
}
r = loop_clients(accept_fd, bus_uid);
finish:
sd_notify(false,
"STOPPING=1\n"
"STATUS=Shutting down.");
strv_free(arg_configuration);
free(arg_address);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,147 +0,0 @@
#pragma once
/***
This file is part of systemd.
Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
#include "hashmap.h"
#include "list.h"
typedef enum PolicyItemType {
_POLICY_ITEM_TYPE_UNSET = 0,
POLICY_ITEM_ALLOW,
POLICY_ITEM_DENY,
_POLICY_ITEM_TYPE_MAX,
_POLICY_ITEM_TYPE_INVALID = -1,
} PolicyItemType;
typedef enum PolicyItemClass {
_POLICY_ITEM_CLASS_UNSET = 0,
POLICY_ITEM_SEND,
POLICY_ITEM_RECV,
POLICY_ITEM_OWN,
POLICY_ITEM_OWN_PREFIX,
POLICY_ITEM_USER,
POLICY_ITEM_GROUP,
POLICY_ITEM_IGNORE,
_POLICY_ITEM_CLASS_MAX,
_POLICY_ITEM_CLASS_INVALID = -1,
} PolicyItemClass;
typedef struct PolicyItem PolicyItem;
struct PolicyItem {
PolicyItemType type;
PolicyItemClass class;
char *interface;
char *member;
char *error;
char *path;
char *name;
uint8_t message_type;
uid_t uid;
gid_t gid;
bool uid_valid, gid_valid;
LIST_FIELDS(PolicyItem, items);
};
typedef struct Policy {
LIST_HEAD(PolicyItem, default_items);
LIST_HEAD(PolicyItem, mandatory_items);
LIST_HEAD(PolicyItem, on_console_items);
LIST_HEAD(PolicyItem, no_console_items);
Hashmap *user_items;
Hashmap *group_items;
} Policy;
typedef struct SharedPolicy {
char **configuration;
pthread_mutex_t lock;
pthread_rwlock_t rwlock;
Policy buffer;
Policy *policy;
} SharedPolicy;
/* policy */
int policy_load(Policy *p, char **files);
void policy_free(Policy *p);
bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name);
bool policy_check_hello(Policy *p, uid_t uid, gid_t gid);
bool policy_check_one_recv(Policy *p,
uid_t uid,
gid_t gid,
int message_type,
const char *name,
const char *path,
const char *interface,
const char *member);
bool policy_check_recv(Policy *p,
uid_t uid,
gid_t gid,
int message_type,
Set *names,
char **namesv,
const char *path,
const char *interface,
const char *member,
bool dbus_to_kernel);
bool policy_check_one_send(Policy *p,
uid_t uid,
gid_t gid,
int message_type,
const char *name,
const char *path,
const char *interface,
const char *member);
bool policy_check_send(Policy *p,
uid_t uid,
gid_t gid,
int message_type,
Set *names,
char **namesv,
const char *path,
const char *interface,
const char *member,
bool dbus_to_kernel,
char **out_used_name);
void policy_dump(Policy *p);
const char* policy_item_type_to_string(PolicyItemType t) _const_;
PolicyItemType policy_item_type_from_string(const char *s) _pure_;
const char* policy_item_class_to_string(PolicyItemClass t) _const_;
PolicyItemClass policy_item_class_from_string(const char *s) _pure_;
/* shared policy */
int shared_policy_new(SharedPolicy **out);
SharedPolicy *shared_policy_free(SharedPolicy *sp);
int shared_policy_reload(SharedPolicy *sp);
int shared_policy_preload(SharedPolicy *sp, char **configuration);
Policy *shared_policy_acquire(SharedPolicy *sp);
void shared_policy_release(SharedPolicy *sp, Policy *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(SharedPolicy*, shared_policy_free);

View File

@ -1,745 +0,0 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2013 Daniel Mack
Copyright 2014 Kay Sievers
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
#include "driver.h"
#include "env-util.h"
#include "proxy.h"
#include "set.h"
#include "strv.h"
#include "synthesize.h"
#include "util.h"
static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
int r;
assert(bus);
assert(name);
assert(_creds);
r = sd_bus_get_name_creds(bus, name, mask, &c);
if (r == -ESRCH || r == -ENXIO)
return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
if (r < 0)
return r;
*_creds = c;
c = NULL;
return 0;
}
static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
const char *name;
int r;
assert(bus);
assert(m);
assert(_creds);
r = sd_bus_message_read(m, "s", &name);
if (r < 0)
return r;
return get_creds_by_name(bus, name, mask, _creds, error);
}
static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
ProxyActivation *activation = userdata;
/*
* The org.freedesktop.DBus.Peer.Ping() call returned. We don't care
* whether this succeeded, failed, was not implemented or timed out. We
* cannot assume that the target reacts to this properly. Hence, just
* send the reply to the activation request and be done.
*/
m = activation->request; /* claim reference */
--activation->proxy->n_activations;
LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation);
sd_bus_slot_unref(activation->slot);
free(activation);
return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
}
int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
int r;
assert(a);
assert(b);
assert(m);
if (!a->is_kernel)
return 0;
if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
return 0;
/* The "Hello()" call is is handled in process_hello() */
if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
if (!sd_bus_message_has_signature(m, ""))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
return synthetic_reply_method_return(m, "s",
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
"<node>\n"
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
" <method name=\"Introspect\">\n"
" <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" </interface>\n"
" <interface name=\"org.freedesktop.DBus\">\n"
" <method name=\"AddMatch\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" </method>\n"
" <method name=\"RemoveMatch\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" </method>\n"
" <method name=\"GetConnectionCredentials\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"a{sv}\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"GetConnectionSELinuxSecurityContext\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"ay\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"GetConnectionUnixProcessID\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"GetConnectionUnixUser\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"GetId\">\n"
" <arg type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"GetNameOwner\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"Hello\">\n"
" <arg type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"ListActivatableNames\">\n"
" <arg type=\"as\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"ListNames\">\n"
" <arg type=\"as\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"ListQueuedOwners\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"as\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"NameHasOwner\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"b\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"ReleaseName\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"ReloadConfig\">\n"
" </method>\n"
" <method name=\"RequestName\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"StartServiceByName\">\n"
" <arg type=\"s\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"in\"/>\n"
" <arg type=\"u\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"UpdateActivationEnvironment\">\n"
" <arg type=\"a{ss}\" direction=\"in\"/>\n"
" </method>\n"
" <signal name=\"NameAcquired\">\n"
" <arg type=\"s\"/>\n"
" </signal>\n"
" <signal name=\"NameLost\">\n"
" <arg type=\"s\"/>\n"
" </signal>\n"
" <signal name=\"NameOwnerChanged\">\n"
" <arg type=\"s\"/>\n"
" <arg type=\"s\"/>\n"
" <arg type=\"s\"/>\n"
" </signal>\n"
" </interface>\n"
"</node>\n");
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
const char *match;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &match);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_add_match(a, NULL, match, proxy_match, p);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, NULL);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
const char *match;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &match);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = bus_remove_match_by_string(a, match, NULL, NULL);
if (r == 0)
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, NULL);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
if (r < 0)
return synthetic_reply_method_errno(m, r, &error);
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_open_container(reply, 'a', "{sv}");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
/* Due to i.e. namespace translations some data might be missing */
if (creds->mask & SD_BUS_CREDS_PID) {
r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
}
if (creds->mask & SD_BUS_CREDS_EUID) {
r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
}
if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
r = sd_bus_message_open_container(reply, 'e', "sv");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_open_container(reply, 'v', "ay");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_close_container(reply);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_close_container(reply);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
}
r = sd_bus_message_close_container(reply);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_driver_send(m->bus, reply);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
if (r < 0)
return synthetic_reply_method_errno(m, r, &error);
if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_driver_send(m->bus, reply);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
if (r < 0)
return synthetic_reply_method_errno(m, r, &error);
if (!(creds->mask & SD_BUS_CREDS_PID))
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error);
if (r < 0)
return synthetic_reply_method_errno(m, r, &error);
if (!(creds->mask & SD_BUS_CREDS_EUID))
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
sd_id128_t server_id;
char buf[SD_ID128_STRING_MAX];
if (!sd_bus_message_has_signature(m, ""))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_get_bus_id(a, &server_id);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
const char *name;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &name);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (streq(name, "org.freedesktop.DBus"))
return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
if (r < 0)
return synthetic_reply_method_errno(m, r, &error);
if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME))
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
return synthetic_reply_method_return(m, "s", creds->unique_name);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
_cleanup_strv_free_ char **names = NULL;
if (!sd_bus_message_has_signature(m, ""))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_list_names(a, NULL, &names);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
/* Let's sort the names list to make it stable */
strv_sort(names);
return synthetic_reply_method_return_strv(m, names);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
_cleanup_strv_free_ char **names = NULL;
if (!sd_bus_message_has_signature(m, ""))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_list_names(a, &names, NULL);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = strv_extend(&names, "org.freedesktop.DBus");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
/* Let's sort the names list to make it stable */
strv_sort(names);
return synthetic_reply_method_return_strv(m, names);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
struct kdbus_cmd_list cmd = {
.flags = KDBUS_LIST_QUEUED,
.size = sizeof(cmd),
};
struct kdbus_info *name_list, *name;
_cleanup_strv_free_ char **owners = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *arg0;
int err = 0;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &arg0);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_get_name_creds(a, arg0, 0, NULL);
if (r == -ESRCH || r == -ENXIO) {
sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
return synthetic_reply_method_errno(m, r, &error);
}
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd);
if (r < 0)
return synthetic_reply_method_errno(m, -errno, NULL);
name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
KDBUS_FOREACH(name, name_list, cmd.list_size) {
struct kdbus_item *item;
char *n;
KDBUS_ITEM_FOREACH(item, name, items) {
if (item->type == KDBUS_ITEM_OWNED_NAME) {
if (!streq_ptr(item->name.name, arg0))
continue;
if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
err = -ENOMEM;
break;
}
r = strv_consume(&owners, n);
if (r < 0) {
err = r;
break;
}
}
}
if (err < 0)
break;
}
r = bus_kernel_cmd_free(a, cmd.offset);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (err < 0)
return synthetic_reply_method_errno(m, err, NULL);
return synthetic_reply_method_return_strv(m, owners);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
const char *name;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &name);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (streq(name, "org.freedesktop.DBus"))
return synthetic_reply_method_return(m, "b", true);
r = sd_bus_get_name_creds(a, name, 0, NULL);
if (r < 0 && r != -ESRCH && r != -ENXIO)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, "b", r >= 0);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
const char *name;
if (!sd_bus_message_has_signature(m, "s"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "s", &name);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_release_name(a, name);
if (r < 0) {
if (r == -ESRCH)
return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
if (r == -EADDRINUSE)
return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
return synthetic_reply_method_errno(m, r, NULL);
}
set_remove(owned_names, (char*) name);
return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
if (!sd_bus_message_has_signature(m, ""))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = shared_policy_reload(sp);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, NULL);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
const char *name;
uint32_t flags, param;
bool in_queue;
if (!sd_bus_message_has_signature(m, "su"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "su", &name, &flags);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (sp) {
Policy *policy;
bool denied;
policy = shared_policy_acquire(sp);
denied = !policy_check_own(policy, ucred->uid, ucred->gid, name);
shared_policy_release(sp, policy);
if (denied)
return synthetic_reply_method_errno(m, -EPERM, NULL);
}
if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
return synthetic_reply_method_errno(m, -EINVAL, NULL);
param = 0;
if (flags & BUS_NAME_ALLOW_REPLACEMENT)
param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
if (flags & BUS_NAME_REPLACE_EXISTING)
param |= SD_BUS_NAME_REPLACE_EXISTING;
if (!(flags & BUS_NAME_DO_NOT_QUEUE))
param |= SD_BUS_NAME_QUEUE;
r = set_put_strdup(owned_names, name);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_request_name(a, name, param);
if (r < 0) {
if (r == -EALREADY)
return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
set_remove(owned_names, (char*) name);
if (r == -EEXIST)
return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
return synthetic_reply_method_errno(m, r, NULL);
}
in_queue = (r == 0);
if (in_queue)
return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
ProxyActivation *activation;
const char *name;
uint64_t cookie;
uint32_t flags;
if (!sd_bus_message_has_signature(m, "su"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_read(m, "su", &name, &flags);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (flags != 0)
return synthetic_reply_method_errno(m, -EINVAL, NULL);
r = sd_bus_get_name_creds(a, name, 0, NULL);
if (r >= 0 || streq(name, "org.freedesktop.DBus"))
return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
if (r != -ESRCH)
return synthetic_reply_method_errno(m, r, NULL);
if (p->n_activations >= PROXY_ACTIVATIONS_MAX)
return synthetic_reply_method_errno(m, -EMFILE, NULL);
r = sd_bus_message_get_cookie(m, &cookie);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_new_method_call(a,
&msg,
name,
"/",
"org.freedesktop.DBus.Peer",
"Ping");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = bus_message_seal(msg, cookie, BUS_DEFAULT_TIMEOUT);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
activation = new0(ProxyActivation, 1);
if (!activation)
return synthetic_reply_method_errno(m, -ENOMEM, NULL);
r = sd_bus_call_async(a,
&activation->slot,
msg,
driver_activation,
activation,
0);
if (r < 0) {
free(activation);
return synthetic_reply_method_errno(m, r, NULL);
}
activation->proxy = p;
activation->request = sd_bus_message_ref(m);
LIST_PREPEND(activations_by_proxy, p->activations, activation);
++p->n_activations;
return 1;
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
_cleanup_strv_free_ char **args = NULL;
if (!sd_bus_message_has_signature(m, "a{ss}"))
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
_cleanup_free_ char *s = NULL;
const char *key;
const char *value;
r = sd_bus_message_read(m, "ss", &key, &value);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
s = strjoin(key, "=", value, NULL);
if (!s)
return synthetic_reply_method_errno(m, -ENOMEM, NULL);
if (!env_assignment_is_valid(s)) {
log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s);
} else {
r = strv_extend(&args, s);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (strv_isempty(args)) /* nothing to do? */
return synthetic_reply_method_return(m, NULL);
r = sd_bus_message_new_method_call(
a,
&msg,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"SetEnvironment");
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_message_append_strv(msg, args);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_call(a, msg, 0, NULL, NULL);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
return synthetic_reply_method_return(m, NULL);
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
return synthetic_reply_method_errno(m, r, &error);
}
}

View File

@ -1,27 +0,0 @@
#pragma once
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
#include "bus-xml-policy.h"
#include "proxy.h"
int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names);

View File

@ -1,953 +0,0 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2013 Daniel Mack
Copyright 2014 Kay Sievers
Copyright 2014 David Herrmann
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "sd-bus.h"
#include "sd-daemon.h"
#include "alloc-util.h"
#include "bus-control.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
#include "bus-xml-policy.h"
#include "driver.h"
#include "fd-util.h"
#include "formats-util.h"
#include "log.h"
#include "proxy.h"
#include "set.h"
#include "strv.h"
#include "synthesize.h"
#include "user-util.h"
#include "util.h"
static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
int r;
r = sd_bus_new(&b);
if (r < 0)
return log_error_errno(r, "Failed to allocate bus: %m");
r = sd_bus_set_description(b, "sd-proxy");
if (r < 0)
return log_error_errno(r, "Failed to set bus name: %m");
r = sd_bus_set_address(b, destination);
if (r < 0)
return log_error_errno(r, "Failed to set address to connect to: %m");
r = sd_bus_negotiate_fds(b, negotiate_fds);
if (r < 0)
return log_error_errno(r, "Failed to set FD negotiation: %m");
r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
if (r < 0)
return log_error_errno(r, "Failed to set credential negotiation: %m");
if (p->local_creds.pid > 0) {
b->fake_pids.pid = p->local_creds.pid;
b->fake_pids_valid = true;
b->fake_creds.uid = UID_INVALID;
b->fake_creds.euid = p->local_creds.uid;
b->fake_creds.suid = UID_INVALID;
b->fake_creds.fsuid = UID_INVALID;
b->fake_creds.gid = GID_INVALID;
b->fake_creds.egid = p->local_creds.gid;
b->fake_creds.sgid = GID_INVALID;
b->fake_creds.fsgid = GID_INVALID;
b->fake_creds_valid = true;
}
if (local_sec) {
b->fake_label = strdup(local_sec);
if (!b->fake_label)
return log_oom();
}
b->manual_peer_interface = true;
r = sd_bus_start(b);
if (r < 0)
return log_error_errno(r, "Failed to start bus client: %m");
p->destination_bus = b;
b = NULL;
return 0;
}
static int proxy_create_local(Proxy *p, bool negotiate_fds) {
sd_id128_t server_id;
sd_bus *b;
int r;
r = sd_bus_new(&b);
if (r < 0)
return log_error_errno(r, "Failed to allocate bus: %m");
r = sd_bus_set_fd(b, p->local_in, p->local_out);
if (r < 0) {
sd_bus_unref(b);
return log_error_errno(r, "Failed to set fds: %m");
}
/* The fds are now owned by the bus, and we indicate that by
* storing the bus object in the proxy object. */
p->local_bus = b;
r = sd_bus_get_bus_id(p->destination_bus, &server_id);
if (r < 0)
return log_error_errno(r, "Failed to get server ID: %m");
r = sd_bus_set_server(b, 1, server_id);
if (r < 0)
return log_error_errno(r, "Failed to set server mode: %m");
r = sd_bus_negotiate_fds(b, negotiate_fds);
if (r < 0)
return log_error_errno(r, "Failed to set FD negotiation: %m");
r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
if (r < 0)
return log_error_errno(r, "Failed to set credential negotiation: %m");
r = sd_bus_set_anonymous(b, true);
if (r < 0)
return log_error_errno(r, "Failed to set anonymous authentication: %m");
b->manual_peer_interface = true;
r = sd_bus_start(b);
if (r < 0)
return log_error_errno(r, "Failed to start bus client: %m");
return 0;
}
static int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Proxy *p = userdata;
p->synthetic_matched = true;
return 0; /* make sure to continue processing it in further handlers */
}
/*
* We always need NameOwnerChanged so we can synthesize NameLost and
* NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
* subscribe unconditionally.
*/
static int proxy_prepare_matches(Proxy *p) {
_cleanup_free_ char *match = NULL;
const char *unique;
int r;
if (!p->destination_bus->is_kernel)
return 0;
r = sd_bus_get_unique_name(p->destination_bus, &unique);
if (r < 0)
return log_error_errno(r, "Failed to get unique name: %m");
match = strjoin("type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
"arg1='",
unique,
"'",
NULL);
if (!match)
return log_oom();
r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
if (r < 0)
return log_error_errno(r, "Failed to add match for NameLost: %m");
free(match);
match = strjoin("type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
"arg2='",
unique,
"'",
NULL);
if (!match)
return log_oom();
r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
if (r < 0)
return log_error_errno(r, "Failed to add match for NameAcquired: %m");
free(match);
match = strjoin("type='signal',"
"destination='",
unique,
"'",
NULL);
if (!match)
return log_oom();
r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
if (r < 0)
log_error_errno(r, "Failed to add match for directed signals: %m");
/* FIXME: temporarily ignore error to support older kdbus versions */
return 0;
}
int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
_cleanup_(proxy_freep) Proxy *p = NULL;
_cleanup_free_ char *local_sec = NULL;
bool is_unix;
int r;
/* This takes possession/destroys the file descriptors passed
* in even on failure. The caller should hence forget about
* the fds in all cases after calling this function and not
* close them. */
p = new0(Proxy, 1);
if (!p) {
safe_close(in_fd);
safe_close(out_fd);
return log_oom();
}
p->local_in = in_fd;
p->local_out = out_fd;
p->owned_names = set_new(&string_hash_ops);
if (!p->owned_names)
return log_oom();
is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
if (is_unix) {
(void) getpeercred(in_fd, &p->local_creds);
(void) getpeersec(in_fd, &local_sec);
}
r = proxy_create_destination(p, destination, local_sec, is_unix);
if (r < 0)
return r;
r = proxy_create_local(p, is_unix);
if (r < 0)
return r;
r = proxy_prepare_matches(p);
if (r < 0)
return r;
*out = p;
p = NULL;
return 0;
}
Proxy *proxy_free(Proxy *p) {
ProxyActivation *activation;
if (!p)
return NULL;
while ((activation = p->activations)) {
LIST_REMOVE(activations_by_proxy, p->activations, activation);
sd_bus_message_unref(activation->request);
sd_bus_slot_unref(activation->slot);
free(activation);
}
if (p->local_bus)
sd_bus_flush_close_unref(p->local_bus);
else {
safe_close(p->local_in);
if (p->local_out != p->local_in)
safe_close(p->local_out);
}
sd_bus_flush_close_unref(p->destination_bus);
set_free_free(p->owned_names);
free(p);
return NULL;
}
int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
_cleanup_strv_free_ char **strv = NULL;
Policy *policy;
int r;
assert(p);
assert(sp);
/* no need to load legacy policy if destination is not kdbus */
if (!p->destination_bus->is_kernel)
return 0;
p->policy = sp;
policy = shared_policy_acquire(sp);
if (policy) {
/* policy already pre-loaded */
shared_policy_release(sp, policy);
return 0;
}
if (!configuration) {
const char *scope;
r = sd_bus_get_scope(p->destination_bus, &scope);
if (r < 0)
return log_error_errno(r, "Couldn't determine bus scope: %m");
if (streq(scope, "system"))
strv = strv_new("/usr/share/dbus-1/system.conf",
"/etc/dbus-1/system.conf",
"/usr/share/dbus-1/system.d/",
"/etc/dbus-1/system.d/",
"/etc/dbus-1/system-local.conf",
NULL);
else if (streq(scope, "user"))
strv = strv_new("/usr/share/dbus-1/session.conf",
"/etc/dbus-1/session.conf",
"/usr/share/dbus-1/session.d/",
"/etc/dbus-1/session.d/",
"/etc/dbus-1/session-local.conf",
NULL);
else
return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
if (!strv)
return log_oom();
configuration = strv;
}
return shared_policy_preload(sp, configuration);
}
int proxy_hello_policy(Proxy *p, uid_t original_uid) {
Policy *policy;
int r = 0;
assert(p);
if (!p->policy)
return 0;
policy = shared_policy_acquire(p->policy);
if (p->local_creds.uid == original_uid)
log_debug("Permitting access, since bus owner matches bus client.");
else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
log_debug("Permitting access due to XML policy.");
else
r = log_error_errno(EPERM, "Policy denied connection.");
shared_policy_release(p->policy, policy);
return r;
}
static int proxy_wait(Proxy *p) {
uint64_t timeout_destination, timeout_local, t;
int events_destination, events_local, fd;
struct timespec _ts, *ts;
struct pollfd *pollfd;
int r;
assert(p);
fd = sd_bus_get_fd(p->destination_bus);
if (fd < 0)
return log_error_errno(fd, "Failed to get fd: %m");
events_destination = sd_bus_get_events(p->destination_bus);
if (events_destination < 0)
return log_error_errno(events_destination, "Failed to get events mask: %m");
r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
if (r < 0)
return log_error_errno(r, "Failed to get timeout: %m");
events_local = sd_bus_get_events(p->local_bus);
if (events_local < 0)
return log_error_errno(events_local, "Failed to get events mask: %m");
r = sd_bus_get_timeout(p->local_bus, &timeout_local);
if (r < 0)
return log_error_errno(r, "Failed to get timeout: %m");
t = timeout_destination;
if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
t = timeout_local;
if (t == (uint64_t) -1)
ts = NULL;
else {
usec_t nw;
nw = now(CLOCK_MONOTONIC);
if (t > nw)
t -= nw;
else
t = 0;
ts = timespec_store(&_ts, t);
}
pollfd = (struct pollfd[3]) {
{ .fd = fd, .events = events_destination, },
{ .fd = p->local_in, .events = events_local & POLLIN, },
{ .fd = p->local_out, .events = events_local & POLLOUT, },
};
r = ppoll(pollfd, 3, ts, NULL);
if (r < 0)
return log_error_errno(errno, "ppoll() failed: %m");
return 0;
}
static int handle_policy_error(sd_bus_message *m, int r) {
if (r == -ESRCH || r == -ENXIO)
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
return r;
}
static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
int r;
assert(from);
assert(to);
assert(m);
if (!policy)
return 0;
/*
* dbus-1 distinguishes expected and non-expected replies by tracking
* method-calls and timeouts. By default, DENY rules are *NEVER* applied
* on expected replies, unless explicitly specified. But we dont track
* method-calls, thus, we cannot know whether a reply is expected.
* Fortunately, the kdbus forbids non-expected replies, so we can safely
* ignore any policy on those and let the kernel deal with it.
*
* TODO: To be correct, we should only ignore policy-tags that are
* applied on non-expected replies. However, so far we don't parse those
* tags so we let everything pass. I haven't seen a DENY policy tag on
* expected-replies, ever, so don't bother..
*/
if (m->reply_cookie > 0)
return 0;
if (from->is_kernel) {
uid_t sender_uid = UID_INVALID;
gid_t sender_gid = GID_INVALID;
char **sender_names = NULL;
/* Driver messages are always OK */
if (streq_ptr(m->sender, "org.freedesktop.DBus"))
return 0;
/* The message came from the kernel, and is sent to our legacy client. */
(void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
(void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
(void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *sender_creds = NULL;
/* If the message came from another legacy
* client, then the message creds will be
* missing, simply because on legacy clients
* per-message creds were unknown. In this
* case, query the creds of the peer
* instead. */
r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
if (r < 0)
return handle_policy_error(m, r);
(void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
(void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
}
/* First check whether the sender can send the message to our name */
if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
return 0;
/* Return an error back to the caller */
if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
/* Return 1, indicating that the message shall not be processed any further */
return 1;
}
if (to->is_kernel) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *destination_creds = NULL;
uid_t destination_uid = UID_INVALID;
gid_t destination_gid = GID_INVALID;
const char *destination_unique = NULL;
char **destination_names = NULL;
char *n;
/* Driver messages are always OK */
if (streq_ptr(m->destination, "org.freedesktop.DBus"))
return 0;
/* The message came from the legacy client, and is sent to kdbus. */
if (m->destination) {
r = bus_get_name_creds_kdbus(to, m->destination,
SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
true, &destination_creds);
if (r < 0)
return handle_policy_error(m, r);
r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
if (r < 0)
return handle_policy_error(m, r);
(void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
(void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
(void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
}
/* First check if we (the sender) can send to this name */
if (sd_bus_message_is_signal(m, NULL, NULL)) {
/* If we forward a signal from dbus-1 to kdbus, we have
* no idea who the recipient is. Therefore, we cannot
* apply any dbus-1 policies that match on receiver
* credentials. We know sd-bus always sets
* KDBUS_MSG_SIGNAL, so the kernel applies policies to
* the message. Therefore, skip policy checks in this
* case. */
return 0;
} else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
if (n) {
/* If we made a receiver decision, then remember which
* name's policy we used, and to which unique ID it
* mapped when we made the decision. Then, let's pass
* this to the kernel when sending the message, so that
* it refuses the operation should the name and unique
* ID not map to each other anymore. */
r = free_and_strdup(&m->destination_ptr, n);
if (r < 0)
return r;
r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
if (r < 0)
return r;
}
if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
return 0;
}
/* Return an error back to the caller */
if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
/* Return 1, indicating that the message shall not be processed any further */
return 1;
}
return 0;
}
static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
Policy *policy;
int r;
assert(sp);
policy = shared_policy_acquire(sp);
r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
shared_policy_release(sp, policy);
return r;
}
static int process_hello(Proxy *p, sd_bus_message *m) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
bool is_hello;
int r;
assert(p);
assert(m);
/* As reaction to hello we need to respond with two messages:
* the callback reply and the NameAcquired for the unique
* name, since hello is otherwise obsolete on kdbus. */
is_hello =
sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
streq_ptr(m->destination, "org.freedesktop.DBus");
if (!is_hello) {
if (p->got_hello)
return 0;
return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
}
if (p->got_hello)
return log_error_errno(EIO, "Got duplicate hello, aborting.");
p->got_hello = true;
if (!p->destination_bus->is_kernel)
return 0;
r = sd_bus_message_new_method_return(m, &n);
if (r < 0)
return log_error_errno(r, "Failed to generate HELLO reply: %m");
r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
if (r < 0)
return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
r = bus_message_append_sender(n, "org.freedesktop.DBus");
if (r < 0)
return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
r = bus_seal_synthetic_message(p->local_bus, n);
if (r < 0)
return log_error_errno(r, "Failed to seal HELLO reply: %m");
r = sd_bus_send(p->local_bus, n, NULL);
if (r < 0)
return log_error_errno(r, "Failed to send HELLO reply: %m");
n = sd_bus_message_unref(n);
r = sd_bus_message_new_signal(
p->local_bus,
&n,
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"NameAcquired");
if (r < 0)
return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
if (r < 0)
return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
r = bus_message_append_sender(n, "org.freedesktop.DBus");
if (r < 0)
return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
r = sd_bus_message_set_destination(n, p->destination_bus->unique_name);
if (r < 0)
return log_error_errno(r, "Failed to set destination for NameAcquired message: %m");
r = bus_seal_synthetic_message(p->local_bus, n);
if (r < 0)
return log_error_errno(r, "Failed to seal NameAcquired message: %m");
r = sd_bus_send(p->local_bus, n, NULL);
if (r < 0)
return log_error_errno(r, "Failed to send NameAcquired message: %m");
return 1;
}
static int patch_sender(sd_bus *a, sd_bus_message *m) {
char **well_known = NULL;
sd_bus_creds *c;
int r;
assert(a);
assert(m);
if (!a->is_kernel)
return 0;
/* We will change the sender of messages from the bus driver
* so that they originate from the bus driver. This is a
* speciality originating from dbus1, where the bus driver did
* not have a unique id, but only the well-known name. */
c = sd_bus_message_get_creds(m);
if (!c)
return 0;
r = sd_bus_creds_get_well_known_names(c, &well_known);
if (r < 0)
return r;
if (strv_contains(well_known, "org.freedesktop.DBus"))
m->sender = "org.freedesktop.DBus";
return 0;
}
static int proxy_process_destination_to_local(Proxy *p) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
bool matched, matched_synthetic;
int r;
assert(p);
/*
* Usually, we would just take any message that the bus passes to us
* and forward it to the local connection. However, there are actually
* applications that fail if they receive broadcasts that they didn't
* subscribe to. Therefore, we actually emulate a real broadcast
* matching here, and discard any broadcasts that weren't matched. Our
* match-handlers remembers whether a message was matched by any rule,
* by marking it in @p->message_matched.
*/
r = sd_bus_process(p->destination_bus, &m);
matched = p->message_matched;
matched_synthetic = p->synthetic_matched;
p->message_matched = false;
p->synthetic_matched = false;
if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
return r;
if (r < 0) {
log_error_errno(r, "Failed to process destination bus: %m");
return r;
}
if (r == 0)
return 0;
if (!m)
return 1;
/* We officially got EOF, let's quit */
if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
return -ECONNRESET;
r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to synthesize message: %m");
/* discard broadcasts that were not matched by any MATCH rule */
if (!matched && !sd_bus_message_get_destination(m)) {
if (!matched_synthetic)
log_debug("Dropped unmatched broadcast: uid=" UID_FMT " gid=" GID_FMT " pid=" PID_FMT " message=%s path=%s interface=%s member=%s sender=%s destination=%s",
p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type),
strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination));
return 1;
}
patch_sender(p->destination_bus, m);
if (p->policy) {
r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to process policy: %m");
if (r > 0)
return 1;
}
r = sd_bus_send(p->local_bus, m, NULL);
if (r < 0) {
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
/* If the peer tries to send a reply and it is
* rejected with EBADSLT by the kernel, we ignore the
* error. This catches cases where the original
* method-call didn't had EXPECT_REPLY set, but the
* proxy-peer still sends a reply. This is allowed in
* dbus1, but not in kdbus. We don't want to track
* reply-windows in the proxy, so we simply ignore
* EBADSLT for all replies. The only downside is, that
* callers are no longer notified if their replies are
* dropped. However, this is equivalent to the
* caller's timeout to expire, so this should be
* acceptable. Nobody sane sends replies without a
* matching method-call, so nobody should care. */
/* FIXME: remove -EPERM when kdbus is updated */
if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
return 1;
/* Return the error to the client, if we can */
synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
if (r == -ENOBUFS) {
/* if local dbus1 peer does not dispatch its queue, warn only once */
if (!p->queue_overflow)
log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid);
p->queue_overflow = true;
} else
log_error_errno(r,
"Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
return 1;
}
p->queue_overflow = false;
return 1;
}
static int proxy_process_local_to_destination(Proxy *p) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(p);
r = sd_bus_process(p->local_bus, &m);
if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
return r;
if (r < 0) {
log_error_errno(r, "Failed to process local bus: %m");
return r;
}
if (r == 0)
return 0;
if (!m)
return 1;
/* We officially got EOF, let's quit */
if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
return -ECONNRESET;
r = process_hello(p, m);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to process HELLO: %m");
if (r > 0)
return 1;
r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to process driver calls: %m");
if (r > 0)
return 1;
for (;;) {
if (p->policy) {
r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to process policy: %m");
if (r > 0)
return 1;
}
r = sd_bus_send(p->destination_bus, m, NULL);
if (r < 0) {
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
/* The name database changed since the policy check, hence let's check again */
if (r == -EREMCHG)
continue;
/* see above why EBADSLT is ignored for replies */
if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
return 1;
synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
log_error_errno(r,
"Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
return 1;
}
break;
}
return 1;
}
int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Proxy *p = userdata;
p->message_matched = true;
return 0; /* make sure to continue processing it in further handlers */
}
int proxy_run(Proxy *p) {
int r;
assert(p);
for (;;) {
bool busy = false;
if (p->got_hello) {
/* Read messages from bus, to pass them on to our client */
r = proxy_process_destination_to_local(p);
if (r == -ECONNRESET || r == -ENOTCONN)
return 0;
if (r < 0)
return r;
if (r > 0)
busy = true;
}
/* Read messages from our client, to pass them on to the bus */
r = proxy_process_local_to_destination(p);
if (r == -ECONNRESET || r == -ENOTCONN)
return 0;
if (r < 0)
return r;
if (r > 0)
busy = true;
if (!busy) {
r = proxy_wait(p);
if (r == -ECONNRESET || r == -ENOTCONN)
return 0;
if (r < 0)
return r;
}
}
return 0;
}

View File

@ -1,66 +0,0 @@
#pragma once
/***
This file is part of systemd.
Copyright 2014 David Herrmann
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
#include "bus-xml-policy.h"
typedef struct Proxy Proxy;
typedef struct ProxyActivation ProxyActivation;
#define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */
struct Proxy {
sd_bus *local_bus;
struct ucred local_creds;
int local_in;
int local_out;
sd_bus *destination_bus;
Set *owned_names;
SharedPolicy *policy;
LIST_HEAD(ProxyActivation, activations);
size_t n_activations;
bool got_hello : 1;
bool queue_overflow : 1;
bool message_matched : 1;
bool synthetic_matched : 1;
};
struct ProxyActivation {
LIST_FIELDS(ProxyActivation, activations_by_proxy);
Proxy *proxy;
sd_bus_message *request;
sd_bus_slot *slot;
};
int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
Proxy *proxy_free(Proxy *p);
int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration);
int proxy_hello_policy(Proxy *p, uid_t original_uid);
int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error);
int proxy_run(Proxy *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free);

View File

@ -1,244 +0,0 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2013 Daniel Mack
Copyright 2014 Kay Sievers
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <getopt.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "sd-bus.h"
#include "sd-daemon.h"
#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "def.h"
#include "formats-util.h"
#include "log.h"
#include "proxy.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
static char *arg_address = NULL;
static char *arg_command_line_buffer = NULL;
static int help(void) {
printf("%s [OPTIONS...]\n\n"
"Connect STDIO to a given bus address.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --machine=MACHINE Connect to specified machine\n"
" --address=ADDRESS Connect to the bus specified by ADDRESS\n"
" (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_ADDRESS,
ARG_MACHINE,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "address", required_argument, NULL, ARG_ADDRESS },
{ "machine", required_argument, NULL, ARG_MACHINE },
{},
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
return version();
case ARG_ADDRESS: {
char *a;
a = strdup(optarg);
if (!a)
return log_oom();
free(arg_address);
arg_address = a;
break;
}
case ARG_MACHINE: {
_cleanup_free_ char *e = NULL;
char *a;
e = bus_address_escape(optarg);
if (!e)
return log_oom();
a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
if (!a)
return log_oom();
free(arg_address);
arg_address = a;
break;
}
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
/* If the first command line argument is only "x" characters
* we'll write who we are talking to into it, so that "ps" is
* explanatory */
arg_command_line_buffer = argv[optind];
if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
log_error("Too many arguments");
return -EINVAL;
}
if (!arg_address) {
arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
if (!arg_address)
return log_oom();
}
return 1;
}
static int rename_service(sd_bus *a, sd_bus *b) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_free_ char *p = NULL, *name = NULL;
const char *comm;
char **cmdline;
uid_t uid;
pid_t pid;
int r;
assert(a);
assert(b);
r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &uid);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
r = sd_bus_creds_get_cmdline(creds, &cmdline);
if (r < 0)
return r;
r = sd_bus_creds_get_comm(creds, &comm);
if (r < 0)
return r;
name = uid_to_name(uid);
if (!name)
return -ENOMEM;
p = strv_join(cmdline, " ");
if (!p)
return -ENOMEM;
/* The status string gets the full command line ... */
sd_notifyf(false,
"STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
pid, p,
uid, name);
/* ... and the argv line only the short comm */
if (arg_command_line_buffer) {
size_t m, w;
m = strlen(arg_command_line_buffer);
w = snprintf(arg_command_line_buffer, m,
"[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
pid, comm,
uid, name);
if (m > w)
memzero(arg_command_line_buffer + w, m - w);
}
log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
pid, p,
uid, name,
a->unique_name);
return 0;
}
int main(int argc, char *argv[]) {
_cleanup_(proxy_freep) Proxy *p = NULL;
int r;
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address);
if (r < 0)
goto finish;
r = rename_service(p->destination_bus, p->local_bus);
if (r < 0)
log_debug_errno(r, "Failed to rename process: %m");
r = proxy_run(p);
finish:
sd_notify(false,
"STOPPING=1\n"
"STATUS=Shutting down.");
free(arg_address);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -1,225 +0,0 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2013 Daniel Mack
Copyright 2014 Kay Sievers
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stddef.h>
#include "sd-bus.h"
#include "bus-internal.h"
#include "bus-match.h"
#include "bus-message.h"
#include "bus-util.h"
#include "synthesize.h"
#include "util.h"
int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
int r;
assert(b);
assert(m);
r = bus_message_append_sender(m, "org.freedesktop.DBus");
if (r < 0)
return r;
r = bus_seal_synthetic_message(b, m);
if (r < 0)
return r;
return sd_bus_send(b, m, NULL);
}
int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
r = sd_bus_message_new_method_error(call, &m, e);
if (r < 0)
return r;
return synthetic_driver_send(call->bus, m);
}
int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
va_list ap;
va_start(ap, format);
bus_error_setfv(&error, name, format, ap);
va_end(ap);
return synthetic_reply_method_error(call, &error);
}
int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
_cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
assert(call);
if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
if (sd_bus_error_is_set(p))
return synthetic_reply_method_error(call, p);
sd_bus_error_set_errno(&berror, error);
return synthetic_reply_method_error(call, &berror);
}
int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) {
_cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
va_list ap;
assert(call);
if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
va_start(ap, format);
sd_bus_error_set_errnofv(&berror, error, format, ap);
va_end(ap);
return synthetic_reply_method_error(call, &berror);
}
int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
r = sd_bus_message_new_method_return(call, &m);
if (r < 0)
return r;
if (!isempty(types)) {
va_list ap;
va_start(ap, types);
r = bus_message_append_ap(m, types, ap);
va_end(ap);
if (r < 0)
return r;
}
return synthetic_driver_send(call->bus, m);
}
int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
r = sd_bus_message_new_method_return(call, &m);
if (r < 0)
return synthetic_reply_method_errno(call, r, NULL);
r = sd_bus_message_append_strv(m, l);
if (r < 0)
return synthetic_reply_method_errno(call, r, NULL);
return synthetic_driver_send(call->bus, m);
}
int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
const char *name, *old_owner, *new_owner;
int r;
assert(p);
assert(a);
assert(b);
assert(m);
/* If we get NameOwnerChanged for our own name, we need to
* synthesize NameLost/NameAcquired, since socket clients need
* that, even though it is obsoleted on kdbus */
if (!a->is_kernel)
return 0;
if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
!streq_ptr(m->path, "/org/freedesktop/DBus") ||
!streq_ptr(m->sender, "org.freedesktop.DBus"))
return 0;
r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
if (r < 0)
return r;
r = sd_bus_message_rewind(m, true);
if (r < 0)
return r;
if (streq(old_owner, a->unique_name)) {
r = sd_bus_message_new_signal(
b,
&n,
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"NameLost");
} else if (streq(new_owner, a->unique_name)) {
r = sd_bus_message_new_signal(
b,
&n,
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"NameAcquired");
} else
return 0;
if (r < 0)
return r;
r = sd_bus_message_append(n, "s", name);
if (r < 0)
return r;
r = bus_message_append_sender(n, "org.freedesktop.DBus");
if (r < 0)
return r;
r = sd_bus_message_set_destination(n, a->unique_name);
if (r < 0)
return r;
r = bus_seal_synthetic_message(b, n);
if (r < 0)
return r;
return sd_bus_send(b, n, NULL);
}

View File

@ -1,36 +0,0 @@
#pragma once
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
#include "proxy.h"
int synthetic_driver_send(sd_bus *b, sd_bus_message *m);
int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...);
int synthetic_reply_method_return_strv(sd_bus_message *call, char **l);
int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e);
int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4);
int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p);
int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4);
int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m);

View File

@ -1,170 +0,0 @@
/***
This file is part of systemd.
Copyright 2014 Daniel Mack
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <stddef.h>
#include <unistd.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "bus-xml-policy.h"
#include "log.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
static int test_policy_load(Policy *p, const char *name) {
_cleanup_free_ char *path = NULL;
int r = 0;
path = strjoin(TEST_DIR, "/bus-policy/", name, NULL);
assert_se(path);
if (access(path, R_OK) == 0)
r = policy_load(p, STRV_MAKE(path));
else
r = -ENOENT;
return r;
}
static int show_policy(const char *fn) {
Policy p = {};
int r;
r = policy_load(&p, STRV_MAKE(fn));
if (r < 0) {
log_error_errno(r, "Failed to load policy %s: %m", fn);
return r;
}
policy_dump(&p);
policy_free(&p);
return 0;
}
int main(int argc, char *argv[]) {
Policy p = {};
printf("Showing session policy BEGIN\n");
show_policy("/etc/dbus-1/session.conf");
printf("Showing session policy END\n");
printf("Showing system policy BEGIN\n");
show_policy("/etc/dbus-1/system.conf");
printf("Showing system policy END\n");
/* Ownership tests */
assert_se(test_policy_load(&p, "ownerships.conf") == 0);
assert_se(policy_check_own(&p, 0, 0, "org.test.test1") == true);
assert_se(policy_check_own(&p, 1, 0, "org.test.test1") == true);
assert_se(policy_check_own(&p, 0, 0, "org.test.test2") == true);
assert_se(policy_check_own(&p, 1, 0, "org.test.test2") == false);
assert_se(policy_check_own(&p, 0, 0, "org.test.test3") == false);
assert_se(policy_check_own(&p, 1, 0, "org.test.test3") == false);
assert_se(policy_check_own(&p, 0, 0, "org.test.test4") == false);
assert_se(policy_check_own(&p, 1, 0, "org.test.test4") == true);
policy_free(&p);
/* Signaltest */
assert_se(test_policy_load(&p, "signals.conf") == 0);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true);
assert_se(policy_check_one_send(&p, 1, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == false);
policy_free(&p);
/* Method calls */
assert_se(test_policy_load(&p, "methods.conf") == 0);
policy_dump(&p);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true);
assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test3", "/an/object/path", "org.test.int3", "Member111") == true);
policy_free(&p);
/* User and groups */
assert_se(test_policy_load(&p, "hello.conf") == 0);
policy_dump(&p);
assert_se(policy_check_hello(&p, 0, 0) == true);
assert_se(policy_check_hello(&p, 1, 0) == false);
assert_se(policy_check_hello(&p, 0, 1) == false);
policy_free(&p);
/* dbus1 test file: ownership */
assert_se(test_policy_load(&p, "check-own-rules.conf") >= 0);
policy_dump(&p);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop") == false);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystem") == false);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems") == true);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo") == true);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo.bar") == true);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2") == false);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo") == false);
assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo.bar") == false);
policy_free(&p);
/* dbus1 test file: many rules */
assert_se(test_policy_load(&p, "many-rules.conf") >= 0);
policy_dump(&p);
policy_free(&p);
/* dbus1 test file: generic test */
assert_se(test_policy_load(&p, "test.conf") >= 0);
policy_dump(&p);
assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService") == true);
assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService2") == false);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false);
assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false);
assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false);
assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService") == false);
assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService2") == false);
assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false);
assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false);
assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false);
assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false);
policy_free(&p);
return EXIT_SUCCESS;
}

View File

@ -1,117 +0,0 @@
/***
This file is part of systemd.
Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-util.h"
#include "log.h"
#include "util.h"
typedef struct {
const char *sender;
int matched_acquired;
} TestProxyMatch;
static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) {
TestProxyMatch *match = userdata;
const char *name;
int r;
r = sd_bus_message_read(m, "s", &name);
assert_se(r >= 0);
if (!streq_ptr(match->sender, name))
return 0;
++match->matched_acquired;
return 1;
}
static void test_proxy_matched(void) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL;
_cleanup_free_ char *matchstr = NULL;
TestProxyMatch match = {};
const char *me;
int r;
/* open bus 'a' */
r = sd_bus_new(&a);
assert_se(r >= 0);
r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket");
assert_se(r >= 0);
r = sd_bus_set_bus_client(a, true);
assert_se(r >= 0);
r = sd_bus_start(a);
assert_se(r >= 0);
r = sd_bus_get_unique_name(a, &me);
assert_se(r >= 0);
matchstr = strjoin("type='signal',"
"member='NameAcquired',"
"destination='",
me,
"'",
NULL);
assert_se(matchstr);
r = sd_bus_add_match(a, NULL, matchstr, test_proxy_acquired, &match);
assert_se(r >= 0);
r = sd_bus_get_unique_name(a, &match.sender);
assert_se(r >= 0);
/* barrier to guarantee proxy/dbus-daemon handled the previous data */
r = sd_bus_call_method(a,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetId",
NULL, NULL, NULL);
assert_se(r >= 0);
/* now we can be sure the Name* signals were sent */
do {
r = sd_bus_process(a, NULL);
} while (r > 0);
assert_se(r == 0);
assert_se(match.matched_acquired == 1);
}
int main(int argc, char **argv) {
if (access("/var/run/dbus/system_bus_socket", F_OK) < 0)
return EXIT_TEST_SKIP;
log_parse_environment();
test_proxy_matched();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,301 @@
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <getopt.h>
#include <poll.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "sd-bus.h"
#include "sd-daemon.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "build.h"
#include "log.h"
#include "util.h"
#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
const char *arg_bus_path = DEFAULT_BUS_PATH;
static int help(void) {
printf("%s [OPTIONS...]\n\n"
"STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --bus-path=PATH Path to the kernel bus (default: %s)\n",
program_invocation_short_name, DEFAULT_BUS_PATH);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "bus-path", required_argument, NULL, 'p' },
{ NULL, 0, NULL, 0 }
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) {
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
return version();
case '?':
return -EINVAL;
case 'p':
arg_bus_path = optarg;
break;
default:
log_error("Unknown option code %c", c);
return -EINVAL;
}
}
return 1;
}
int main(int argc, char *argv[]) {
_cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
sd_id128_t server_id;
bool is_unix;
int r, in_fd, out_fd;
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = sd_listen_fds(0);
if (r == 0) {
in_fd = STDIN_FILENO;
out_fd = STDOUT_FILENO;
} else if (r == 1) {
in_fd = SD_LISTEN_FDS_START;
out_fd = SD_LISTEN_FDS_START;
} else {
log_error("Illegal number of file descriptors passed\n");
goto finish;
}
is_unix =
sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
r = sd_bus_new(&a);
if (r < 0) {
log_error_errno(r, "Failed to allocate bus: %m");
goto finish;
}
r = sd_bus_set_address(a, arg_bus_path);
if (r < 0) {
log_error_errno(r, "Failed to set address to connect to: %m");
goto finish;
}
r = sd_bus_negotiate_fds(a, is_unix);
if (r < 0) {
log_error_errno(r, "Failed to set FD negotiation: %m");
goto finish;
}
r = sd_bus_start(a);
if (r < 0) {
log_error_errno(r, "Failed to start bus client: %m");
goto finish;
}
r = sd_bus_get_bus_id(a, &server_id);
if (r < 0) {
log_error_errno(r, "Failed to get server ID: %m");
goto finish;
}
r = sd_bus_new(&b);
if (r < 0) {
log_error_errno(r, "Failed to allocate bus: %m");
goto finish;
}
r = sd_bus_set_fd(b, in_fd, out_fd);
if (r < 0) {
log_error_errno(r, "Failed to set fds: %m");
goto finish;
}
r = sd_bus_set_server(b, 1, server_id);
if (r < 0) {
log_error_errno(r, "Failed to set server mode: %m");
goto finish;
}
r = sd_bus_negotiate_fds(b, is_unix);
if (r < 0) {
log_error_errno(r, "Failed to set FD negotiation: %m");
goto finish;
}
r = sd_bus_set_anonymous(b, true);
if (r < 0) {
log_error_errno(r, "Failed to set anonymous authentication: %m");
goto finish;
}
r = sd_bus_start(b);
if (r < 0) {
log_error_errno(r, "Failed to start bus client: %m");
goto finish;
}
for (;;) {
_cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
int events_a, events_b, fd;
uint64_t timeout_a, timeout_b, t;
struct timespec _ts, *ts;
r = sd_bus_process(a, &m);
if (r < 0) {
log_error_errno(r, "Failed to process bus a: %m");
goto finish;
}
if (m) {
r = sd_bus_send(b, m, NULL);
if (r < 0) {
log_error_errno(r, "Failed to send message: %m");
goto finish;
}
}
if (r > 0)
continue;
r = sd_bus_process(b, &m);
if (r < 0) {
/* treat 'connection reset by peer' as clean exit condition */
if (r == -ECONNRESET)
r = 0;
goto finish;
}
if (m) {
r = sd_bus_send(a, m, NULL);
if (r < 0) {
log_error_errno(r, "Failed to send message: %m");
goto finish;
}
}
if (r > 0)
continue;
fd = sd_bus_get_fd(a);
if (fd < 0) {
log_error_errno(r, "Failed to get fd: %m");
goto finish;
}
events_a = sd_bus_get_events(a);
if (events_a < 0) {
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
r = sd_bus_get_timeout(a, &timeout_a);
if (r < 0) {
log_error_errno(r, "Failed to get timeout: %m");
goto finish;
}
events_b = sd_bus_get_events(b);
if (events_b < 0) {
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
r = sd_bus_get_timeout(b, &timeout_b);
if (r < 0) {
log_error_errno(r, "Failed to get timeout: %m");
goto finish;
}
t = timeout_a;
if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
t = timeout_b;
if (t == (uint64_t) -1)
ts = NULL;
else {
usec_t nw;
nw = now(CLOCK_MONOTONIC);
if (t > nw)
t -= nw;
else
t = 0;
ts = timespec_store(&_ts, t);
}
{
struct pollfd p[3] = {
{.fd = fd, .events = events_a, },
{.fd = STDIN_FILENO, .events = events_b & POLLIN, },
{.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};
r = ppoll(p, ELEMENTSOF(p), ts, NULL);
}
if (r < 0) {
log_error("ppoll() failed: %m");
goto finish;
}
}
r = 0;
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -19,7 +19,6 @@
#include "architecture.h"
#include "automount.h"
#include "bus-xml-policy.h"
#include "busname.h"
#include "cgroup.h"
#include "compress.h"
@ -83,8 +82,6 @@ int main(int argc, char **argv) {
test_table(path_result, PATH_RESULT);
test_table(path_state, PATH_STATE);
test_table(path_type, PATH_TYPE);
test_table(policy_item_class, POLICY_ITEM_CLASS);
test_table(policy_item_type, POLICY_ITEM_TYPE);
test_table(protect_home, PROTECT_HOME);
test_table(protect_system, PROTECT_SYSTEM);
test_table(rlimit, RLIMIT);

View File

@ -6,7 +6,6 @@
# (at your option) any later version.
g systemd-journal - -
u systemd-bus-proxy - "systemd Bus Proxy"
m4_ifdef(`ENABLE_NETWORKD',
u systemd-network - "systemd Network Management"
)m4_dnl

2
units/.gitignore vendored
View File

@ -1,4 +1,3 @@
/systemd-bus-proxyd.service.m4
/user@.service.m4
/console-getty.service
/console-getty.service.m4
@ -24,7 +23,6 @@
/systemd-backlight@.service
/systemd-binfmt.service
/systemd-bootchart.service
/systemd-bus-proxyd.service
/systemd-coredump@.service
/systemd-firstboot.service
/systemd-fsck-root.service

View File

@ -1,25 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Legacy D-Bus Protocol Compatibility Daemon
[Service]
ExecStart=@rootlibexecdir@/systemd-bus-proxyd --address=kernel:path=/sys/fs/kdbus/0-system/bus
ExecReload=@bindir@/busctl --address=unix:path=/run/dbus/system_bus_socket call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus ReloadConfig
NotifyAccess=main
CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP m4_ifdef(`HAVE_SMACK', CAP_MAC_ADMIN )
PrivateTmp=yes
PrivateDevices=yes
PrivateNetwork=yes
ProtectSystem=full
ProtectHome=yes
# The proxy manages connections of all users, so it needs an elevated file
# limit. It does proper per-user accounting (indirectly via kdbus), therefore,
# the effective per-user limits stay the same.
LimitNOFILE=16384

View File

@ -1,12 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Legacy D-Bus Protocol Compatibility Socket
[Socket]
ListenStream=/var/run/dbus/system_bus_socket

View File

@ -1,2 +1 @@
/systemd-exit.service
/systemd-bus-proxyd.service

View File

@ -1,14 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Legacy D-Bus Protocol Compatibility Daemon
[Service]
ExecStart=@rootlibexecdir@/systemd-bus-proxyd --address=kernel:path=/sys/fs/kdbus/%U-user/bus
ExecReload=@bindir@/busctl --address=unix:path=/run/user/%U/bus call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus ReloadConfig
NotifyAccess=main

View File

@ -1,12 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Legacy D-Bus Protocol Compatibility Socket
[Socket]
ListenStream=%t/bus