From f52da59548fac369e47cff73851c54a90cb0077c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 7 Dec 2017 12:57:31 +0100 Subject: [PATCH 1/7] logind: simplify one conditional Don't bother with removing the directory if we didn't create it. --- src/login/logind-user.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 94e250b94a..f17bc26f14 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -344,16 +344,13 @@ static int user_mkdir_runtime_path(User *u) { if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) { _cleanup_free_ char *t = NULL; - (void) mkdir_label(u->runtime_path, 0700); + r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s", + u->uid, u->gid, u->manager->runtime_dir_size, + mac_smack_use() ? ",smackfsroot=*" : ""); + if (r < 0) + return log_oom(); - if (mac_smack_use()) - r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size); - else - r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size); - if (r < 0) { - r = log_oom(); - goto fail; - } + (void) mkdir_label(u->runtime_path, 0700); r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t); if (r < 0) { From 8b5c4d167a82dc6458c447813dd39b4a4ef0fdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 7 Dec 2017 13:12:13 +0100 Subject: [PATCH 2/7] logind: fix misleading message This message would also be emitted at boot for any user with linger enabled, so "logged in" is the wrong term to use. --- src/login/logind-user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index f17bc26f14..00c2a22490 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -458,7 +458,7 @@ int user_start(User *u) { u->stopping = false; if (!u->started) { - log_debug("New user %s logged in.", u->name); + log_debug("Starting services for new user %s.", u->name); /* Make XDG_RUNTIME_DIR */ r = user_mkdir_runtime_path(u); From a789420775d7b01249c71f5e472ab325bc0657c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 7 Dec 2017 14:23:58 +0100 Subject: [PATCH 3/7] core: reuse slice_build_parent_slice --- src/core/slice.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/core/slice.c b/src/core/slice.c index 5ab1e6f898..fef47b04fe 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -59,30 +59,24 @@ static void slice_set_state(Slice *t, SliceState state) { } static int slice_add_parent_slice(Slice *s) { - char *a, *dash; - Unit *parent; + Unit *u = UNIT(s), *parent; + _cleanup_free_ char *a = NULL; int r; assert(s); - if (UNIT_ISSET(UNIT(s)->slice)) + if (UNIT_ISSET(u->slice)) return 0; - if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE)) - return 0; + r = slice_build_parent_slice(u->id, &a); + if (r <= 0) /* 0 means root slice */ + return r; - a = strdupa(UNIT(s)->id); - dash = strrchr(a, '-'); - if (dash) - strcpy(dash, ".slice"); - else - a = (char*) SPECIAL_ROOT_SLICE; - - r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent); + r = manager_load_unit(u->manager, a, NULL, NULL, &parent); if (r < 0) return r; - unit_ref_set(&UNIT(s)->slice, parent); + unit_ref_set(&u->slice, parent); return 0; } From e5af6e0e2d545c7fd29b9b8abd749bd3994b5bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 7 Dec 2017 14:28:00 +0100 Subject: [PATCH 4/7] tree-wide: use SPECIAL_ROOT_SLICE --- src/basic/unit-name.c | 9 +++++---- src/machine/machined.c | 3 ++- src/test/test-cgroup-util.c | 17 +++++++++-------- src/test/test-unit-name.c | 9 +++++---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index 403f288b57..0fa0472ee1 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -28,6 +28,7 @@ #include "glob-util.h" #include "hexdecoct.h" #include "path-util.h" +#include "special.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -673,7 +674,7 @@ int slice_build_parent_slice(const char *slice, char **ret) { if (!slice_name_is_valid(slice)) return -EINVAL; - if (streq(slice, "-.slice")) { + if (streq(slice, SPECIAL_ROOT_SLICE)) { *ret = NULL; return 0; } @@ -686,7 +687,7 @@ int slice_build_parent_slice(const char *slice, char **ret) { if (dash) strcpy(dash, ".slice"); else { - r = free_and_strdup(&s, "-.slice"); + r = free_and_strdup(&s, SPECIAL_ROOT_SLICE); if (r < 0) { free(s); return r; @@ -710,7 +711,7 @@ int slice_build_subslice(const char *slice, const char*name, char **ret) { if (!unit_prefix_is_valid(name)) return -EINVAL; - if (streq(slice, "-.slice")) + if (streq(slice, SPECIAL_ROOT_SLICE)) subslice = strappend(name, ".slice"); else { char *e; @@ -735,7 +736,7 @@ bool slice_name_is_valid(const char *name) { if (!unit_name_is_valid(name, UNIT_NAME_PLAIN)) return false; - if (streq(name, "-.slice")) + if (streq(name, SPECIAL_ROOT_SLICE)) return true; e = endswith(name, ".slice"); diff --git a/src/machine/machined.c b/src/machine/machined.c index d481020893..b5cb863e5d 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -37,6 +37,7 @@ #include "machined.h" #include "process-util.h" #include "signal-util.h" +#include "special.h" Manager *manager_new(void) { Manager *m; @@ -112,7 +113,7 @@ static int manager_add_host_machine(Manager *m) { if (!rd) return log_oom(); - unit = strdup("-.slice"); + unit = strdup(SPECIAL_ROOT_SLICE); if (!unit) return log_oom(); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 45eb3ef8b1..2248a30635 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -27,6 +27,7 @@ #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" +#include "special.h" #include "stat-util.h" #include "string-util.h" #include "test-helper.h" @@ -141,10 +142,10 @@ static void check_p_g_slice(const char *path, int code, const char *result) { static void test_path_get_slice(void) { check_p_g_slice("/user.slice", 0, "user.slice"); - check_p_g_slice("/foobar", 0, "-.slice"); + check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE); check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice"); - check_p_g_slice("", 0, "-.slice"); - check_p_g_slice("foobar", 0, "-.slice"); + check_p_g_slice("", 0, SPECIAL_ROOT_SLICE); + check_p_g_slice("foobar", 0, SPECIAL_ROOT_SLICE); check_p_g_slice("foobar.slice", 0, "foobar.slice"); check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice"); } @@ -165,10 +166,10 @@ static void test_path_get_user_slice(void) { check_p_g_u_slice("foobar.slice", -ENXIO, NULL); check_p_g_u_slice("foo.slice/foo-bar.slice/waldo.service", -ENXIO, NULL); - check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, "-.slice"); - check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, "-.slice"); - check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, "-.slice"); - check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, "-.slice"); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, SPECIAL_ROOT_SLICE); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice"); check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); } @@ -274,7 +275,7 @@ static void test_slice_to_path(void) { test_slice_to_path_one("foobar.slice", "foobar.slice", 0); test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0); test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL); - test_slice_to_path_one("-.slice", "", 0); + test_slice_to_path_one(SPECIAL_ROOT_SLICE, "", 0); test_slice_to_path_one("--.slice", NULL, -EINVAL); test_slice_to_path_one("-", NULL, -EINVAL); test_slice_to_path_one("-foo-.slice", NULL, -EINVAL); diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index e24892b590..416542c83f 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -32,6 +32,7 @@ #include "manager.h" #include "path-util.h" #include "rm-rf.h" +#include "special.h" #include "specifier.h" #include "string-util.h" #include "test-helper.h" @@ -338,7 +339,7 @@ static void test_unit_name_build(void) { } static void test_slice_name_is_valid(void) { - assert_se(slice_name_is_valid("-.slice")); + assert_se(slice_name_is_valid(SPECIAL_ROOT_SLICE)); assert_se(slice_name_is_valid("foo.slice")); assert_se(slice_name_is_valid("foo-bar.slice")); assert_se(slice_name_is_valid("foo-bar-baz.slice")); @@ -356,7 +357,7 @@ static void test_build_subslice(void) { char *a; char *b; - assert_se(slice_build_subslice("-.slice", "foo", &a) >= 0); + assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0); assert_se(slice_build_subslice(a, "bar", &b) >= 0); free(a); assert_se(slice_build_subslice(b, "barfoo", &a) >= 0); @@ -378,8 +379,8 @@ static void test_build_parent_slice_one(const char *name, const char *expect, in } static void test_build_parent_slice(void) { - test_build_parent_slice_one("-.slice", NULL, 0); - test_build_parent_slice_one("foo.slice", "-.slice", 1); + test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0); + test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1); test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1); test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1); test_build_parent_slice_one("foo-bar--baz.slice", NULL, -EINVAL); From 8426bfd397d5aba61c9b5ec79c12864ccf4cfd58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 7 Dec 2017 22:16:16 +0100 Subject: [PATCH 5/7] logind: use free_and_replace in one spot No functional change. --- src/login/logind-user.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 00c2a22490..32b2045696 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -527,9 +527,7 @@ static int user_stop_service(User *u) { return r; } - free(u->service_job); - u->service_job = job; - + free_and_replace(u->service_job, job); return r; } From e09fc88440f399766f7f4fbe8e56b68ba18a131d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 9 Dec 2017 10:18:48 +0100 Subject: [PATCH 6/7] mount: add option to specify uid= and gid= The kernel needs two numbers, but for the user it's most convenient to provide the user name and have that resolved to uid and gid. Right now the primary group of the specified user is always used. That's the most common case anyway. In the future we can extend the --owner option to allow a group after a colon. [I added this before realizing that this will not be enough to be used for user runtime directory. But this seems useful on its own, so I'm keeping this commit.] --- man/systemd-mount.xml | 8 ++++++ src/mount/mount-tool.c | 55 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index 87bc2b36eb..76ea0550d7 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -159,6 +159,14 @@ Additional mount options for the mount point. + + + + Let the specified user USER own the mounted file system. + This is done by appending and options to the list + of mount options. Only certain file systems support this option. + + diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index da3647e7e2..f82e9dac44 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -41,6 +41,7 @@ #include "strv.h" #include "udev-util.h" #include "unit-name.h" +#include "user-util.h" #include "terminal-util.h" enum { @@ -69,6 +70,8 @@ static usec_t arg_timeout_idle = USEC_INFINITY; static bool arg_timeout_idle_set = false; static char **arg_automount_property = NULL; static int arg_bind_device = -1; +static uid_t arg_uid = UID_INVALID; +static gid_t arg_gid = GID_INVALID; static bool arg_fsck = true; static bool arg_aggressive_gc = false; @@ -89,6 +92,7 @@ static void help(void) { " --discover Discover mount device metadata\n" " -t --type=TYPE File system type\n" " -o --options=OPTIONS Mount options\n" + " --owner=USER Add uid= and gid= options for USER\n" " --fsck=no Don't run file system check before mount\n" " --description=TEXT Description for unit\n" " -p --property=NAME=VALUE Set mount unit property\n" @@ -116,6 +120,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_DISCOVER, ARG_MOUNT_TYPE, ARG_MOUNT_OPTIONS, + ARG_OWNER, ARG_FSCK, ARG_DESCRIPTION, ARG_TIMEOUT_IDLE, @@ -139,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) { { "discover", no_argument, NULL, ARG_DISCOVER }, { "type", required_argument, NULL, 't' }, { "options", required_argument, NULL, 'o' }, + { "owner", required_argument, NULL, ARG_OWNER }, { "fsck", required_argument, NULL, ARG_FSCK }, { "description", required_argument, NULL, ARG_DESCRIPTION }, { "property", required_argument, NULL, 'p' }, @@ -220,6 +226,18 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); break; + case ARG_OWNER: { + const char *user = optarg; + + r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL); + if (r < 0) + return log_error_errno(r, + r == -EBADMSG ? "UID or GID of user %s are invalid." + : "Cannot use \"%s\" as owner: %m", + optarg); + break; + } + case ARG_FSCK: r = parse_boolean(optarg); if (r < 0) @@ -422,6 +440,7 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) { } static int transient_mount_set_properties(sd_bus_message *m) { + _cleanup_free_ char *options = NULL; int r; assert(m); @@ -442,11 +461,24 @@ static int transient_mount_set_properties(sd_bus_message *m) { return r; } - if (arg_mount_options) { - r = sd_bus_message_append(m, "(sv)", "Options", "s", arg_mount_options); + /* Prepend uid=…,gid=… if arg_uid is set */ + if (arg_uid != UID_INVALID) { + r = asprintf(&options, + "uid=" UID_FMT ",gid=" GID_FMT "%s%s", + arg_uid, arg_gid, + arg_mount_options ? "," : "", arg_mount_options); + if (r < 0) + return -ENOMEM; + } + + if (options || arg_mount_options) { + log_debug("Using mount options: %s", options ?: arg_mount_options); + + r = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options); if (r < 0) return r; - } + } else + log_debug("Not using any mount options"); if (arg_fsck) { _cleanup_free_ char *fsck = NULL; @@ -1604,6 +1636,23 @@ int main(int argc, char* argv[]) { } } + /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options, + * but not for all filesystem types. Let's try to catch the cases where the option + * would be used if the file system does not support it. It is also possible to + * autodetect the file system, but that's only possible with disk-based file systems + * which incidentally seem to be implemented more carefully and reject unknown options, + * so it's probably OK that we do the check only when the type is specified. + */ + if (arg_mount_type && + !streq(arg_mount_type, "auto") && + arg_uid != UID_INVALID && + !fstype_can_uid_gid(arg_mount_type)) { + log_error("File system type %s is not known to support uid=/gid=, refusing.", + arg_mount_type); + r = -EOPNOTSUPP; + goto finish; + } + switch (arg_action) { case ACTION_MOUNT: From fb883e759d3c35a9085b1ab25d6176c2979d29d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 9 Dec 2017 19:23:26 +0100 Subject: [PATCH 7/7] generator: add helper function for writing unit files It doesn't save too much, but it's a common pattern so I think it's worth to factor this out. --- src/cryptsetup/cryptsetup-generator.c | 25 +++++------- src/fstab-generator/fstab-generator.c | 54 +++++++------------------ src/shared/generator.c | 34 ++++++++++++++++ src/shared/generator.h | 6 +++ src/veritysetup/veritysetup-generator.c | 20 ++++----- 5 files changed, 73 insertions(+), 66 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 7e61332e52..531edc6847 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -61,7 +61,7 @@ static int create_disk( const char *password, const char *options) { - _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *e = NULL, + _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL, *filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL; _cleanup_fclose_ FILE *f = NULL; const char *dmname; @@ -90,18 +90,14 @@ static int create_disk( if (!e) return log_oom(); - r = unit_name_build("systemd-cryptsetup", e, ".service", &n); - if (r < 0) - return log_error_errno(r, "Failed to generate unit name: %m"); - - p = strjoin(arg_dest, "/", n); - if (!p) - return log_oom(); - u = fstab_node_to_udev_node(device); if (!u) return log_oom(); + r = unit_name_build("systemd-cryptsetup", e, ".service", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + u_escaped = specifier_escape(u); if (!u_escaped) return log_oom(); @@ -114,14 +110,11 @@ static int create_disk( if (!password_escaped) return log_oom(); - f = fopen(p, "wxe"); - if (!f) - return log_error_errno(errno, "Failed to create unit file %s: %m", p); - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = generator_open_unit_file(arg_dest, NULL, n, &f); + if (r < 0) + return r; fprintf(f, - "# Automatically generated by systemd-cryptsetup-generator\n\n" "[Unit]\n" "Description=Cryptography Setup for %%I\n" "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n" @@ -210,7 +203,7 @@ static int create_disk( r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write file %s: %m", p); + return log_error_errno(r, "Failed to write unit file %s: %m", n); if (!noauto) { r = generator_add_symlink(arg_dest, d, "wants", n); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 22c4ae9861..95bc5e38d5 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -102,7 +102,7 @@ static int add_swap( struct mntent *me, MountpointFlags flags) { - _cleanup_free_ char *name = NULL, *unit = NULL; + _cleanup_free_ char *name = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -123,19 +123,9 @@ static int add_swap( if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - unit = strjoin(arg_dest, "/", name); - if (!unit) - return log_oom(); - - f = fopen(unit, "wxe"); - if (!f) - return log_error_errno(errno, - errno == EEXIST ? - "Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?" : - "Failed to create unit file %s: %m", - unit); - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = generator_open_unit_file(arg_dest, "/etc/fstab", name, &f); + if (r < 0) + return r; fputs("# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" @@ -153,7 +143,7 @@ static int add_swap( r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write unit file %s: %m", unit); + return log_error_errno(r, "Failed to write unit file %s: %m", name); /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); @@ -323,10 +313,9 @@ static int add_mount( _cleanup_free_ char *name = NULL, - *automount_name = NULL, *automount_unit = NULL, + *automount_name = NULL, *filtered = NULL, *where_escaped = NULL; - const char *unit; _cleanup_fclose_ FILE *f = NULL; int r; @@ -363,20 +352,11 @@ static int add_mount( if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - unit = strjoina(dest, "/", name); - - f = fopen(unit, "wxe"); - if (!f) - return log_error_errno(errno, - errno == EEXIST ? - "Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?" : - "Failed to create unit file %s: %m", - unit); - - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = generator_open_unit_file(dest, "/etc/fstab", name, &f); + if (r < 0) + return r; fprintf(f, - "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", @@ -461,7 +441,7 @@ static int add_mount( r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write unit file %s: %m", unit); + return log_error_errno(r, "Failed to write unit file %s: %m", name); if (flags & MAKEFS) { r = generator_hook_up_mkfs(dest, what, where, fstype); @@ -487,19 +467,13 @@ static int add_mount( if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - automount_unit = strjoin(dest, "/", automount_name); - if (!automount_unit) - return log_oom(); - fclose(f); - f = fopen(automount_unit, "wxe"); - if (!f) - return log_error_errno(errno, "Failed to create unit file %s: %m", automount_unit); - (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + r = generator_open_unit_file(dest, "/etc/fstab", automount_name, &f); + if (r < 0) + return r; fprintf(f, - "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", @@ -534,7 +508,7 @@ static int add_mount( r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write unit file %s: %m", automount_unit); + return log_error_errno(r, "Failed to write unit file %s: %m", automount_name); r = generator_add_symlink(dest, post, (flags & NOFAIL) ? "wants" : "requires", automount_name); diff --git a/src/shared/generator.c b/src/shared/generator.c index 3495a7ef7d..2b0a4ecdc8 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -19,6 +19,7 @@ ***/ #include +#include #include #include "alloc-util.h" @@ -39,6 +40,39 @@ #include "unit-name.h" #include "util.h" +int generator_open_unit_file( + const char *dest, + const char *source, + const char *name, + FILE **file) { + + const char *unit; + FILE *f; + + unit = strjoina(dest, "/", name); + + f = fopen(unit, "wxe"); + if (!f) { + if (source && errno == EEXIST) + return log_error_errno(errno, + "Failed to create unit file %s, as it already exists. Duplicate entry in %s?", + unit, source); + else + return log_error_errno(errno, + "Failed to create unit file %s: %m", + unit); + } + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + fprintf(f, + "# Automatically generated by %s\n\n", + program_invocation_short_name); + + *file = f; + return 0; +} + int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src) { /* Adds a symlink from ..d/ to ../ */ diff --git a/src/shared/generator.h b/src/shared/generator.h index 32d1ad021c..e1c636a218 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -22,6 +22,12 @@ #include +int generator_open_unit_file( + const char *dest, + const char *source, + const char *name, + FILE **file); + int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src); int generator_write_fsck_deps( diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c index 5919b1380e..c29c6f0bb3 100644 --- a/src/veritysetup/veritysetup-generator.c +++ b/src/veritysetup/veritysetup-generator.c @@ -27,6 +27,7 @@ #include "fd-util.h" #include "fileio.h" #include "fstab-util.h" +#include "generator.h" #include "hexdecoct.h" #include "id128-util.h" #include "mkdir.h" @@ -36,6 +37,8 @@ #include "string-util.h" #include "unit-name.h" +#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service" + static char *arg_dest = NULL; static bool arg_enabled = true; static char *arg_root_hash = NULL; @@ -45,7 +48,7 @@ static char *arg_hash_what = NULL; static int create_device(void) { _cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL; _cleanup_fclose_ FILE *f = NULL; - const char *p, *to; + const char *to; int r; /* If all three pieces of information are missing, then verity is turned off */ @@ -67,8 +70,6 @@ static int create_device(void) { " hash device %s,\n" " and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash); - p = strjoina(arg_dest, "/systemd-veritysetup@root.service"); - u = fstab_node_to_udev_node(arg_data_what); if (!u) return log_oom(); @@ -94,12 +95,11 @@ static int create_device(void) { if (!root_hash_escaped) return log_oom(); - f = fopen(p, "wxe"); - if (!f) - return log_error_errno(errno, "Failed to create unit file %s: %m", p); + r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f); + if (r < 0) + return r; fprintf(f, - "# Automatically generated by systemd-veritysetup-generator\n\n" "[Unit]\n" "Description=Integrity Protection Setup for %%I\n" "Documentation=man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n" @@ -121,12 +121,12 @@ static int create_device(void) { r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write file %s: %m", p); + return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m"); - to = strjoina(arg_dest, "/cryptsetup.target.requires/systemd-veritysetup@root.service"); + to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE); (void) mkdir_parents(to, 0755); - if (symlink("../systemd-veritysetup@root.service", to) < 0) + if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); return 0;