File mokutil-bsc964726-fix-immutable.patch of Package mokutil.24584

From 0eb97e1b1cf9352969117bf7c9368f8ccf77575e Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 16 Jun 2016 14:17:19 +0800
Subject: [PATCH] Change the immutable flag

The upstream patches introduced by bsc#964726 make files in efivarfs
immutable. This patch changes the immutable flag before writing the
variables so that mokutil can change the content of the variable
properly.

Signed-off-by: Gary Lin <glin@suse.com>
---
 src/efilib.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/efilib.c b/src/efilib.c
index 6db914f..1d76893 100644
--- a/src/efilib.c
+++ b/src/efilib.c
@@ -35,6 +35,8 @@
  */
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
@@ -168,6 +170,51 @@ read_variable (efi_variable_t *var)
 	return EFI_SUCCESS;
 }
 
+static int
+set_immutable_fd (int fd, int immutable)
+{
+	unsigned int flags;
+	int rc = 0;
+
+	rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+	if (rc < 0) {
+		if (errno == ENOTTY)
+			rc = 0;
+	} else if ((immutable && !(flags & FS_IMMUTABLE_FL)) ||
+		   (!immutable && (flags & FS_IMMUTABLE_FL))) {
+		if (immutable)
+			flags |= FS_IMMUTABLE_FL;
+		else
+			flags &= ~FS_IMMUTABLE_FL;
+
+		rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
+	}
+
+	return rc;
+}
+
+static int
+set_immutable (const char *filename, int immutable)
+{
+	typeof(errno) error = 0;
+	int fd;
+	int rc = 0;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		if (errno == ENOTTY)
+			return 0;
+		else
+			return fd;
+	}
+
+	rc = set_immutable_fd (fd, immutable);
+	error = errno;
+	close(fd);
+	errno = error;
+	return rc;
+}
+
 efi_status_t
 write_variable (const char *filename, efi_variable_t *var)
 {
@@ -189,6 +236,9 @@ write_variable (const char *filename, efi_variable_t *var)
 	memcpy (buffer + sizeof(uint32_t), var->Data, var->DataSize);
 	total = var->DataSize + sizeof(uint32_t);
 
+	if (!access(filename, F_OK))
+		set_immutable (filename, 0);
+
 	flag = O_WRONLY | O_CREAT;
 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 	fd = open (filename, flag, mode);
@@ -196,12 +246,14 @@ write_variable (const char *filename, efi_variable_t *var)
 		free (buffer);
 		return EFI_INVALID_PARAMETER;
 	}
+	set_immutable_fd (fd, 0);
 	writesize = write (fd, buffer, total);
 	if (writesize != total) {
 		close (fd);
 		free (buffer);
 		return EFI_INVALID_PARAMETER;
 	}
+	set_immutable_fd (fd, 1);
 	close (fd);
 	free (buffer);
 	return EFI_SUCCESS;
@@ -248,6 +300,7 @@ delete_variable(efi_variable_t *var)
 
 	snprintf(filename, PATH_MAX-1, "%s/%s", SYSFS_DIR_EFI_VARS, name);
 
+	set_immutable (filename, 0);
 	if (unlink (filename) == 0)
 		return EFI_SUCCESS;
 
@@ -270,8 +323,12 @@ edit_protected_variable (efi_variable_t *var)
 	if (ret != EFI_SUCCESS)
 		return ret;
 
-	if (chmod (filename, S_IRUSR | S_IWUSR) < 0)
+	set_immutable (filename, 0);
+	if (chmod (filename, S_IRUSR | S_IWUSR) < 0) {
+		set_immutable (filename, 1);
 		return EFI_UNSUPPORTED;
+	}
+	set_immutable (filename, 1);
 
 	return EFI_SUCCESS;
 }
-- 
2.8.4

openSUSE Build Service is sponsored by