diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-06-25 10:06:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-25 10:06:03 +0200 |
commit | c7e42ceb7a99538535ac9f3673b078768a51becf (patch) | |
tree | 9cad7beb045bcbd0e1a5899a956bb5883be09ee2 | |
parent | fab347489fcfafbc8367c86afc637ce1b81ae59e (diff) | |
parent | 5c6d40d13238e56699074fc1b01f4ac929ba62b8 (diff) | |
download | systemd-c7e42ceb7a99538535ac9f3673b078768a51becf.tar.gz |
Merge pull request #12869 from poettering/dynamic-user-re-migrate
DynamicUser=1 state directory back migration
-rw-r--r-- | src/core/execute.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/src/core/execute.c b/src/core/execute.c index 426e57b8e0..acce8326fe 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2099,27 +2099,30 @@ static int setup_exec_directory( (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode != EXEC_PRESERVE_NO))) { _cleanup_free_ char *private_root = NULL; - /* So, here's one extra complication when dealing with DynamicUser=1 units. In that case we - * want to avoid leaving a directory around fully accessible that is owned by a dynamic user - * whose UID is later on reused. To lock this down we use the same trick used by container - * managers to prohibit host users to get access to files of the same UID in containers: we - * place everything inside a directory that has an access mode of 0700 and is owned root:root, - * so that it acts as security boundary for unprivileged host code. We then use fs namespacing - * to make this directory permeable for the service itself. + /* So, here's one extra complication when dealing with DynamicUser=1 units. In that + * case we want to avoid leaving a directory around fully accessible that is owned by + * a dynamic user whose UID is later on reused. To lock this down we use the same + * trick used by container managers to prohibit host users to get access to files of + * the same UID in containers: we place everything inside a directory that has an + * access mode of 0700 and is owned root:root, so that it acts as security boundary + * for unprivileged host code. We then use fs namespacing to make this directory + * permeable for the service itself. * - * Specifically: for a service which wants a special directory "foo/" we first create a - * directory "private/" with access mode 0700 owned by root:root. Then we place "foo" inside of - * that directory (i.e. "private/foo/"), and make "foo" a symlink to "private/foo". This way, - * privileged host users can access "foo/" as usual, but unprivileged host users can't look - * into it. Inside of the namespaceof the container "private/" is replaced by a more liberally - * accessible tmpfs, into which the host's "private/foo/" is mounted under the same name, thus - * disabling the access boundary for the service and making sure it only gets access to the - * dirs it needs but no others. Tricky? Yes, absolutely, but it works! + * Specifically: for a service which wants a special directory "foo/" we first create + * a directory "private/" with access mode 0700 owned by root:root. Then we place + * "foo" inside of that directory (i.e. "private/foo/"), and make "foo" a symlink to + * "private/foo". This way, privileged host users can access "foo/" as usual, but + * unprivileged host users can't look into it. Inside of the namespace of the unit + * "private/" is replaced by a more liberally accessible tmpfs, into which the host's + * "private/foo/" is mounted under the same name, thus disabling the access boundary + * for the service and making sure it only gets access to the dirs it needs but no + * others. Tricky? Yes, absolutely, but it works! * - * Note that we don't do this for EXEC_DIRECTORY_CONFIGURATION as that's assumed not to be - * owned by the service itself. - * Also, note that we don't do this for EXEC_DIRECTORY_RUNTIME as that's often used for sharing - * files or sockets with other services. */ + * Note that we don't do this for EXEC_DIRECTORY_CONFIGURATION as that's assumed not + * to be owned by the service itself. + * + * Also, note that we don't do this for EXEC_DIRECTORY_RUNTIME as that's often used + * for sharing files or sockets with other services. */ private_root = path_join(params->prefix[type], "private"); if (!private_root) { @@ -2168,6 +2171,38 @@ static int setup_exec_directory( goto fail; } else { + _cleanup_free_ char *target = NULL; + + if (type != EXEC_DIRECTORY_CONFIGURATION && + readlink_and_make_absolute(p, &target) >= 0) { + _cleanup_free_ char *q = NULL; + + /* This already exists and is a symlink? Interesting. Maybe it's one created + * by DynamicUser=1 (see above)? */ + + q = path_join(params->prefix[type], "private", *rt); + if (!q) { + r = -ENOMEM; + goto fail; + } + + if (path_equal(q, target)) { + + /* Hmm, apparently DynamicUser= was once turned on for this service, + * but is no longer. Let's move the directory back up. */ + + if (unlink(p) < 0) { + r = -errno; + goto fail; + } + + if (rename(q, p) < 0) { + r = -errno; + goto fail; + } + } + } + r = mkdir_label(p, context->directories[type].mode); if (r < 0) { if (r != -EEXIST) |