Skip to content

Commit ea185bd

Browse files
committed
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
2 parents 7654481 + e3cf2d9 commit ea185bd

File tree

5 files changed

+37
-37
lines changed

5 files changed

+37
-37
lines changed

drivers/firmware/efi/cper-arm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void cper_print_proc_arm(const char *pfx,
311311
ctx_info = (struct cper_arm_ctx_info *)err_info;
312312
max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
313313
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);
315315

316316
printk("%sContext info structure %d:\n", pfx, i);
317317
if (len < size) {

drivers/firmware/efi/cper-x86.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
325325

326326
ctx_info = (struct cper_ia_proc_ctx *)err_info;
327327
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);
329329
int groupsize = 4;
330330

331331
printk("%sContext Information Structure %d:\n", pfx, i);

drivers/firmware/efi/mokvar-table.c

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,13 @@ static struct kobject *mokvar_kobj;
9999
*/
100100
void __init efi_mokvar_table_init(void)
101101
{
102+
struct efi_mokvar_table_entry __aligned(1) *mokvar_entry, *next_entry;
102103
efi_memory_desc_t md;
103104
void *va = NULL;
104105
unsigned long cur_offset = 0;
105106
unsigned long offset_limit;
106-
unsigned long map_size = 0;
107107
unsigned long map_size_needed = 0;
108108
unsigned long size;
109-
struct efi_mokvar_table_entry *mokvar_entry;
110109
int err;
111110

112111
if (!efi_enabled(EFI_MEMMAP))
@@ -134,48 +133,46 @@ void __init efi_mokvar_table_init(void)
134133
*/
135134
err = -EINVAL;
136135
while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
137-
mokvar_entry = va + cur_offset;
138-
map_size_needed = cur_offset + sizeof(*mokvar_entry);
139-
if (map_size_needed > map_size) {
140-
if (va)
141-
early_memunmap(va, map_size);
142-
/*
143-
* Map a little more than the fixed size entry
144-
* header, anticipating some data. It's safe to
145-
* do so as long as we stay within current memory
146-
* descriptor.
147-
*/
148-
map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
149-
offset_limit);
150-
va = early_memremap(efi.mokvar_table, map_size);
151-
if (!va) {
152-
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
153-
efi.mokvar_table, map_size);
154-
return;
155-
}
156-
mokvar_entry = va + cur_offset;
136+
if (va)
137+
early_memunmap(va, sizeof(*mokvar_entry));
138+
va = early_memremap(efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
139+
if (!va) {
140+
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n",
141+
efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
142+
return;
157143
}
158-
144+
mokvar_entry = va;
145+
next:
159146
/* Check for last sentinel entry */
160147
if (mokvar_entry->name[0] == '\0') {
161148
if (mokvar_entry->data_size != 0)
162149
break;
163150
err = 0;
151+
map_size_needed = cur_offset + sizeof(*mokvar_entry);
164152
break;
165153
}
166154

167-
/* Sanity check that the name is null terminated */
168-
size = strnlen(mokvar_entry->name,
169-
sizeof(mokvar_entry->name));
170-
if (size >= sizeof(mokvar_entry->name))
171-
break;
155+
/* Enforce that the name is NUL terminated */
156+
mokvar_entry->name[sizeof(mokvar_entry->name) - 1] = '\0';
172157

173158
/* Advance to the next entry */
174-
cur_offset = map_size_needed + mokvar_entry->data_size;
159+
size = sizeof(*mokvar_entry) + mokvar_entry->data_size;
160+
cur_offset += size;
161+
162+
/*
163+
* Don't bother remapping if the current entry header and the
164+
* next one end on the same page.
165+
*/
166+
next_entry = (void *)((unsigned long)mokvar_entry + size);
167+
if (((((unsigned long)(mokvar_entry + 1) - 1) ^
168+
((unsigned long)(next_entry + 1) - 1)) & PAGE_MASK) == 0) {
169+
mokvar_entry = next_entry;
170+
goto next;
171+
}
175172
}
176173

177174
if (va)
178-
early_memunmap(va, map_size);
175+
early_memunmap(va, sizeof(*mokvar_entry));
179176
if (err) {
180177
pr_err("EFI MOKvar config table is not valid\n");
181178
return;

fs/efivarfs/file.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ static ssize_t efivarfs_file_write(struct file *file,
5757

5858
if (bytes == -ENOENT) {
5959
/*
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
6263
*/
63-
i_size_write(inode, 0);
64+
i_size_write(inode, 1);
6465
} else {
6566
i_size_write(inode, datasize + sizeof(attributes));
6667
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)
124125
struct efivar_entry *var = inode->i_private;
125126

126127
inode_lock(inode);
127-
var->removed = (--var->open_count == 0 && i_size_read(inode) == 0);
128+
/* FIXME: temporary work around for fwupdate */
129+
var->removed = (--var->open_count == 0 && i_size_read(inode) == 1);
128130
inode_unlock(inode);
129131

130132
if (var->removed)

fs/efivarfs/super.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
367367
if (err)
368368
return err;
369369

370+
register_pm_notifier(&sfi->pm_nb);
371+
370372
return efivar_init(efivarfs_callback, sb, true);
371373
}
372374

@@ -552,7 +554,6 @@ static int efivarfs_init_fs_context(struct fs_context *fc)
552554

553555
sfi->pm_nb.notifier_call = efivarfs_pm_notify;
554556
sfi->pm_nb.priority = 0;
555-
register_pm_notifier(&sfi->pm_nb);
556557

557558
return 0;
558559
}

0 commit comments

Comments
 (0)