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-3' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI fixes from Ard Biesheuvel:
"Here's a final batch of EFI fixes for v6.14.

The efivarfs ones are fixes for changes that were made this cycle.
James's fix is somewhat of a band-aid, but it was blessed by the VFS
folks, who are working with James to come up with something better for
the next cycle.

- Avoid physical address 0x0 for random page allocations

- Add correct lockdep annotation when traversing efivarfs on resume

- Avoid NULL mount in kernel_file_open() when traversing efivarfs on
resume"

* tag 'efi-fixes-for-v6.14-3' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
efivarfs: fix NULL dereference on resume
efivarfs: use I_MUTEX_CHILD nested lock to traverse variables on resume
efi/libstub: Avoid physical address 0x0 when doing random allocation

+53 -3
+4
drivers/firmware/efi/libstub/randomalloc.c
··· 75 75 if (align < EFI_ALLOC_ALIGN) 76 76 align = EFI_ALLOC_ALIGN; 77 77 78 + /* Avoid address 0x0, as it can be mistaken for NULL */ 79 + if (alloc_min == 0) 80 + alloc_min = align; 81 + 78 82 size = round_up(size, EFI_ALLOC_ALIGN); 79 83 80 84 /* count the suitable slots in each memory map entry */
+49 -3
fs/efivarfs/super.c
··· 421 421 if (err) 422 422 size = 0; 423 423 424 - inode_lock(inode); 424 + inode_lock_nested(inode, I_MUTEX_CHILD); 425 425 i_size_write(inode, size); 426 426 inode_unlock(inode); 427 427 ··· 474 474 return err; 475 475 } 476 476 477 + static void efivarfs_deactivate_super_work(struct work_struct *work) 478 + { 479 + struct super_block *s = container_of(work, struct super_block, 480 + destroy_work); 481 + /* 482 + * note: here s->destroy_work is free for reuse (which 483 + * will happen in deactivate_super) 484 + */ 485 + deactivate_super(s); 486 + } 487 + 488 + static struct file_system_type efivarfs_type; 489 + 477 490 static int efivarfs_pm_notify(struct notifier_block *nb, unsigned long action, 478 491 void *ptr) 479 492 { 480 493 struct efivarfs_fs_info *sfi = container_of(nb, struct efivarfs_fs_info, 481 494 pm_nb); 482 - struct path path = { .mnt = NULL, .dentry = sfi->sb->s_root, }; 495 + struct path path; 483 496 struct efivarfs_ctx ectx = { 484 497 .ctx = { 485 498 .actor = efivarfs_actor, ··· 500 487 .sb = sfi->sb, 501 488 }; 502 489 struct file *file; 490 + struct super_block *s = sfi->sb; 503 491 static bool rescan_done = true; 504 492 505 493 if (action == PM_HIBERNATION_PREPARE) { ··· 513 499 if (rescan_done) 514 500 return NOTIFY_DONE; 515 501 502 + /* ensure single superblock is alive and pin it */ 503 + if (!atomic_inc_not_zero(&s->s_active)) 504 + return NOTIFY_DONE; 505 + 516 506 pr_info("efivarfs: resyncing variable state\n"); 517 507 518 - /* O_NOATIME is required to prevent oops on NULL mnt */ 508 + path.dentry = sfi->sb->s_root; 509 + 510 + /* 511 + * do not add SB_KERNMOUNT which a single superblock could 512 + * expose to userspace and which also causes MNT_INTERNAL, see 513 + * below 514 + */ 515 + path.mnt = vfs_kern_mount(&efivarfs_type, 0, 516 + efivarfs_type.name, NULL); 517 + if (IS_ERR(path.mnt)) { 518 + pr_err("efivarfs: internal mount failed\n"); 519 + /* 520 + * We may be the last pinner of the superblock but 521 + * calling efivarfs_kill_sb from within the notifier 522 + * here would deadlock trying to unregister it 523 + */ 524 + INIT_WORK(&s->destroy_work, efivarfs_deactivate_super_work); 525 + schedule_work(&s->destroy_work); 526 + return PTR_ERR(path.mnt); 527 + } 528 + 529 + /* path.mnt now has pin on superblock, so this must be above one */ 530 + atomic_dec(&s->s_active); 531 + 519 532 file = kernel_file_open(&path, O_RDONLY | O_DIRECTORY | O_NOATIME, 520 533 current_cred()); 534 + /* 535 + * safe even if last put because no MNT_INTERNAL means this 536 + * will do delayed deactivate_super and not deadlock 537 + */ 538 + mntput(path.mnt); 521 539 if (IS_ERR(file)) 522 540 return NOTIFY_DONE; 523 541