core/namespace: hide the correct credentials tree when running in user scope (#39651)

This commit is contained in:
Yu Watanabe
2025-11-10 11:01:16 +09:00
committed by GitHub
3 changed files with 31 additions and 6 deletions

View File

@@ -2811,13 +2811,21 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
return log_oom_debug();
*me = (MountEntry) {
.path_const = "/run/credentials",
.mode = MOUNT_TMPFS,
.read_only = true,
.options_const = "mode=0755" TMPFS_LIMITS_EMPTY_OR_ALMOST,
.flags = MS_NODEV|MS_STRICTATIME|MS_NOSUID|MS_NOEXEC,
};
if (p->runtime_scope == RUNTIME_SCOPE_SYSTEM)
me->path_const = "/run/credentials";
else {
r = path_extract_directory(p->creds_path, &me->path_malloc);
if (r < 0)
return log_debug_errno(r, "Failed to extract parent directory from '%s': %m",
p->creds_path);
}
me = mount_list_extend(&ml);
if (!me)
return log_oom_debug();
@@ -2829,9 +2837,11 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
.source_const = p->creds_path,
.ignore = true,
};
} else {
/* If our service has no credentials store configured, then make the whole credentials tree
* inaccessible wholesale. */
}
if (!p->creds_path || p->runtime_scope != RUNTIME_SCOPE_SYSTEM) {
/* If our service has no credentials store configured, or we're running in user scope, then
* make the system credentials tree inaccessible wholesale. */
MountEntry *me = mount_list_extend(&ml);
if (!me)

View File

@@ -2504,8 +2504,9 @@ static int start_transient_service(sd_bus *bus) {
/* Optionally, wait for the start job to complete. If we are supposed to read the service's stdin
* lets skip this however, because we should start that already when the start job is running, and
* there's little point in waiting for the start job to complete in that case anyway, as we'll wait
* for EOF anyway, which is going to be much later. */
if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) {
* for EOF anyway, which is going to be much later. Similar applies to --wait where we're going
* to wait for the service to terminate. */
if (!arg_no_block && !arg_wait && arg_stdio == ARG_STDIO_NONE) {
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_error_errno(r, "Could not watch jobs: %m");

View File

@@ -554,4 +554,18 @@ run0 -u testuser --pipe mkdir -p /home/testuser/.config/credstore.encrypted
run0 -u testuser --pipe systemd-creds encrypt --user --name=brummbaer - /home/testuser/.config/credstore.encrypted/brummbaer < /tmp/brummbaer.data
run0 -u testuser --pipe systemd-run --user --pipe -p ImportCredential=brummbaer systemd-creds cat brummbaer | cmp /tmp/brummbaer.data
# https://github.com/systemd/systemd/pull/39651
TESTUSER_CRED_DIR="/run/user/$(id -u testuser)/credentials"
PID="$(systemd-notify --fork -- systemd-run -M testuser@ --user --wait --unit=brummbaer.service -p LoadCredential=brummbaer sleep infinity)"
[[ -d "$TESTUSER_CRED_DIR/brummbaer.service" ]]
[[ -f "$TESTUSER_CRED_DIR/brummbaer.service/brummbaer" ]]
systemd-run -M testuser@ --user --wait -p PrivateMounts=yes -p ImportCredential=brummbaer \
bash -xec "[[ ! -d '$TESTUSER_CRED_DIR/brummbaer.service' ]] && [[ \$(stat -c %a /run/credentials) -eq 0 ]]"
systemd-run -M testuser@ --user --wait -p ImportCredential=brummbaer \
test -d "$TESTUSER_CRED_DIR/brummbaer.service"
kill "$PID"
touch /testok