namespace: Clone root dir descriptor before use
Before doing anything with the root directory file descriptor, let's make sure we clone it first so that the caller can't mess with mount fd attributes via mount_setattr() anymore. We clone during parsing instead of in executor so that the caller can't mess with the mount fd between invocations.
This commit is contained in:
+30
-7
@@ -502,16 +502,13 @@ static int bus_set_transient_exec_context_fd(
|
||||
assert(name);
|
||||
assert(p);
|
||||
assert(b);
|
||||
assert(verify_mode == O_DIRECTORY || (verify_mode & ~O_ACCMODE_STRICT) == 0);
|
||||
assert((verify_mode & ~O_ACCMODE_STRICT) == 0);
|
||||
|
||||
r = sd_bus_message_read(message, "h", &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (verify_mode == O_DIRECTORY)
|
||||
r = fd_verify_directory(fd);
|
||||
else
|
||||
r = fd_vet_accmode(fd, verify_mode);
|
||||
r = fd_vet_accmode(fd, verify_mode);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(reterr_error, r, "%s passed is of incompatible type: %m", name);
|
||||
|
||||
@@ -813,8 +810,34 @@ static int bus_service_set_transient_property(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(name, "RootDirectoryFileDescriptor"))
|
||||
return bus_set_transient_exec_context_fd(u, name, &s->root_directory_fd, &s->exec_context.root_directory_as_fd, O_DIRECTORY, message, flags, reterr_error);
|
||||
if (streq(name, "RootDirectoryFileDescriptor")) {
|
||||
int fd;
|
||||
|
||||
r = sd_bus_message_read(message, "h", &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fd_verify_directory(fd);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(reterr_error, r, "RootDirectoryFileDescriptor= is not a directory: %m");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
int fd_clone;
|
||||
|
||||
/* Note that this invalidates the fd we got from the client. They won't be able to
|
||||
* move_mount() it themselves. If they already move_mount()'ed it themselves, this
|
||||
* will fail to clone the fd. */
|
||||
fd_clone = mount_fd_clone(fd, /* recursive= */ true, /* replacement_fd= */ NULL);
|
||||
if (fd_clone < 0)
|
||||
return fd_clone;
|
||||
|
||||
/* We're closing our own clone here, which shouldn't need an asynchronous_close(). */
|
||||
close_and_replace(s->root_directory_fd, fd_clone);
|
||||
s->exec_context.root_directory_as_fd = true;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2877,6 +2877,7 @@ void exec_params_shallow_clear(ExecParameters *p) {
|
||||
p->fd_names = strv_free(p->fd_names);
|
||||
p->files_env = strv_free(p->files_env);
|
||||
p->fds = mfree(p->fds);
|
||||
p->root_directory_fd = safe_close(p->root_directory_fd);
|
||||
p->exec_fd = safe_close(p->exec_fd);
|
||||
p->user_lookup_fd = -EBADF;
|
||||
p->bpf_restrict_fs_map_fd = -EBADF;
|
||||
|
||||
+8
-1
@@ -1951,7 +1951,14 @@ static int service_spawn_internal(
|
||||
exec_params.stdin_fd = s->stdin_fd;
|
||||
exec_params.stdout_fd = s->stdout_fd;
|
||||
exec_params.stderr_fd = s->stderr_fd;
|
||||
exec_params.root_directory_fd = s->root_directory_fd;
|
||||
|
||||
if (s->root_directory_fd >= 0) {
|
||||
r = mount_fd_clone(s->root_directory_fd, /* recursive= */ true, &s->root_directory_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
exec_params.root_directory_fd = r;
|
||||
}
|
||||
|
||||
r = exec_spawn(UNIT(s),
|
||||
c,
|
||||
|
||||
Reference in New Issue
Block a user