@@ -35,15 +35,48 @@ efi_status_t check_platform_features(void)
3535}
3636
3737/*
38- * Although relocatable kernels can fix up the misalignment with respect to
39- * MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
40- * sync with those recorded in the vmlinux when kaslr is disabled but the
41- * image required relocation anyway. Therefore retain 2M alignment unless
42- * KASLR is in use.
38+ * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
39+ * to provide space, and fail to zero it). Check for this condition by double
40+ * checking that the first and the last byte of the image are covered by the
41+ * same EFI memory map entry.
4342 */
44- static u64 min_kimg_align ( void )
43+ static bool check_image_region ( u64 base , u64 size )
4544{
46- return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN ;
45+ unsigned long map_size , desc_size , buff_size ;
46+ efi_memory_desc_t * memory_map ;
47+ struct efi_boot_memmap map ;
48+ efi_status_t status ;
49+ bool ret = false;
50+ int map_offset ;
51+
52+ map .map = & memory_map ;
53+ map .map_size = & map_size ;
54+ map .desc_size = & desc_size ;
55+ map .desc_ver = NULL ;
56+ map .key_ptr = NULL ;
57+ map .buff_size = & buff_size ;
58+
59+ status = efi_get_memory_map (& map );
60+ if (status != EFI_SUCCESS )
61+ return false;
62+
63+ for (map_offset = 0 ; map_offset < map_size ; map_offset += desc_size ) {
64+ efi_memory_desc_t * md = (void * )memory_map + map_offset ;
65+ u64 end = md -> phys_addr + md -> num_pages * EFI_PAGE_SIZE ;
66+
67+ /*
68+ * Find the region that covers base, and return whether
69+ * it covers base+size bytes.
70+ */
71+ if (base >= md -> phys_addr && base < end ) {
72+ ret = (base + size ) <= end ;
73+ break ;
74+ }
75+ }
76+
77+ efi_bs_call (free_pool , memory_map );
78+
79+ return ret ;
4780}
4881
4982efi_status_t handle_kernel_image (unsigned long * image_addr ,
@@ -56,6 +89,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
5689 unsigned long kernel_size , kernel_memsize = 0 ;
5790 u32 phys_seed = 0 ;
5891
92+ /*
93+ * Although relocatable kernels can fix up the misalignment with
94+ * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
95+ * subtly out of sync with those recorded in the vmlinux when kaslr is
96+ * disabled but the image required relocation anyway. Therefore retain
97+ * 2M alignment if KASLR was explicitly disabled, even if it was not
98+ * going to be activated to begin with.
99+ */
100+ u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN ;
101+
59102 if (IS_ENABLED (CONFIG_RANDOMIZE_BASE )) {
60103 if (!efi_nokaslr ) {
61104 status = efi_get_random_bytes (sizeof (phys_seed ),
@@ -76,6 +119,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
76119 if (image -> image_base != _text )
77120 efi_err ("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n" );
78121
122+ if (!IS_ALIGNED ((u64 )_text , EFI_KIMG_ALIGN ))
123+ efi_err ("FIRMWARE BUG: kernel image not aligned on %ldk boundary\n" ,
124+ EFI_KIMG_ALIGN >> 10 );
125+
79126 kernel_size = _edata - _text ;
80127 kernel_memsize = kernel_size + (_end - _edata );
81128 * reserve_size = kernel_memsize ;
@@ -85,14 +132,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
85132 * If KASLR is enabled, and we have some randomness available,
86133 * locate the kernel at a randomized offset in physical memory.
87134 */
88- status = efi_random_alloc (* reserve_size , min_kimg_align () ,
135+ status = efi_random_alloc (* reserve_size , min_kimg_align ,
89136 reserve_addr , phys_seed );
137+ if (status != EFI_SUCCESS )
138+ efi_warn ("efi_random_alloc() failed: 0x%lx\n" , status );
90139 } else {
91140 status = EFI_OUT_OF_RESOURCES ;
92141 }
93142
94143 if (status != EFI_SUCCESS ) {
95- if (IS_ALIGNED ((u64 )_text , min_kimg_align ())) {
144+ if (!check_image_region ((u64 )_text , kernel_memsize )) {
145+ efi_err ("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n" );
146+ } else if (IS_ALIGNED ((u64 )_text , min_kimg_align )) {
96147 /*
97148 * Just execute from wherever we were loaded by the
98149 * UEFI PE/COFF loader if the alignment is suitable.
@@ -103,7 +154,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
103154 }
104155
105156 status = efi_allocate_pages_aligned (* reserve_size , reserve_addr ,
106- ULONG_MAX , min_kimg_align () );
157+ ULONG_MAX , min_kimg_align );
107158
108159 if (status != EFI_SUCCESS ) {
109160 efi_err ("Failed to relocate kernel\n" );
0 commit comments