1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

EFI fixes for v6.14 #2

- Fix CPER error record parsing bugs
 
 - Fix a couple of efivarfs issues that were introduced in the merge
   window
 
 - Fix an issue in the early remapping code of the MOKvar table
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQQm/3uucuRGn1Dmh0wbglWLn0tXAUCZ8G8cgAKCRAwbglWLn0t
 XMQDAQDNgLENwTSbVZlJaXqc3EEb0hTeV1Rg1WG9gB5DJg5bFgD/ZoWxbY6um/Pn
 Pa7jg3tCR4bINq7WRVbMAocORGN8ZAY=
 =HbXA
 -----END PGP SIGNATURE-----

Merge tag 'efi-fixes-for-v6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI fixes from Ard Biesheuvel:
 "Another couple of EFI fixes for v6.14.

  Only James's patch stands out, as it implements a workaround for odd
  behavior in fwupd in user space, which creates EFI variables by
  touching a file in efivarfs, clearing the immutable bit (which gets
  set automatically for $reasons) and then opening it again for writing,
  none of which is really necessary.

  The fwupd author and LVFS maintainer is already rolling out a fix for
  this on the fwupd side, and suggested that the workaround in this PR
  could be backed out again during the next cycle.

  (There is a semantic mismatch in efivarfs where some essential
  variable attributes are stored in the first 4 bytes of the file, and
  so zero length files cannot exist, as they cannot be written back to
  the underlying variable store. So now, they are dropped once the last
  reference is released.)

  Summary:

   - Fix CPER error record parsing bugs

   - Fix a couple of efivarfs issues that were introduced in the merge
     window

   - Fix an issue in the early remapping code of the MOKvar table"

* tag 'efi-fixes-for-v6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  efi/mokvar-table: Avoid repeated map/unmap of the same page
  efi: Don't map the entire mokvar table to determine its size
  efivarfs: allow creation of zero length files
  efivarfs: Defer PM notifier registration until .fill_super
  efi/cper: Fix cper_arm_ctx_info alignment
  efi/cper: Fix cper_ia_proc_ctx alignment
This commit is contained in:
Linus Torvalds 2025-02-28 08:47:21 -08:00
commit ea185bdedb
5 changed files with 37 additions and 37 deletions

View file

@ -311,7 +311,7 @@ void cper_print_proc_arm(const char *pfx,
ctx_info = (struct cper_arm_ctx_info *)err_info;
max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
for (i = 0; i < proc->context_info_num; i++) {
int size = sizeof(*ctx_info) + ctx_info->size;
int size = ALIGN(sizeof(*ctx_info) + ctx_info->size, 16);
printk("%sContext info structure %d:\n", pfx, i);
if (len < size) {

View file

@ -325,7 +325,7 @@ void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
ctx_info = (struct cper_ia_proc_ctx *)err_info;
for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {
int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
int size = ALIGN(sizeof(*ctx_info) + ctx_info->reg_arr_size, 16);
int groupsize = 4;
printk("%sContext Information Structure %d:\n", pfx, i);

View file

@ -99,14 +99,13 @@ static struct kobject *mokvar_kobj;
*/
void __init efi_mokvar_table_init(void)
{
struct efi_mokvar_table_entry __aligned(1) *mokvar_entry, *next_entry;
efi_memory_desc_t md;
void *va = NULL;
unsigned long cur_offset = 0;
unsigned long offset_limit;
unsigned long map_size = 0;
unsigned long map_size_needed = 0;
unsigned long size;
struct efi_mokvar_table_entry *mokvar_entry;
int err;
if (!efi_enabled(EFI_MEMMAP))
@ -134,48 +133,46 @@ void __init efi_mokvar_table_init(void)
*/
err = -EINVAL;
while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
mokvar_entry = va + cur_offset;
map_size_needed = cur_offset + sizeof(*mokvar_entry);
if (map_size_needed > map_size) {
if (va)
early_memunmap(va, map_size);
/*
* Map a little more than the fixed size entry
* header, anticipating some data. It's safe to
* do so as long as we stay within current memory
* descriptor.
*/
map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
offset_limit);
va = early_memremap(efi.mokvar_table, map_size);
if (!va) {
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
efi.mokvar_table, map_size);
return;
}
mokvar_entry = va + cur_offset;
if (va)
early_memunmap(va, sizeof(*mokvar_entry));
va = early_memremap(efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
if (!va) {
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n",
efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
return;
}
mokvar_entry = va;
next:
/* Check for last sentinel entry */
if (mokvar_entry->name[0] == '\0') {
if (mokvar_entry->data_size != 0)
break;
err = 0;
map_size_needed = cur_offset + sizeof(*mokvar_entry);
break;
}
/* Sanity check that the name is null terminated */
size = strnlen(mokvar_entry->name,
sizeof(mokvar_entry->name));
if (size >= sizeof(mokvar_entry->name))
break;
/* Enforce that the name is NUL terminated */
mokvar_entry->name[sizeof(mokvar_entry->name) - 1] = '\0';
/* Advance to the next entry */
cur_offset = map_size_needed + mokvar_entry->data_size;
size = sizeof(*mokvar_entry) + mokvar_entry->data_size;
cur_offset += size;
/*
* Don't bother remapping if the current entry header and the
* next one end on the same page.
*/
next_entry = (void *)((unsigned long)mokvar_entry + size);
if (((((unsigned long)(mokvar_entry + 1) - 1) ^
((unsigned long)(next_entry + 1) - 1)) & PAGE_MASK) == 0) {
mokvar_entry = next_entry;
goto next;
}
}
if (va)
early_memunmap(va, map_size);
early_memunmap(va, sizeof(*mokvar_entry));
if (err) {
pr_err("EFI MOKvar config table is not valid\n");
return;

View file

@ -57,10 +57,11 @@ static ssize_t efivarfs_file_write(struct file *file,
if (bytes == -ENOENT) {
/*
* zero size signals to release that the write deleted
* the variable
* FIXME: temporary workaround for fwupdate, signal
* failed write with a 1 to keep created but not
* written files
*/
i_size_write(inode, 0);
i_size_write(inode, 1);
} else {
i_size_write(inode, datasize + sizeof(attributes));
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
@ -124,7 +125,8 @@ static int efivarfs_file_release(struct inode *inode, struct file *file)
struct efivar_entry *var = inode->i_private;
inode_lock(inode);
var->removed = (--var->open_count == 0 && i_size_read(inode) == 0);
/* FIXME: temporary work around for fwupdate */
var->removed = (--var->open_count == 0 && i_size_read(inode) == 1);
inode_unlock(inode);
if (var->removed)

View file

@ -367,6 +367,8 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (err)
return err;
register_pm_notifier(&sfi->pm_nb);
return efivar_init(efivarfs_callback, sb, true);
}
@ -552,7 +554,6 @@ static int efivarfs_init_fs_context(struct fs_context *fc)
sfi->pm_nb.notifier_call = efivarfs_pm_notify;
sfi->pm_nb.priority = 0;
register_pm_notifier(&sfi->pm_nb);
return 0;
}