Blame SOURCES/0011-initial-mok-variables-code.patch

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