summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2021-11-22 14:09:38 +0100
committerGitHub <noreply@github.com>2021-11-22 14:09:38 +0100
commitd837adb0a8bf38902b2fcbe7149a22e4ebd3f318 (patch)
treeabb35298f0699c20c320f89f7fbbf36f2eb3f54b /src
parentFIDO2 device removal instructions (#21426) (diff)
parentDocument usr-specific verity parameters (diff)
downloadsystemd-d837adb0a8bf38902b2fcbe7149a22e4ebd3f318.tar.xz
systemd-d837adb0a8bf38902b2fcbe7149a22e4ebd3f318.zip
Merge pull request #21357 from mbd98/usr-verity-auto
veritysetup-generator, fstab-generator: Setup and mount usr verity device when 'usrhash' (and optionally systemd.verity_usr_*) is present as kernel command line parameter
Diffstat (limited to 'src')
-rw-r--r--src/fstab-generator/fstab-generator.c35
-rw-r--r--src/veritysetup/veritysetup-generator.c193
2 files changed, 167 insertions, 61 deletions
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 1e6ad432dc..b764bee215 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -50,6 +50,7 @@ static int arg_root_rw = -1;
static char *arg_usr_what = NULL;
static char *arg_usr_fstype = NULL;
static char *arg_usr_options = NULL;
+static char *arg_usr_hash = NULL;
static VolatileMode arg_volatile_mode = _VOLATILE_MODE_INVALID;
STATIC_DESTRUCTOR_REGISTER(arg_root_what, freep);
@@ -59,6 +60,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep);
static int write_options(FILE *f, const char *options) {
_cleanup_free_ char *o = NULL;
@@ -969,6 +971,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (!strextend_with_separator(&arg_usr_options, ",", value))
return log_oom();
+ } else if (streq(key, "usrhash")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ return free_and_strdup_warn(&arg_usr_hash, value);
+
} else if (streq(key, "rw") && !value)
arg_root_rw = true;
else if (streq(key, "ro") && !value)
@@ -997,24 +1006,35 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
}
-static int determine_root(void) {
- /* If we have a root hash but no root device then Verity is used, and we use the "root" DM device as root. */
+static int determine_device(char **what, const char *hash, const char *name) {
- if (arg_root_what)
+ assert(what);
+ assert(name);
+
+ /* If we have a hash but no device then Verity is used, and we use the DM device. */
+ if (*what)
return 0;
- if (!arg_root_hash)
+ if (!hash)
return 0;
- arg_root_what = strdup("/dev/mapper/root");
- if (!arg_root_what)
+ *what = path_join("/dev/mapper/", name);
+ if (!*what)
return log_oom();
- log_info("Using verity root device %s.", arg_root_what);
+ log_info("Using verity %s device %s.", name, *what);
return 1;
}
+static int determine_root(void) {
+ return determine_device(&arg_root_what, arg_root_hash, "root");
+}
+
+static int determine_usr(void) {
+ return determine_device(&arg_usr_what, arg_usr_hash, "usr");
+}
+
static int run(const char *dest, const char *dest_early, const char *dest_late) {
int r, r2 = 0, r3 = 0;
@@ -1026,6 +1046,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
(void) determine_root();
+ (void) determine_usr();
/* Always honour root= and usr= in the kernel command line if we are in an initrd */
if (in_initrd()) {
diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c
index 13181b86ed..e38bd04159 100644
--- a/src/veritysetup/veritysetup-generator.c
+++ b/src/veritysetup/veritysetup-generator.c
@@ -22,53 +22,69 @@
#include "string-util.h"
#include "unit-name.h"
-#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service"
+#define SYSTEMD_VERITYSETUP_SERVICE_ROOT "systemd-veritysetup@root.service"
+#define SYSTEMD_VERITYSETUP_SERVICE_USR "systemd-veritysetup@usr.service"
static const char *arg_dest = NULL;
static bool arg_enabled = true;
static bool arg_read_veritytab = true;
static const char *arg_veritytab = NULL;
static char *arg_root_hash = NULL;
-static char *arg_data_what = NULL;
-static char *arg_hash_what = NULL;
-static char *arg_options = NULL;
+static char *arg_root_data_what = NULL;
+static char *arg_root_hash_what = NULL;
+static char *arg_root_options = NULL;
+static char *arg_usr_hash = NULL;
+static char *arg_usr_data_what = NULL;
+static char *arg_usr_hash_what = NULL;
+static char *arg_usr_options = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
-STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep);
-STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep);
-STATIC_DESTRUCTOR_REGISTER(arg_options, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_data_what, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_hash_what, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_usr_data_what, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_usr_hash_what, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep);
+
+static int create_device(
+ const char *name,
+ const char *service,
+ const char *hash,
+ const char *data_what,
+ const char *hash_what,
+ const char *options) {
-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, *options_escaped = NULL;
+ *hash_escaped = NULL, *options_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *to;
+ const char *to, *from;
int r;
+ assert(name);
+ assert(service);
+
/* If all three pieces of information are missing, then verity is turned off */
- if (!arg_root_hash && !arg_data_what && !arg_hash_what)
+ if (!hash && !data_what && !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)
+ if (!hash)
+ log_error("Verity information for %s incomplete, hash unspecified.", name);
+ if (!data_what)
+ log_error("Verity information for %s incomplete, data device unspecified.", name);
+ if (!hash_what)
+ log_error("Verity information for %s incomplete, hash device unspecified.", name);
+
+ if (!hash || !data_what || !hash_what)
return -EINVAL;
- log_debug("Using root verity data device %s,\n"
- " hash device %s,\n"
- " options %s,\n"
- " and root hash %s.", arg_data_what, arg_hash_what, arg_options, arg_root_hash);
+ log_debug("Using %s verity data device %s, hash device %s, options %s, and hash %s.", name, data_what, hash_what, options, hash);
- u = fstab_node_to_udev_node(arg_data_what);
+ u = fstab_node_to_udev_node(data_what);
if (!u)
return log_oom();
- v = fstab_node_to_udev_node(arg_hash_what);
+ v = fstab_node_to_udev_node(hash_what);
if (!v)
return log_oom();
@@ -86,15 +102,15 @@ static int create_device(void) {
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- options_escaped = specifier_escape(strempty(arg_options));
+ options_escaped = specifier_escape(strempty(options));
if (!options_escaped)
return log_oom();
- root_hash_escaped = specifier_escape(arg_root_hash);
- if (!root_hash_escaped)
+ hash_escaped = specifier_escape(hash);
+ if (!hash_escaped)
return log_oom();
- r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f);
+ r = generator_open_unit_file(arg_dest, NULL, service, &f);
if (r < 0)
return r;
@@ -112,25 +128,35 @@ static int create_device(void) {
"\n[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
- "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s' '%s'\n"
- "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n",
+ "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach '%s' '%s' '%s' '%s' '%s'\n"
+ "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach '%s' \n",
d, e,
d, e,
- u_escaped, v_escaped, root_hash_escaped, options_escaped);
+ name, u_escaped, v_escaped, hash_escaped, options_escaped,
+ name);
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m");
+ return log_error_errno(r, "Failed to write file unit %s: %m", service);
- to = strjoina(arg_dest, "/veritysetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE);
+ to = strjoina(arg_dest, "/veritysetup.target.requires/", service);
+ from = strjoina("../", service);
(void) mkdir_parents(to, 0755);
- if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0)
+ if (symlink(from, to) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", to);
return 0;
}
+static int create_root_device(void) {
+ return create_device("root", SYSTEMD_VERITYSETUP_SERVICE_ROOT, arg_root_hash, arg_root_data_what, arg_root_hash_what, arg_root_options);
+}
+
+static int create_usr_device(void) {
+ return create_device("usr", SYSTEMD_VERITYSETUP_SERVICE_USR, arg_usr_hash, arg_usr_data_what, arg_usr_hash_what, arg_usr_options);
+}
+
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
@@ -164,7 +190,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- r = free_and_strdup(&arg_data_what, value);
+ r = free_and_strdup(&arg_root_data_what, value);
if (r < 0)
return log_oom();
@@ -173,7 +199,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- r = free_and_strdup(&arg_hash_what, value);
+ r = free_and_strdup(&arg_root_hash_what, value);
if (r < 0)
return log_oom();
@@ -182,7 +208,43 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- r = free_and_strdup(&arg_options, value);
+ r = free_and_strdup(&arg_root_options, value);
+ if (r < 0)
+ return log_oom();
+
+ } else if (proc_cmdline_key_streq(key, "usrhash")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = free_and_strdup(&arg_usr_hash, value);
+ if (r < 0)
+ return log_oom();
+
+ } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_data")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = free_and_strdup(&arg_usr_data_what, value);
+ if (r < 0)
+ return log_oom();
+
+ } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_hash")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = free_and_strdup(&arg_usr_hash_what, value);
+ if (r < 0)
+ return log_oom();
+
+ } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_options")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = free_and_strdup(&arg_usr_options, value);
if (r < 0)
return log_oom();
@@ -191,47 +253,66 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
}
-static int determine_devices(void) {
+static int determine_device(
+ const char *name,
+ const char *hash,
+ char **data_what,
+ char **hash_what) {
+
+ sd_id128_t data_uuid, verity_uuid;
_cleanup_free_ void *m = NULL;
- sd_id128_t root_uuid, verity_uuid;
size_t l;
int r;
- /* Try to automatically derive the root data and hash device paths from the root hash */
+ assert(name);
+ assert(data_what);
+ assert(hash_what);
- if (!arg_root_hash)
+ if (!hash)
return 0;
- if (arg_data_what && arg_hash_what)
+ if (*data_what && *hash_what)
return 0;
- r = unhexmem(arg_root_hash, strlen(arg_root_hash), &m, &l);
+ r = unhexmem(hash, strlen(hash), &m, &l);
if (r < 0)
- return log_error_errno(r, "Failed to parse root hash: %s", arg_root_hash);
+ return log_error_errno(r, "Failed to parse hash: %s", hash);
if (l < sizeof(sd_id128_t)) {
- log_debug("Root hash is shorter than 128 bits (32 characters), ignoring for discovering verity partition.");
+ log_debug("Root hash for %s is shorter than 128 bits (32 characters), ignoring for discovering verity partition.", name);
return 0;
}
- if (!arg_data_what) {
- memcpy(&root_uuid, m, sizeof(root_uuid));
+ if (!*data_what) {
+ memcpy(&data_uuid, m, sizeof(data_uuid));
- arg_data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(root_uuid));
- if (!arg_data_what)
+ *data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(data_uuid));
+ if (!*data_what)
return log_oom();
}
- if (!arg_hash_what) {
+ if (!*hash_what) {
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
- arg_hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid));
- if (!arg_hash_what)
+ *hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid));
+ if (!*hash_what)
return log_oom();
}
+ log_info("Using data device %s and hash device %s for %s.", *data_what, *hash_what, name);
+
return 1;
}
+static int determine_devices(void) {
+ int r;
+
+ r = determine_device("root", arg_root_hash, &arg_root_data_what, &arg_root_hash_what);
+ if (r < 0)
+ return r;
+
+ return determine_device("usr", arg_usr_hash, &arg_usr_data_what, &arg_usr_hash_what);
+}
+
static int create_disk(
const char *name,
const char *data_device,
@@ -446,7 +527,11 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
if (r < 0)
return r;
- return create_device();
+ r = create_root_device();
+ if (r < 0)
+ return r;
+
+ return create_usr_device();
}
DEFINE_MAIN_GENERATOR_FUNCTION(run);