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:
Daan De Meyer
2025-10-31 13:09:51 +01:00
parent 456ee3c5f9
commit 9e26ced980
15 changed files with 162 additions and 10 deletions
+7 -3
View File
@@ -267,6 +267,9 @@ bool exec_needs_mount_namespace(
if (context->root_image)
return true;
if (context->root_directory_as_fd)
return true;
if (!strv_isempty(context->read_write_paths) ||
!strv_isempty(context->read_only_paths) ||
!strv_isempty(context->inaccessible_paths) ||
@@ -354,7 +357,7 @@ const char* exec_get_private_notify_socket_path(const ExecContext *context, cons
if (!needs_sandboxing)
return NULL;
if (!context->root_directory && !context->root_image)
if (!context->root_directory && !context->root_image && !context->root_directory_as_fd)
return NULL;
if (!exec_context_get_effective_mount_apivfs(context))
@@ -2045,9 +2048,9 @@ bool exec_context_restrict_filesystems_set(const ExecContext *c) {
bool exec_context_with_rootfs(const ExecContext *c) {
assert(c);
/* Checks if RootDirectory= or RootImage= are used */
/* Checks if RootDirectory=, RootImage= or RootDirectoryFileDescriptor= are used */
return !empty_or_root(c->root_directory) || c->root_image;
return !empty_or_root(c->root_directory) || c->root_image || c->root_directory_as_fd;
}
int exec_context_has_vpicked_extensions(const ExecContext *context) {
@@ -2846,6 +2849,7 @@ void exec_params_deep_clear(ExecParameters *p) {
p->stdin_fd = safe_close(p->stdin_fd);
p->stdout_fd = safe_close(p->stdout_fd);
p->stderr_fd = safe_close(p->stderr_fd);
p->root_directory_fd = safe_close(p->root_directory_fd);
p->notify_socket = mfree(p->notify_socket);