Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+37 -37
+1 -1
drivers/firmware/efi/cper-arm.c
··· 311 311 ctx_info = (struct cper_arm_ctx_info *)err_info; 312 312 max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1; 313 313 for (i = 0; i < proc->context_info_num; i++) { 314 - int size = sizeof(*ctx_info) + ctx_info->size; 314 + int size = ALIGN(sizeof(*ctx_info) + ctx_info->size, 16); 315 315 316 316 printk("%sContext info structure %d:\n", pfx, i); 317 317 if (len < size) {
+1 -1
drivers/firmware/efi/cper-x86.c
··· 325 325 326 326 ctx_info = (struct cper_ia_proc_ctx *)err_info; 327 327 for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) { 328 - int size = sizeof(*ctx_info) + ctx_info->reg_arr_size; 328 + int size = ALIGN(sizeof(*ctx_info) + ctx_info->reg_arr_size, 16); 329 329 int groupsize = 4; 330 330 331 331 printk("%sContext Information Structure %d:\n", pfx, i);
+27 -30
drivers/firmware/efi/mokvar-table.c
··· 99 99 */ 100 100 void __init efi_mokvar_table_init(void) 101 101 { 102 + struct efi_mokvar_table_entry __aligned(1) *mokvar_entry, *next_entry; 102 103 efi_memory_desc_t md; 103 104 void *va = NULL; 104 105 unsigned long cur_offset = 0; 105 106 unsigned long offset_limit; 106 - unsigned long map_size = 0; 107 107 unsigned long map_size_needed = 0; 108 108 unsigned long size; 109 - struct efi_mokvar_table_entry *mokvar_entry; 110 109 int err; 111 110 112 111 if (!efi_enabled(EFI_MEMMAP)) ··· 133 134 */ 134 135 err = -EINVAL; 135 136 while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) { 136 - mokvar_entry = va + cur_offset; 137 - map_size_needed = cur_offset + sizeof(*mokvar_entry); 138 - if (map_size_needed > map_size) { 139 - if (va) 140 - early_memunmap(va, map_size); 141 - /* 142 - * Map a little more than the fixed size entry 143 - * header, anticipating some data. It's safe to 144 - * do so as long as we stay within current memory 145 - * descriptor. 146 - */ 147 - map_size = min(map_size_needed + 2*EFI_PAGE_SIZE, 148 - offset_limit); 149 - va = early_memremap(efi.mokvar_table, map_size); 150 - if (!va) { 151 - pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n", 152 - efi.mokvar_table, map_size); 153 - return; 154 - } 155 - mokvar_entry = va + cur_offset; 137 + if (va) 138 + early_memunmap(va, sizeof(*mokvar_entry)); 139 + va = early_memremap(efi.mokvar_table + cur_offset, sizeof(*mokvar_entry)); 140 + if (!va) { 141 + pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n", 142 + efi.mokvar_table + cur_offset, sizeof(*mokvar_entry)); 143 + return; 156 144 } 157 - 145 + mokvar_entry = va; 146 + next: 158 147 /* Check for last sentinel entry */ 159 148 if (mokvar_entry->name[0] == '\0') { 160 149 if (mokvar_entry->data_size != 0) 161 150 break; 162 151 err = 0; 152 + map_size_needed = cur_offset + sizeof(*mokvar_entry); 163 153 break; 164 154 } 165 155 166 - /* Sanity check that the name is null terminated */ 167 - size = strnlen(mokvar_entry->name, 168 - sizeof(mokvar_entry->name)); 169 - if (size >= sizeof(mokvar_entry->name)) 170 - break; 156 + /* Enforce that the name is NUL terminated */ 157 + mokvar_entry->name[sizeof(mokvar_entry->name) - 1] = '\0'; 171 158 172 159 /* Advance to the next entry */ 173 - cur_offset = map_size_needed + mokvar_entry->data_size; 160 + size = sizeof(*mokvar_entry) + mokvar_entry->data_size; 161 + cur_offset += size; 162 + 163 + /* 164 + * Don't bother remapping if the current entry header and the 165 + * next one end on the same page. 166 + */ 167 + next_entry = (void *)((unsigned long)mokvar_entry + size); 168 + if (((((unsigned long)(mokvar_entry + 1) - 1) ^ 169 + ((unsigned long)(next_entry + 1) - 1)) & PAGE_MASK) == 0) { 170 + mokvar_entry = next_entry; 171 + goto next; 172 + } 174 173 } 175 174 176 175 if (va) 177 - early_memunmap(va, map_size); 176 + early_memunmap(va, sizeof(*mokvar_entry)); 178 177 if (err) { 179 178 pr_err("EFI MOKvar config table is not valid\n"); 180 179 return;
+6 -4
fs/efivarfs/file.c
··· 57 57 58 58 if (bytes == -ENOENT) { 59 59 /* 60 - * zero size signals to release that the write deleted 61 - * the variable 60 + * FIXME: temporary workaround for fwupdate, signal 61 + * failed write with a 1 to keep created but not 62 + * written files 62 63 */ 63 - i_size_write(inode, 0); 64 + i_size_write(inode, 1); 64 65 } else { 65 66 i_size_write(inode, datasize + sizeof(attributes)); 66 67 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); ··· 125 124 struct efivar_entry *var = inode->i_private; 126 125 127 126 inode_lock(inode); 128 - var->removed = (--var->open_count == 0 && i_size_read(inode) == 0); 127 + /* FIXME: temporary work around for fwupdate */ 128 + var->removed = (--var->open_count == 0 && i_size_read(inode) == 1); 129 129 inode_unlock(inode); 130 130 131 131 if (var->removed)
+2 -1
fs/efivarfs/super.c
··· 367 367 if (err) 368 368 return err; 369 369 370 + register_pm_notifier(&sfi->pm_nb); 371 + 370 372 return efivar_init(efivarfs_callback, sb, true); 371 373 } 372 374 ··· 554 552 555 553 sfi->pm_nb.notifier_call = efivarfs_pm_notify; 556 554 sfi->pm_nb.priority = 0; 557 - register_pm_notifier(&sfi->pm_nb); 558 555 559 556 return 0; 560 557 }