static int write_what(FILE *f, const char *what) { _cleanup_free_ char *w = NULL; w = specifier_escape(what); if (!w) return log_oom(); fprintf(f, "What=%s\n", w); return 1; }
static int write_fsck_sysroot_service(const char *dir, const char *what) { _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit; int r; escaped = specifier_escape(what); if (!escaped) return log_oom(); escaped2 = cescape(escaped); if (!escaped2) return log_oom(); unit = strjoina(dir, "/systemd-fsck-root.service"); log_debug("Creating %s", unit); r = unit_name_from_path(what, ".device", &device); if (r < 0) return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what); f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by %1$s\n\n" "[Unit]\n" "Description=File System Check on %2$s\n" "Documentation=man:systemd-fsck-root.service(8)\n" "DefaultDependencies=no\n" "BindsTo=%3$s\n" "After=initrd-root-device.target local-fs-pre.target %3$s\n" "Before=shutdown.target\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" "TimeoutSec=0\n", program_invocation_short_name, escaped, device, escaped2); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); return 0; }
static int write_options(FILE *f, const char *options) { _cleanup_free_ char *o = NULL; if (isempty(options)) return 0; if (streq(options, "defaults")) return 0; o = specifier_escape(options); if (!o) return log_oom(); fprintf(f, "Options=%s\n", o); return 1; }
static void test_specifier_escape_one(const char *a, const char *b) { _cleanup_free_ char *x = NULL; x = specifier_escape(a); assert_se(streq_ptr(x, b)); }
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 *to; int r; /* If all three pieces of information are missing, then verity is turned off */ if (!arg_root_hash && !arg_data_what && !arg_hash_what) return 0; /* if one of them is missing however, the data is simply incomplete and this is an error */ if (!arg_root_hash) log_error("Verity information incomplete, root hash unspecified."); if (!arg_data_what) log_error("Verity information incomplete, root data device unspecified."); if (!arg_hash_what) log_error("Verity information incomplete, root hash device unspecified."); if (!arg_root_hash || !arg_data_what || !arg_hash_what) return -EINVAL; log_debug("Using root verity data device %s,\n" " hash device %s,\n" " and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash); u = fstab_node_to_udev_node(arg_data_what); if (!u) return log_oom(); v = fstab_node_to_udev_node(arg_hash_what); if (!v) return log_oom(); u_escaped = specifier_escape(u); if (!u_escaped) return log_oom(); v_escaped = specifier_escape(v); if (!v_escaped) return log_oom(); r = unit_name_from_path(u, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); r = unit_name_from_path(v, ".device", &e); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); root_hash_escaped = specifier_escape(arg_root_hash); if (!root_hash_escaped) return log_oom(); r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f); if (r < 0) return r; fprintf(f, "[Unit]\n" "Description=Integrity Protection Setup for %%I\n" "Documentation=man:systemd-veritysetup-generator(8) man:[email protected](8)\n" "SourcePath=/proc/cmdline\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=%s %s\n" "IgnoreOnIsolate=true\n" "After=cryptsetup-pre.target %s %s\n" "Before=cryptsetup.target umount.target\n" "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s'\n" "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n", d, e, d, e, u_escaped, v_escaped, root_hash_escaped); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m"); to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE); (void) mkdir_parents(to, 0755); if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); return 0; }
static int create_disk( const char *name, const char *device, const char *password, const char *options) { _cleanup_free_ char *p = NULL, *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; bool noauto, nofail, tmp, swap, netdev; int r; assert(name); assert(device); noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0"); tmp = fstab_test_option(options, "tmp\0"); swap = fstab_test_option(options, "swap\0"); netdev = fstab_test_option(options, "_netdev\0"); if (tmp && swap) { log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name); return -EINVAL; } name_escaped = specifier_escape(name); if (!name_escaped) return log_oom(); e = unit_name_escape(name); 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(); u_escaped = specifier_escape(u); if (!u_escaped) return log_oom(); r = unit_name_from_path(u, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); password_escaped = specifier_escape(password); 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); 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:[email protected](8)\n" "SourcePath=/etc/crypttab\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "IgnoreOnIsolate=true\n" "After=%s\n", netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target"); if (!nofail) fprintf(f, "Before=%s\n", netdev ? "remote-cryptsetup.target" : "cryptsetup.target"); if (password) { if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random")) fputs_unlocked("After=systemd-random-seed.service\n", f); else if (!STR_IN_SET(password, "-", "none")) { _cleanup_free_ char *uu; uu = fstab_node_to_udev_node(password); if (!uu) return log_oom(); if (!path_equal(uu, "/dev/null")) { if (path_startswith(uu, "/dev/")) { _cleanup_free_ char *dd = NULL; r = unit_name_from_path(uu, ".device", &dd); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); fprintf(f, "After=%1$s\nRequires=%1$s\n", dd); } else fprintf(f, "RequiresMountsFor=%s\n", password_escaped); } } } if (path_startswith(u, "/dev/")) { fprintf(f, "BindsTo=%s\n" "After=%s\n" "Before=umount.target\n", d, d); if (swap) fputs_unlocked("Before=dev-mapper-%i.swap\n", f); } else fprintf(f, "RequiresMountsFor=%s\n", u_escaped); r = generator_write_timeouts(arg_dest, device, name, options, &filtered); if (r < 0) return r; filtered_escaped = specifier_escape(filtered); if (!filtered_escaped) return log_oom(); fprintf(f, "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "TimeoutSec=0\n" /* the binary handles timeouts anyway */ "KeyringMode=shared\n" /* make sure we can share cached keys among instances */ "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n" "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped), name_escaped); if (tmp) fprintf(f, "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", name_escaped); if (swap) fprintf(f, "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", name_escaped); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", p); if (!noauto) { r = generator_add_symlink(arg_dest, d, "wants", n); if (r < 0) return r; r = generator_add_symlink(arg_dest, netdev ? "remote-cryptsetup.target" : "cryptsetup.target", nofail ? "wants" : "requires", n); if (r < 0) return r; } dmname = strjoina("dev-mapper-", e, ".device"); r = generator_add_symlink(arg_dest, dmname, "requires", n); if (r < 0) return r; if (!noauto && !nofail) { r = write_drop_in(arg_dest, dmname, 90, "device-timeout", "# Automatically generated by systemd-cryptsetup-generator \n\n" "[Unit]\nJobTimeoutSec=0"); if (r < 0) return log_error_errno(r, "Failed to write device drop-in: %m"); } return 0; }