Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
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));
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
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;
}