summaryrefslogtreecommitdiffstats
path: root/src/run
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2024-03-26 13:19:33 +0100
committerGitHub <noreply@github.com>2024-03-26 13:19:33 +0100
commitc38e4e2fda402948ab213b53bbec059cc1a151ae (patch)
treeda7a15fc115b7edb3cc95743bcdc2b08ec5fa7d2 /src/run
parentbuild(deps): bump pkg/opensuse from `af49127` to `acdb1cd` (diff)
parentupdate TODO (diff)
downloadsystemd-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.c53
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);