|
|
9985ef |
From 678895d781125544df91432861fadcae8d1c7a80 Mon Sep 17 00:00:00 2001
|
|
|
9985ef |
From: Peter Jones <pjones@redhat.com>
|
|
|
9985ef |
Date: Mon, 17 Aug 2020 14:18:31 -0400
|
|
|
9985ef |
Subject: [PATCH] initial mok-variables code
|
|
|
9985ef |
|
|
|
9985ef |
This patch adds support for getting mok variables from
|
|
|
9985ef |
/sys/firmware/fi/mok-variables/$NAME , if they are present, as well as
|
|
|
9985ef |
for checking MokListRT, MokListRT1, MokListRT2, etc., for any of the mok
|
|
|
9985ef |
variables.
|
|
|
9985ef |
|
|
|
9985ef |
Resolves: rhbz#1868820
|
|
|
9985ef |
|
|
|
9985ef |
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
|
9985ef |
---
|
|
|
9985ef |
src/mokutil.c | 177 +++++++++++++++++++++++++++++++++++++++++++-------
|
|
|
9985ef |
1 file changed, 153 insertions(+), 24 deletions(-)
|
|
|
9985ef |
|
|
|
9985ef |
diff --git a/src/mokutil.c b/src/mokutil.c
|
|
|
9985ef |
index b5080107600..d2fcdc9da0e 100644
|
|
|
9985ef |
--- a/src/mokutil.c
|
|
|
9985ef |
+++ b/src/mokutil.c
|
|
|
9985ef |
@@ -229,6 +229,63 @@ signature_size (const efi_guid_t *hash_type)
|
|
|
9985ef |
return 0;
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
+static int
|
|
|
9985ef |
+mok_get_variable(const char *name, uint8_t **datap, size_t *data_sizep)
|
|
|
9985ef |
+{
|
|
|
9985ef |
+ char filename[] = "/sys/firmware/efi/mok-variables/implausibly-long-mok-variable-name";
|
|
|
9985ef |
+ size_t filename_sz = sizeof(filename);
|
|
|
9985ef |
+ int fd, rc;
|
|
|
9985ef |
+ struct stat sb = { 0, };
|
|
|
9985ef |
+ uint8_t *buf;
|
|
|
9985ef |
+ size_t bufsz, pos = 0;
|
|
|
9985ef |
+ ssize_t ssz;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ *datap = 0;
|
|
|
9985ef |
+ *data_sizep = 0;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ snprintf(filename, filename_sz, "/sys/firmware/efi/mok-variables/%s", name);
|
|
|
9985ef |
+
|
|
|
9985ef |
+ fd = open(filename, O_RDONLY);
|
|
|
9985ef |
+ if (fd < 0)
|
|
|
9985ef |
+ return fd;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ rc = fstat(fd, &sb);
|
|
|
9985ef |
+ if (rc < 0) {
|
|
|
9985ef |
+err_close:
|
|
|
9985ef |
+ close(fd);
|
|
|
9985ef |
+ return rc;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ if (sb.st_size == 0) {
|
|
|
9985ef |
+ errno = ENOENT;
|
|
|
9985ef |
+ rc = -1;
|
|
|
9985ef |
+ goto err_close;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ bufsz = sb.st_size;
|
|
|
9985ef |
+ buf = calloc(1, bufsz);
|
|
|
9985ef |
+ if (!buf)
|
|
|
9985ef |
+ goto err_close;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ while (pos < bufsz) {
|
|
|
9985ef |
+ ssz = read(fd, &buf[pos], bufsz - pos);
|
|
|
9985ef |
+ if (ssz < 0) {
|
|
|
9985ef |
+ if (errno == EAGAIN ||
|
|
|
9985ef |
+ errno == EWOULDBLOCK ||
|
|
|
9985ef |
+ errno == EINTR)
|
|
|
9985ef |
+ continue;
|
|
|
9985ef |
+ free(buf);
|
|
|
9985ef |
+ goto err_close;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ pos += ssz;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+ *datap = buf;
|
|
|
9985ef |
+ *data_sizep = pos;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+}
|
|
|
9985ef |
+
|
|
|
9985ef |
static MokListNode*
|
|
|
9985ef |
build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num)
|
|
|
9985ef |
{
|
|
|
9985ef |
@@ -596,25 +653,44 @@ static int
|
|
|
9985ef |
list_keys_in_var (const char *var_name, const efi_guid_t guid)
|
|
|
9985ef |
{
|
|
|
9985ef |
uint8_t *data = NULL;
|
|
|
9985ef |
- size_t data_size;
|
|
|
9985ef |
+ char varname[] = "implausibly-long-mok-variable-name";
|
|
|
9985ef |
+ size_t data_sz, i, varname_sz = sizeof(varname);
|
|
|
9985ef |
uint32_t attributes;
|
|
|
9985ef |
int ret;
|
|
|
9985ef |
|
|
|
9985ef |
- ret = efi_get_variable (guid, var_name, &data, &data_size, &attributes);
|
|
|
9985ef |
- if (ret < 0) {
|
|
|
9985ef |
- if (errno == ENOENT) {
|
|
|
9985ef |
- printf ("%s is empty\n", var_name);
|
|
|
9985ef |
- return 0;
|
|
|
9985ef |
+ ret = mok_get_variable(var_name, &data, &data_sz);
|
|
|
9985ef |
+ if (ret >= 0) {
|
|
|
9985ef |
+ ret = list_keys (data, data_sz);
|
|
|
9985ef |
+ free(data);
|
|
|
9985ef |
+ return ret;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ for (i = 0; i < SIZE_MAX; i++) {
|
|
|
9985ef |
+ if (i == 0) {
|
|
|
9985ef |
+ snprintf(varname, varname_sz, "%s", var_name);
|
|
|
9985ef |
+ } else {
|
|
|
9985ef |
+ snprintf(varname, varname_sz, "%s%zu", var_name, i);
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
- fprintf (stderr, "Failed to read %s: %m\n", var_name);
|
|
|
9985ef |
- return -1;
|
|
|
9985ef |
+ ret = efi_get_variable (guid, varname, &data, &data_sz,
|
|
|
9985ef |
+ &attributes);
|
|
|
9985ef |
+ if (ret < 0)
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ ret = list_keys (data, data_sz);
|
|
|
9985ef |
+ free(data);
|
|
|
9985ef |
+ /*
|
|
|
9985ef |
+ * If ret is < 0, the next one will error as well.
|
|
|
9985ef |
+ * If ret is 0, we need to test the next variable.
|
|
|
9985ef |
+ * If it's 1, that's a real answer.
|
|
|
9985ef |
+ */
|
|
|
9985ef |
+ if (ret < 0)
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+ if (ret > 0)
|
|
|
9985ef |
+ return ret;
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
- ret = list_keys (data, data_size);
|
|
|
9985ef |
- free (data);
|
|
|
9985ef |
-
|
|
|
9985ef |
- return ret;
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
static int
|
|
|
9985ef |
@@ -1013,22 +1089,15 @@ is_valid_cert (void *cert, uint32_t cert_size)
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
static int
|
|
|
9985ef |
-is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size,
|
|
|
9985ef |
- const efi_guid_t *vendor, const char *db_name)
|
|
|
9985ef |
+is_one_duplicate (const efi_guid_t *type,
|
|
|
9985ef |
+ const void *data, const uint32_t data_size,
|
|
|
9985ef |
+ uint8_t *var_data, size_t var_data_size)
|
|
|
9985ef |
{
|
|
|
9985ef |
- uint8_t *var_data;
|
|
|
9985ef |
- size_t var_data_size;
|
|
|
9985ef |
- uint32_t attributes;
|
|
|
9985ef |
uint32_t node_num;
|
|
|
9985ef |
MokListNode *list;
|
|
|
9985ef |
int ret = 0;
|
|
|
9985ef |
|
|
|
9985ef |
- if (!data || data_size == 0 || !db_name)
|
|
|
9985ef |
- return 0;
|
|
|
9985ef |
-
|
|
|
9985ef |
- ret = efi_get_variable (*vendor, db_name, &var_data, &var_data_size,
|
|
|
9985ef |
- &attributes);
|
|
|
9985ef |
- if (ret < 0)
|
|
|
9985ef |
+ if (!data || data_size == 0)
|
|
|
9985ef |
return 0;
|
|
|
9985ef |
|
|
|
9985ef |
list = build_mok_list (var_data, var_data_size, &node_num);
|
|
|
9985ef |
@@ -1060,11 +1129,69 @@ is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size
|
|
|
9985ef |
done:
|
|
|
9985ef |
if (list)
|
|
|
9985ef |
free (list);
|
|
|
9985ef |
- free (var_data);
|
|
|
9985ef |
|
|
|
9985ef |
return ret;
|
|
|
9985ef |
}
|
|
|
9985ef |
|
|
|
9985ef |
+static int
|
|
|
9985ef |
+is_duplicate (const efi_guid_t *type,
|
|
|
9985ef |
+ const void *data, const uint32_t data_size,
|
|
|
9985ef |
+ const efi_guid_t *vendor, const char *db_name)
|
|
|
9985ef |
+{
|
|
|
9985ef |
+ uint32_t attributes;
|
|
|
9985ef |
+ char varname[] = "implausibly-long-mok-variable-name";
|
|
|
9985ef |
+ size_t varname_sz = sizeof(varname);
|
|
|
9985ef |
+ int ret = 0;
|
|
|
9985ef |
+ size_t i;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ if (!strncmp(db_name, "Mok", 3)) {
|
|
|
9985ef |
+ uint8_t *var_data = NULL;
|
|
|
9985ef |
+ size_t var_data_size = 0;
|
|
|
9985ef |
+ ret = mok_get_variable(db_name, &var_data, &var_data_size);
|
|
|
9985ef |
+ if (ret >= 0) {
|
|
|
9985ef |
+ ret = is_one_duplicate(type, data, data_size,
|
|
|
9985ef |
+ var_data, var_data_size);
|
|
|
9985ef |
+ if (ret >= 0) {
|
|
|
9985ef |
+ free (var_data);
|
|
|
9985ef |
+ return ret;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+ var_data = NULL;
|
|
|
9985ef |
+ var_data_size = 0;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ for (i = 0; i < SIZE_MAX; i++) {
|
|
|
9985ef |
+ uint8_t *var_data = NULL;
|
|
|
9985ef |
+ size_t var_data_size = 0;
|
|
|
9985ef |
+ if (i == 0) {
|
|
|
9985ef |
+ snprintf(varname, varname_sz, "%s", db_name);
|
|
|
9985ef |
+ } else {
|
|
|
9985ef |
+ snprintf(varname, varname_sz, "%s%zu", db_name, i);
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ ret = efi_get_variable (*vendor, varname,
|
|
|
9985ef |
+ &var_data, &var_data_size,
|
|
|
9985ef |
+ &attributes);
|
|
|
9985ef |
+ if (ret < 0)
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+
|
|
|
9985ef |
+ ret = is_one_duplicate(type, data, data_size,
|
|
|
9985ef |
+ var_data, var_data_size);
|
|
|
9985ef |
+ free (var_data);
|
|
|
9985ef |
+ /*
|
|
|
9985ef |
+ * If ret is < 0, the next one will error as well.
|
|
|
9985ef |
+ * If ret is 0, we need to test the next variable.
|
|
|
9985ef |
+ * If it's 1, that's a real answer.
|
|
|
9985ef |
+ */
|
|
|
9985ef |
+ if (ret < 0)
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+ if (ret > 0)
|
|
|
9985ef |
+ return ret;
|
|
|
9985ef |
+ }
|
|
|
9985ef |
+
|
|
|
9985ef |
+ return 0;
|
|
|
9985ef |
+}
|
|
|
9985ef |
+
|
|
|
9985ef |
static int
|
|
|
9985ef |
is_valid_request (const efi_guid_t *type, void *mok, uint32_t mok_size,
|
|
|
9985ef |
MokRequest req)
|
|
|
9985ef |
--
|
|
|
9985ef |
2.26.2
|
|
|
9985ef |
|