From a6c57e74c527dcfc60edecec029146d961b4cdb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 13 Nov 2019 10:31:44 +0100 Subject: [PATCH 1/5] cryptsetup-generator: allow overriding crypttab path with $SYSTEMD_CRYPTAB --- docs/ENVIRONMENT.md | 3 +++ src/cryptsetup/cryptsetup-generator.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 83c2d25134..0d3f575e6d 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -41,6 +41,9 @@ All tools: debugging, in order to test generators and other code against specific kernel command lines. +* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only + useful for debugging. Currently only supported by systemd-cryptsetup-generator. + * `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`. diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 4815ded753..a4977ffa4d 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -37,6 +37,7 @@ typedef struct crypto_device { static const char *arg_dest = NULL; static bool arg_enabled = true; static bool arg_read_crypttab = true; +static const char *arg_crypttab = NULL; static bool arg_whitelist = false; static Hashmap *arg_disks = NULL; static char *arg_default_options = NULL; @@ -271,11 +272,12 @@ static int create_disk( "[Unit]\n" "Description=Cryptography Setup for %%I\n" "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n" - "SourcePath=/etc/crypttab\n" + "SourcePath=%s\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "IgnoreOnIsolate=true\n" "After=%s\n", + arg_crypttab, netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target"); if (password) { @@ -558,15 +560,15 @@ static int add_crypttab_devices(void) { if (!arg_read_crypttab) return 0; - r = fopen_unlocked("/etc/crypttab", "re", &f); + r = fopen_unlocked(arg_crypttab, "re", &f); if (r < 0) { if (errno != ENOENT) - log_error_errno(errno, "Failed to open /etc/crypttab: %m"); + log_error_errno(errno, "Failed to open %s: %m", arg_crypttab); return 0; } if (fstat(fileno(f), &st) < 0) { - log_error_errno(errno, "Failed to stat /etc/crypttab: %m"); + log_error_errno(errno, "Failed to stat %s: %m", arg_crypttab); return 0; } @@ -578,7 +580,7 @@ static int add_crypttab_devices(void) { r = read_line(f, LONG_LINE_MAX, &line); if (r < 0) - return log_error_errno(r, "Failed to read /etc/crypttab: %m"); + return log_error_errno(r, "Failed to read %s: %m", arg_crypttab); if (r == 0) break; @@ -590,7 +592,7 @@ static int add_crypttab_devices(void) { k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyspec, &options); if (k < 2 || k > 4) { - log_error("Failed to parse /etc/crypttab:%u, ignoring.", crypttab_line); + log_error("Failed to parse %s:%u, ignoring.", arg_crypttab, crypttab_line); continue; } @@ -667,6 +669,8 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) assert_se(arg_dest = dest); + arg_crypttab = getenv("SYSTEMD_CRYPTTAB") ?: "/etc/crypttab"; + arg_disks = hashmap_new(&crypt_device_hash_ops); if (!arg_disks) return log_oom(); From 3f5ac3038e53e15cea36d89261f97018af4dd163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 13 Nov 2019 12:06:58 +0100 Subject: [PATCH 2/5] cryptsetup-generator: allow overriding /run/systemd/cryptsetup with $RUNTIME_DIRECTORY I added a fairly vague entry to docs/ENVIRONMENT because I think it is worth mentioning there (in case someone is looking for any environment variable that might be relevant). --- docs/ENVIRONMENT.md | 4 ++++ src/cryptsetup/cryptsetup-generator.c | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 0d3f575e6d..5ad18c9e97 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -64,6 +64,10 @@ All tools: this only controls use of Unicode emoji glyphs, and has no effect on other Unicode glyphs. +* `$RUNTIME_DIRECTORY` — various tools use this variable to locate the + appropriate path under /run. This variable is also set by the manager when + RuntimeDirectory= is used, see systemd.exec(5). + systemctl: * `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index a4977ffa4d..4bfcba8f0f 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -38,6 +38,7 @@ static const char *arg_dest = NULL; static bool arg_enabled = true; static bool arg_read_crypttab = true; static const char *arg_crypttab = NULL; +static const char *arg_runtime_directory = NULL; static bool arg_whitelist = false; static Hashmap *arg_disks = NULL; static char *arg_default_options = NULL; @@ -90,11 +91,11 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha assert(unit); assert(mount); - r = mkdir_parents("/run/systemd/cryptsetup", 0755); + r = mkdir_parents(arg_runtime_directory, 0755); if (r < 0) return r; - r = mkdir("/run/systemd/cryptsetup", 0700); + r = mkdir(arg_runtime_directory, 0700); if (r < 0 && errno != EEXIST) return -errno; @@ -102,7 +103,7 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha if (!name_escaped) return -ENOMEM; - where = strjoin("/run/systemd/cryptsetup/keydev-", name_escaped); + where = strjoin(arg_runtime_directory, "/keydev-", name_escaped); if (!where) return -ENOMEM; @@ -670,6 +671,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) assert_se(arg_dest = dest); arg_crypttab = getenv("SYSTEMD_CRYPTTAB") ?: "/etc/crypttab"; + arg_runtime_directory = getenv("RUNTIME_DIRECTORY") ?: "/run/systemd/cryptsetup"; arg_disks = hashmap_new(&crypt_device_hash_ops); if (!arg_disks) From 32c6237a7c2e697d2fc4f3403319db16858fb8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 13 Nov 2019 10:32:30 +0100 Subject: [PATCH 3/5] cryptsetup-generator: guess whether the keyfile argument is two items or one Fixes #13615. See the inline comment for documentation. --- src/cryptsetup/cryptsetup-generator.c | 45 ++++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 4bfcba8f0f..811a9468c1 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -62,17 +62,36 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key c = strrchr(keyspec, ':'); if (c) { - keyfile = strndup(keyspec, c-keyspec); - keydev = strdup(c + 1); - if (!keyfile || !keydev) + /* The keydev part has to be either an absolute path to device node (/dev/something, + * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device + * specification starting with LABEL= or similar. The keyfile part has the same syntax. + * + * Let's try to guess if the second part looks like a keydev specification, or just part of a + * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to + * an absolute path. If we didn't get an absolute path, assume that it is just part of the + * first keyfile argument. */ + + keydev = fstab_node_to_udev_node(c + 1); + if (!keydev) return log_oom(); - } else { + + if (path_is_absolute(keydev)) + keyfile = strndup(keyspec, c-keyspec); + else { + log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n" + "Assuming that \"%s\" is a single device specification.", + c + 1, keyspec); + keydev = mfree(keydev); + c = NULL; + } + } + + if (!c) /* No keydev specified */ keyfile = strdup(keyspec); - keydev = NULL; - if (!keyfile) - return log_oom(); - } + + if (!keyfile) + return log_oom(); *ret_keyfile = TAKE_PTR(keyfile); *ret_keydev = TAKE_PTR(keydev); @@ -81,7 +100,7 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key } static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) { - _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; + _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; _cleanup_fclose_ FILE *f = NULL; int r; usec_t timeout_us; @@ -119,22 +138,18 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha if (r < 0) return r; - what = fstab_node_to_udev_node(keydev); - if (!what) - return -ENOMEM; - fprintf(f, "[Unit]\n" "DefaultDependencies=no\n\n" "[Mount]\n" "What=%s\n" "Where=%s\n" - "Options=ro%s\n", what, where, canfail ? ",nofail" : ""); + "Options=ro%s\n", keydev, where, canfail ? ",nofail" : ""); if (keydev_timeout) { r = parse_sec_fix_0(keydev_timeout, &timeout_us); if (r >= 0) { - r = unit_name_from_path(what, ".device", &device_unit); + r = unit_name_from_path(keydev, ".device", &device_unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); From ed4ad4889723a9acdf75ed86f10cee0024bbbcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 13 Nov 2019 17:36:46 +0100 Subject: [PATCH 4/5] Allow overriding /etc/fstab with $SYSTEMD_FSTAB --- docs/ENVIRONMENT.md | 3 +++ src/cryptsetup/cryptsetup.c | 3 ++- src/fstab-generator/fstab-generator.c | 28 ++++++++++++++------------- src/remount-fs/remount-fs.c | 5 +++-- src/shared/fstab-util.c | 4 ++-- src/shared/fstab-util.h | 4 ++++ 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 5ad18c9e97..4882cab600 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -41,6 +41,9 @@ All tools: debugging, in order to test generators and other code against specific kernel command lines. +* `$SYSTEMD_FSTAB` — if set, use this path instead of /etc/fstab. Only useful + for debugging. + * `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only useful for debugging. Currently only supported by systemd-cryptsetup-generator. diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index dd8c178fcb..dd1504dc9d 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -15,6 +15,7 @@ #include "device-util.h" #include "escape.h" #include "fileio.h" +#include "fstab-util.h" #include "log.h" #include "main-func.h" #include "mount-util.h" @@ -302,7 +303,7 @@ static char *disk_mount_point(const char *label) { if (asprintf(&device, "/dev/mapper/%s", label) < 0) return NULL; - f = setmntent("/etc/fstab", "re"); + f = setmntent(fstab_path(), "re"); if (!f) return NULL; diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index abe4413f92..6fd6fbdf1c 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -112,14 +112,16 @@ static int add_swap( if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - r = generator_open_unit_file(arg_dest, "/etc/fstab", name, &f); + r = generator_open_unit_file(arg_dest, fstab_path(), name, &f); if (r < 0) return r; - fputs("[Unit]\n" - "SourcePath=/etc/fstab\n" - "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" - "[Swap]\n", f); + fprintf(f, + "[Unit]\n" + "SourcePath=%s\n" + "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" + "[Swap]\n", + fstab_path()); r = write_what(f, what); if (r < 0) @@ -340,7 +342,7 @@ static int add_mount( if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - r = generator_open_unit_file(dest, "/etc/fstab", name, &f); + r = generator_open_unit_file(dest, fstab_path(), name, &f); if (r < 0) return r; @@ -463,7 +465,7 @@ static int add_mount( f = safe_fclose(f); - r = generator_open_unit_file(dest, "/etc/fstab", automount_name, &f); + r = generator_open_unit_file(dest, fstab_path(), automount_name, &f); if (r < 0) return r; @@ -515,19 +517,19 @@ static int add_mount( static int parse_fstab(bool initrd) { _cleanup_endmntent_ FILE *f = NULL; - const char *fstab_path; + const char *fstab; struct mntent *me; int r = 0; - fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab"; - log_debug("Parsing %s...", fstab_path); + fstab = initrd ? "/sysroot/etc/fstab" : fstab_path(); + log_debug("Parsing %s...", fstab); - f = setmntent(fstab_path, "re"); + f = setmntent(fstab, "re"); if (!f) { if (errno == ENOENT) return 0; - return log_error_errno(errno, "Failed to open %s: %m", fstab_path); + return log_error_errno(errno, "Failed to open %s: %m", fstab); } while ((me = getmntent(f))) { @@ -606,7 +608,7 @@ static int parse_fstab(bool initrd) { me->mnt_passno, makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT, post, - fstab_path); + fstab); } if (r >= 0 && k < 0) diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index 5891013427..7386f70529 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -9,6 +9,7 @@ #include "env-util.h" #include "exit-status.h" +#include "fstab-util.h" #include "log.h" #include "main-func.h" #include "mount-setup.h" @@ -86,10 +87,10 @@ static int run(int argc, char *argv[]) { umask(0022); - f = setmntent("/etc/fstab", "re"); + f = setmntent(fstab_path(), "re"); if (!f) { if (errno != ENOENT) - return log_error_errno(errno, "Failed to open /etc/fstab: %m"); + return log_error_errno(errno, "Failed to open %s: %m", fstab_path()); } else while ((me = getmntent(f))) { /* Remount the root fs, /usr, and all API VFSs */ diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index 75e4784c38..f90501eb92 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -19,7 +19,7 @@ int fstab_has_fstype(const char *fstype) { _cleanup_endmntent_ FILE *f = NULL; struct mntent *m; - f = setmntent("/etc/fstab", "re"); + f = setmntent(fstab_path(), "re"); if (!f) return errno == ENOENT ? false : -errno; @@ -39,7 +39,7 @@ int fstab_is_mount_point(const char *mount) { _cleanup_endmntent_ FILE *f = NULL; struct mntent *m; - f = setmntent("/etc/fstab", "re"); + f = setmntent(fstab_path(), "re"); if (!f) return errno == ENOENT ? false : -errno; diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index 0862256511..f575ed0bb2 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -31,3 +31,7 @@ static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no } char *fstab_node_to_udev_node(const char *p); + +static inline const char* fstab_path(void) { + return secure_getenv("SYSTEMD_FSTAB") ?: "/etc/fstab"; +} From 1f6597a84cd3891a69a630c6c4b168da46b1c160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 13 Nov 2019 21:55:30 +0100 Subject: [PATCH 5/5] man: mention $RUNTIME_DIRECTORY & friends in environment list --- man/systemd.exec.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 8701005e6b..0d3645f19f 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -2436,6 +2436,20 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy information. + + $RUNTIME_DIRECTORY + $STATE_DIRECTORY + $CACHE_DIRECTORY + $LOGS_DIRECTORY + $CONFIGURATION_DIRECTORY + + Contains and absolute paths to the directories defined with + RuntimeDirectory=, StateDirectory=, + CacheDirectory=, LogsDirectory=, and + ConfigurationDirectory= when those settings are used. + + + $MAINPID