diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2024-03-26 13:19:33 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-26 13:19:33 +0100 |
commit | c38e4e2fda402948ab213b53bbec059cc1a151ae (patch) | |
tree | da7a15fc115b7edb3cc95743bcdc2b08ec5fa7d2 /src/run | |
parent | build(deps): bump pkg/opensuse from `af49127` to `acdb1cd` (diff) | |
parent | update TODO (diff) | |
download | systemd-c38e4e2fda402948ab213b53bbec059cc1a151ae.tar.xz systemd-c38e4e2fda402948ab213b53bbec059cc1a151ae.zip |
Merge pull request #29721 from poettering/systemd-project
New capsule@.service feature
Diffstat (limited to 'src/run')
-rw-r--r-- | src/run/run.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/src/run/run.c b/src/run/run.c index 93e061a3c3..7f40ed0076 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -17,11 +17,14 @@ #include "bus-unit-util.h" #include "bus-wait-for-jobs.h" #include "calendarspec.h" +#include "capsule-util.h" +#include "chase.h" #include "env-util.h" #include "escape.h" #include "exit-status.h" #include "fd-util.h" #include "format-util.h" +#include "fs-util.h" #include "hostname-util.h" #include "main-func.h" #include "parse-argument.h" @@ -35,6 +38,7 @@ #include "special.h" #include "strv.h" #include "terminal-util.h" +#include "uid-classification.h" #include "unit-def.h" #include "unit-name.h" #include "user-util.h" @@ -265,6 +269,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, + { "capsule", required_argument, NULL, 'C' }, { "scope", no_argument, NULL, ARG_SCOPE }, { "unit", required_argument, NULL, 'u' }, { "description", required_argument, NULL, ARG_DESCRIPTION }, @@ -317,7 +322,7 @@ static int parse_argv(int argc, char *argv[]) { /* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long() * that checks for GNU extensions in optstring ('-' or '+' at the beginning). */ optind = 0; - while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hrC:H:M:E:p:tPqGdSu:", options, NULL)) >= 0) switch (c) { @@ -339,6 +344,18 @@ static int parse_argv(int argc, char *argv[]) { arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; break; + case 'C': + r = capsule_name_is_valid(optarg); + if (r < 0) + return log_error_errno(r, "Unable to validate capsule name '%s': %m", optarg); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid capsule name: %s", optarg); + + arg_host = optarg; + arg_transport = BUS_TRANSPORT_CAPSULE; + arg_runtime_scope = RUNTIME_SCOPE_USER; + break; + case ARG_SCOPE: arg_scope = true; break; @@ -1598,6 +1615,28 @@ static void set_window_title(PTYForward *f) { (void) pty_forward_set_title_prefix(f, dot); } +static int chown_to_capsule(const char *path, const char *capsule) { + _cleanup_free_ char *p = NULL; + int r; + + assert(path); + assert(capsule); + + p = path_join("/run/capsules/", capsule); + if (!p) + return -ENOMEM; + + struct stat st; + r = chase_and_stat(p, /* root= */ NULL, CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS, /* ret_path= */ NULL, &st); + if (r < 0) + return r; + + if (uid_is_system(st.st_uid) || gid_is_system(st.st_gid)) /* paranoid safety check */ + return -EPERM; + + return chmod_and_chown(path, 0600, st.st_uid, st.st_gid); +} + static int start_transient_service(sd_bus *bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -1610,7 +1649,7 @@ static int start_transient_service(sd_bus *bus) { if (arg_stdio == ARG_STDIO_PTY) { - if (arg_transport == BUS_TRANSPORT_LOCAL) { + if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_CAPSULE)) { master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (master < 0) return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); @@ -1619,6 +1658,14 @@ static int start_transient_service(sd_bus *bus) { if (r < 0) return log_error_errno(r, "Failed to determine tty name: %m"); + if (arg_transport == BUS_TRANSPORT_CAPSULE) { + /* If we are in capsule mode, we must give the capsule UID/GID access to the PTY we just allocated first. */ + + r = chown_to_capsule(pty_path, arg_host); + if (r < 0) + return log_error_errno(r, "Failed to chown tty to capsule UID/GID: %m"); + } + if (unlockpt(master) < 0) return log_error_errno(errno, "Failed to unlock tty: %m"); @@ -2306,7 +2353,7 @@ static int run(int argc, char* argv[]) { * limited direct connection */ if (arg_wait || arg_stdio != ARG_STDIO_NONE || - (arg_runtime_scope == RUNTIME_SCOPE_USER && arg_transport != BUS_TRANSPORT_LOCAL)) + (arg_runtime_scope == RUNTIME_SCOPE_USER && !IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_CAPSULE))) r = bus_connect_transport(arg_transport, arg_host, arg_runtime_scope, &bus); else r = bus_connect_transport_systemd(arg_transport, arg_host, arg_runtime_scope, &bus); |