bus-proxyd.c revision 5e2de0eb1dff7bb86b40c16a0a9c9c4de33e77d1
5e6afdd3d359fc42de7ac432243e98673577e81fLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering This file is part of systemd.
5e6afdd3d359fc42de7ac432243e98673577e81fLennart Poettering Copyright 2010 Lennart Poettering
5e6afdd3d359fc42de7ac432243e98673577e81fLennart Poettering Copyright 2013 Daniel Mack
5e6afdd3d359fc42de7ac432243e98673577e81fLennart Poettering Copyright 2014 Kay Sievers
49dbfa7b2b0bf3906704dac1eaeb4eba91056a19Lennart Poettering systemd is free software; you can redistribute it and/or modify it
b401e1fb9df7ea8b0fd26e16d886056a5ae7c5d9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering (at your option) any later version.
58f2fab16da947052756b7f9ace40f6ee7fa1519Zbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
58f2fab16da947052756b7f9ace40f6ee7fa1519Zbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
3d88bf660dae270c051c8319bba62c58a50c9d2bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3d88bf660dae270c051c8319bba62c58a50c9d2bLennart Poettering Lesser General Public License for more details.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stddef.h>
#include <getopt.h>
#include "log.h"
#include "util.h"
#include "socket-util.h"
#include "sd-daemon.h"
#include "sd-bus.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
#include "build.h"
#include "strv.h"
#include "def.h"
#include "capability.h"
#include "bus-control.h"
#include "smack-util.h"
#include "set.h"
#include "bus-xml-policy.h"
#include "driver.h"
#include "synthesize.h"
static bool arg_drop_privileges = false;
static int help(void) {
help();
case ARG_VERSION:
case ARG_ADDRESS: {
return log_oom();
arg_address = a;
case ARG_DROP_PRIVILEGES:
arg_drop_privileges = true;
case ARG_CONFIGURATION:
return log_oom();
case ARG_MACHINE: {
return log_oom();
#ifdef ENABLE_KDBUS
return log_oom();
arg_address = a;
return -EINVAL;
return -EINVAL;
if (!arg_address) {
if (!arg_address)
return log_oom();
const char *comm;
char **cmdline;
assert(a);
assert(b);
r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
if (!name)
return -ENOMEM;
return -ENOMEM;
sd_notifyf(false,
pid, p,
if (arg_command_line_buffer) {
size_t m, w;
pid, p,
a->unique_name);
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
assert(m);
if (!policy)
if (m->reply_cookie > 0)
bool granted = false;
r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_UID|SD_BUS_CREDS_GID, true, &sender_creds);
return handle_policy_error(m, r);
if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member, false))
granted = true;
Iterator i;
if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member, false)) {
granted = true;
if (granted) {
if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, false))
if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, false))
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
bool granted = false;
if (m->destination) {
true, &destination_creds);
return handle_policy_error(m, r);
return handle_policy_error(m, r);
if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, true))
granted = true;
if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, true)) {
granted = true;
if (granted) {
if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member, true))
Iterator i;
if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member, true))
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
bool is_hello;
assert(a);
assert(b);
assert(m);
is_hello =
if (!is_hello) {
if (*got_hello)
return -EIO;
if (*got_hello) {
return -EIO;
*got_hello = true;
if (!a->is_kernel)
r = sd_bus_message_new_method_return(m, &n);
r = bus_seal_synthetic_message(b, n);
n = sd_bus_message_unref(n);
"/org/freedesktop/DBus",
r = bus_seal_synthetic_message(b, n);
sd_bus_creds *c;
assert(a);
assert(m);
if (!a->is_kernel)
c = sd_bus_message_get_creds(m);
#ifdef HAVE_SMACK
if (!mac_smack_use())
bool got_hello = false;
bool is_unix;
log_open();
goto finish;
r = sd_listen_fds(0);
goto finish;
is_unix =
if (is_unix) {
if (arg_drop_privileges) {
goto finish;
goto finish;
if (!owned_names) {
log_oom();
goto finish;
r = sd_bus_new(&a);
goto finish;
goto finish;
goto finish;
goto finish;
r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
goto finish;
a->fake_pids_valid = true;
a->fake_creds_valid = true;
if (peersec) {
a->manual_peer_interface = true;
r = sd_bus_start(a);
goto finish;
goto finish;
if (a->is_kernel) {
if (!arg_configuration) {
const char *scope;
goto finish;
"/etc/dbus-1/system.conf",
NULL);
"/etc/dbus-1/session.conf",
NULL);
goto finish;
if (!arg_configuration) {
r = log_oom();
goto finish;
goto finish;
goto finish;
r = sd_bus_new(&b);
goto finish;
goto finish;
goto finish;
goto finish;
r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
goto finish;
r = sd_bus_set_anonymous(b, true);
goto finish;
b->manual_peer_interface = true;
r = sd_bus_start(b);
goto finish;
r = rename_service(a, b);
if (a->is_kernel) {
const char *unique;
goto finish;
"path='/org/freedesktop/DBus',"
NULL);
if (!match) {
log_oom();
goto finish;
goto finish;
"path='/org/freedesktop/DBus',"
NULL);
if (!match) {
log_oom();
goto finish;
goto finish;
if (got_hello) {
r = sd_bus_process(a, &m);
if (r == -ECONNRESET)
goto finish;
bool processed = false;
goto finish;
k = synthesize_name_acquired(a, b, m);
goto finish;
patch_sender(a, m);
if (policy) {
goto finish;
processed = true;
if (!processed) {
if (k == -ECONNRESET) {
goto finish;
goto finish;
r = sd_bus_process(b, &m);
if (r == -ECONNRESET)
goto finish;
bool processed = false;
goto finish;
goto finish;
processed = true;
if (!processed) {
goto finish;
processed = true;
if (!processed) {
if (policy) {
goto finish;
processed = true;
if (k == -EREMCHG) {
} else if (k == -ECONNRESET) {
goto finish;
goto finish;
if (fd < 0) {
goto finish;
if (events_a < 0) {
goto finish;
goto finish;
if (events_b < 0) {
goto finish;
goto finish;
t = timeout_a;
t = timeout_b;
if (t > nw)
t -= nw;
goto finish;
sd_notify(false,