core: Add RootDirectoryFileDescriptor=
RootDirectory= but via a open_tree() file descriptor. This allows setting up the execution environment for a service by the client in a mount namespace and then starting a transient unit in that execution environment using the new property. We also add --root-directory= and --same-root-dir= to systemd-run to have it run services within the given root directory. As systemd-run might be invoked from a different mount namespace than what systemd is running in, systemd-run opens the given path with open_tree() and then sends it to systemd using the new RootDirectoryFileDescriptor= property.
This commit is contained in:
+39
-1
@@ -4,6 +4,7 @@
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@@ -106,6 +107,7 @@ static bool arg_quiet = false;
|
||||
static bool arg_verbose = false;
|
||||
static bool arg_aggressive_gc = false;
|
||||
static char *arg_working_directory = NULL;
|
||||
static char *arg_root_directory = NULL;
|
||||
static bool arg_shell = false;
|
||||
static JobMode arg_job_mode = JOB_FAIL;
|
||||
static char **arg_cmdline = NULL;
|
||||
@@ -168,6 +170,8 @@ static int help(void) {
|
||||
" --nice=NICE Nice level\n"
|
||||
" --working-directory=PATH Set working directory\n"
|
||||
" -d --same-dir Inherit working directory from caller\n"
|
||||
" --root-directory=PATH Set root directory\n"
|
||||
" -R --same-root-dir Inherit root directory from caller\n"
|
||||
" -E --setenv=NAME[=VALUE] Set environment variable\n"
|
||||
" -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n"
|
||||
" STDERR\n"
|
||||
@@ -326,6 +330,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_NO_ASK_PASSWORD,
|
||||
ARG_WAIT,
|
||||
ARG_WORKING_DIRECTORY,
|
||||
ARG_ROOT_DIRECTORY,
|
||||
ARG_SHELL,
|
||||
ARG_JOB_MODE,
|
||||
ARG_IGNORE_FAILURE,
|
||||
@@ -379,6 +384,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "collect", no_argument, NULL, 'G' },
|
||||
{ "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY },
|
||||
{ "same-dir", no_argument, NULL, 'd' },
|
||||
{ "root-directory", required_argument, NULL, ARG_ROOT_DIRECTORY },
|
||||
{ "same-root-dir", no_argument, NULL, 'R' },
|
||||
{ "shell", no_argument, NULL, 'S' },
|
||||
{ "job-mode", required_argument, NULL, ARG_JOB_MODE },
|
||||
{ "ignore-failure", no_argument, NULL, ARG_IGNORE_FAILURE },
|
||||
@@ -388,7 +395,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{},
|
||||
};
|
||||
|
||||
bool with_trigger = false;
|
||||
bool with_trigger = false, same_dir = false;
|
||||
int r, c;
|
||||
|
||||
assert(argc >= 0);
|
||||
@@ -653,6 +660,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
same_dir = false;
|
||||
break;
|
||||
|
||||
case 'd': {
|
||||
@@ -666,9 +674,25 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_working_directory = mfree(arg_working_directory);
|
||||
else
|
||||
free_and_replace(arg_working_directory, p);
|
||||
|
||||
same_dir = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_ROOT_DIRECTORY:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root_directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
r = free_and_strdup_warn(&arg_root_directory, "/");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
arg_aggressive_gc = true;
|
||||
break;
|
||||
@@ -842,6 +866,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
"--wait may not be combined with --scope.");
|
||||
}
|
||||
|
||||
if (same_dir && arg_root_directory && !path_equal(arg_root_directory, "/"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"--same-dir cannot be used with a root directory other than '/'");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1406,6 +1434,16 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
if (arg_root_directory) {
|
||||
_cleanup_close_ int fd = open_tree(AT_FDCWD, arg_root_directory, OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC|AT_RECURSIVE);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to clone mount tree at '%s': %m", arg_root_directory);
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "RootDirectoryFileDescriptor", "h", fd);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
if (pty_path) {
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
|
||||
"TTYPath", "s", pty_path,
|
||||
|
||||
Reference in New Issue
Block a user