Description: Support immutable variables The Linux kernel was changed at some point to create EFI variables as immutable files. Cope with that. Derived from a similar patch in efivar. Origin: other, https://github.com/rhboot/efivar/commit/df78c36 Index: mokutil-0.2.0/src/efilib.c =================================================================== --- mokutil-0.2.0.orig/src/efilib.c +++ mokutil-0.2.0/src/efilib.c @@ -26,8 +26,44 @@ #include #include "efi.h" +#include +#include + #define SYSFS_DIR_EFI_VARS "/sys/firmware/efi/efivars" +static int +efi_set_immutable(const char *path, int immutable) +{ + unsigned int flags; + typeof(errno) error = 0; + int fd; + int rc = 0; + + fd = open(path, O_RDONLY); + if (fd < 0) // File doesn't exist yet, so we don't care + return 0; + + rc = ioctl(fd, FS_IOC_GETFLAGS, &flags); + if (rc < 0) { + if (errno != ENOTTY) + error = errno; + } 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); + if (rc < 0) + error = errno; + } + + close(fd); + errno = error; + return rc; +} + char * efi_guid_unparse (efi_guid_t *guid, char *out) { @@ -172,6 +208,12 @@ write_variable (const char *filename, ef memcpy (buffer + sizeof(uint32_t), var->Data, var->DataSize); total = var->DataSize + sizeof(uint32_t); + int rc = efi_set_immutable (filename, 0); + if (rc < 0) { + free (buffer); + return EFI_INVALID_PARAMETER; + } + flag = O_WRONLY | O_CREAT; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fd = open (filename, flag, mode); @@ -186,6 +228,9 @@ write_variable (const char *filename, ef return EFI_INVALID_PARAMETER; } close (fd); + + efi_set_immutable (filename, 1); + free (buffer); return EFI_SUCCESS; } @@ -231,6 +276,10 @@ delete_variable(efi_variable_t *var) snprintf(filename, PATH_MAX-1, "%s/%s", SYSFS_DIR_EFI_VARS, name); + int rc = efi_set_immutable (filename, 0); + if (rc < 0) + return EFI_INVALID_PARAMETER; + if (unlink (filename) == 0) return EFI_SUCCESS; @@ -253,8 +302,14 @@ edit_protected_variable (efi_variable_t if (ret != EFI_SUCCESS) return ret; + int rc = efi_set_immutable (filename, 0); + if (rc < 0) + return EFI_INVALID_PARAMETER; + if (chmod (filename, S_IRUSR | S_IWUSR) < 0) return EFI_UNSUPPORTED; + efi_set_immutable (filename, 1); + return EFI_SUCCESS; }