diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 35 | ||||
-rw-r--r-- | src/bus-proxyd/stdio-bridge.c | 282 |
3 files changed, 304 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore index d4704feed..17a64c277 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ /systemd-shutdownd /systemd-sleep /systemd-socket-proxyd +/systemd-stdio-bridge /systemd-subterm /systemd-sysctl /systemd-system-update-generator diff --git a/Makefile.am b/Makefile.am index 4bbe69eba..20f760c5b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -391,6 +391,7 @@ rootlibexec_PROGRAMS = \ systemd-sysctl \ systemd-sleep \ systemd-bus-proxyd \ + systemd-stdio-bridge \ systemd-socket-proxyd \ systemd-update-done @@ -2023,11 +2024,10 @@ test_conf_files_LDADD = \ libsystemd-shared.la test_bus_policy_SOURCES = \ - src/bus-proxyd/test-bus-xml-policy.c \ - src/bus-proxyd/bus-xml-policy.c \ - src/bus-proxyd/bus-xml-policy.h + src/bus-proxyd/test-bus-xml-policy.c test_bus_policy_LDADD = \ + libsystemd-proxy.la \ libsystemd-internal.la \ libsystemd-shared.la @@ -2679,8 +2679,10 @@ systemd_run_LDADD = \ libsystemd-shared.la # ------------------------------------------------------------------------------ -systemd_bus_proxyd_SOURCES = \ - src/bus-proxyd/bus-proxyd.c \ +noinst_LTLIBRARIES += \ + libsystemd-proxy.la + +libsystemd_proxy_la_SOURCES = \ src/bus-proxyd/bus-xml-policy.c \ src/bus-proxyd/bus-xml-policy.h \ src/bus-proxyd/driver.c \ @@ -2690,20 +2692,25 @@ systemd_bus_proxyd_SOURCES = \ src/bus-proxyd/synthesize.c \ src/bus-proxyd/synthesize.h -systemd_bus_proxyd_LDADD = \ +libsystemd_proxy_la_LIBADD = \ libsystemd-internal.la \ libsystemd-shared.la -bus-proxyd-install-hook: - $(AM_V_at)$(MKDIR_P) $(DESTDIR)$(bindir) - $(AM_V_RM)rm -f $(DESTDIR)$(bindir)/systemd-stdio-bridge - $(AM_V_LN)$(LN_S) --relative -f $(DESTDIR)$(rootlibexecdir)/systemd-bus-proxyd $(DESTDIR)$(bindir)/systemd-stdio-bridge +systemd_bus_proxyd_SOURCES = \ + src/bus-proxyd/bus-proxyd.c + +systemd_bus_proxyd_LDADD = \ + libsystemd-proxy.la \ + libsystemd-internal.la \ + libsystemd-shared.la -bus-proxyd-uninstall-hook: - rm -f $(DESTDIR)$(bindir)/systemd-stdio-bridge +systemd_stdio_bridge_SOURCES = \ + src/bus-proxyd/stdio-bridge.c -INSTALL_EXEC_HOOKS += bus-proxyd-install-hook -UNINSTALL_EXEC_HOOKS += bus-proxyd-uninstall-hook +systemd_stdio_bridge_LDADD = \ + libsystemd-proxy.la \ + libsystemd-internal.la \ + libsystemd-shared.la if ENABLE_KDBUS nodist_systemunit_DATA += \ diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c new file mode 100644 index 000000000..711f74cac --- /dev/null +++ b/src/bus-proxyd/stdio-bridge.c @@ -0,0 +1,282 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + 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 <sys/socket.h> +#include <sys/un.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/poll.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 "proxy.h" +#include "synthesize.h" + +static char *arg_address = NULL; +static char *arg_command_line_buffer = NULL; +static char **arg_configuration = 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" + " --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: + puts(PACKAGE_STRING); + puts(SYSTEMD_FEATURES); + return 0; + + case ARG_ADDRESS: { + char *a; + + a = strdup(optarg); + if (!a) + return log_oom(); + + free(arg_address); + arg_address = a; + 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(); + +#ifdef ENABLE_KDBUS + a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); +#else + a = strjoin("x-machine-unix:machine=", e, NULL); +#endif + 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_bus_creds_unref_ 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_UID|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_uid(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 = proxy_load_policy(p, arg_configuration); + if (r < 0) + goto finish; + + r = proxy_hello_policy(p, getuid()); + if (r < 0) + goto finish; + + r = rename_service(p->dest_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."); + + strv_free(arg_configuration); + free(arg_address); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} |