run: allow connecting to capsule instances with --capsule=/-C

This commit is contained in:
Lennart Poettering
2023-10-26 09:19:04 +02:00
parent 56cb74c3cd
commit 759b3c082d

View File

@@ -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;
@@ -1603,6 +1620,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;
@@ -1615,7 +1654,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");
@@ -1624,6 +1663,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");
@@ -2311,7 +2358,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);