Skip to content

Commit 236d70f

Browse files
author
Alexander Gordeev
committed
s390/boot: Do not rescue .vmlinux.relocs section
The .vmlinux.relocs section is moved in front of the compressed kernel. The interim section rescue step is avoided as result. Suggested-by: Sumanth Korikkar <sumanthk@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent 56b1069 commit 236d70f

3 files changed

Lines changed: 22 additions & 41 deletions

File tree

arch/s390/boot/startup.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -185,34 +185,15 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
185185
}
186186

187187
static void kaslr_adjust_got(unsigned long offset) {}
188-
static void rescue_relocs(void) {}
189-
static void free_relocs(void) {}
190188
#else
191-
static int *vmlinux_relocs_64_start;
192-
static int *vmlinux_relocs_64_end;
193-
194-
static void rescue_relocs(void)
195-
{
196-
unsigned long size = __vmlinux_relocs_64_end - __vmlinux_relocs_64_start;
197-
198-
vmlinux_relocs_64_start = (void *)physmem_alloc_top_down(RR_RELOC, size, 0);
199-
vmlinux_relocs_64_end = (void *)vmlinux_relocs_64_start + size;
200-
memmove(vmlinux_relocs_64_start, __vmlinux_relocs_64_start, size);
201-
}
202-
203-
static void free_relocs(void)
204-
{
205-
physmem_free(RR_RELOC);
206-
}
207-
208189
static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
209190
unsigned long offset, unsigned long phys_offset)
210191
{
211192
int *reloc;
212193
long loc;
213194

214195
/* Adjust R_390_64 relocations */
215-
for (reloc = vmlinux_relocs_64_start; reloc < vmlinux_relocs_64_end; reloc++) {
196+
for (reloc = (int *)__vmlinux_relocs_64_start; reloc < (int *)__vmlinux_relocs_64_end; reloc++) {
216197
loc = (long)*reloc + phys_offset;
217198
if (loc < min_addr || loc > max_addr)
218199
error("64-bit relocation outside of kernel!\n");
@@ -486,7 +467,6 @@ void startup_kernel(void)
486467
detect_physmem_online_ranges(max_physmem_end);
487468
save_ipl_cert_comp_list();
488469
rescue_initrd(safe_addr, ident_map_size);
489-
rescue_relocs();
490470

491471
if (kaslr_enabled())
492472
__kaslr_offset_phys = randomize_within_range(kernel_size, THREAD_SIZE, 0, ident_map_size);
@@ -498,6 +478,18 @@ void startup_kernel(void)
498478

499479
/* vmlinux decompression is done, shrink reserved low memory */
500480
physmem_reserve(RR_DECOMPRESSOR, 0, (unsigned long)_decompressor_end);
481+
482+
/*
483+
* In case KASLR is enabled the randomized location of .amode31
484+
* section might overlap with .vmlinux.relocs section. To avoid that
485+
* the below randomize_within_range() could have been called with
486+
* __vmlinux_relocs_64_end as the lower range address. However,
487+
* .amode31 section is written to by the decompressed kernel - at
488+
* that time the contents of .vmlinux.relocs is not needed anymore.
489+
* Conversly, .vmlinux.relocs is read only by the decompressor, even
490+
* before the kernel started. Therefore, in case the two sections
491+
* overlap there is no risk of corrupting any data.
492+
*/
501493
if (kaslr_enabled())
502494
amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G);
503495
if (!amode31_lma)
@@ -521,7 +513,6 @@ void startup_kernel(void)
521513
kaslr_adjust_relocs(__kaslr_offset_phys, __kaslr_offset_phys + vmlinux.image_size,
522514
__kaslr_offset, __kaslr_offset_phys);
523515
kaslr_adjust_got(__kaslr_offset);
524-
free_relocs();
525516
setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
526517
copy_bootdata();
527518

arch/s390/boot/vmlinux.lds.S

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ SECTIONS
9999

100100
_decompressor_end = .;
101101

102+
#ifndef CONFIG_PIE_BUILD
103+
. = ALIGN(4);
104+
.vmlinux.relocs : {
105+
__vmlinux_relocs_64_start = .;
106+
*(.vmlinux.relocs_64)
107+
__vmlinux_relocs_64_end = .;
108+
}
109+
#endif
110+
102111
#ifdef CONFIG_KERNEL_UNCOMPRESSED
103112
. = ALIGN(PAGE_SIZE);
104113
. += AMODE31_SIZE; /* .amode31 section */
@@ -111,24 +120,6 @@ SECTIONS
111120
_compressed_end = .;
112121
}
113122

114-
#ifndef CONFIG_PIE_BUILD
115-
/*
116-
* When the kernel is built with CONFIG_KERNEL_UNCOMPRESSED, the entire
117-
* uncompressed vmlinux.bin is positioned in the bzImage decompressor
118-
* image at the default kernel LMA of 0x100000, enabling it to be
119-
* executed in-place. However, the size of .vmlinux.relocs could be
120-
* large enough to cause an overlap with the uncompressed kernel at the
121-
* address 0x100000. To address this issue, .vmlinux.relocs is
122-
* positioned after the .rodata.compressed.
123-
*/
124-
. = ALIGN(4);
125-
.vmlinux.relocs : {
126-
__vmlinux_relocs_64_start = .;
127-
*(.vmlinux.relocs_64)
128-
__vmlinux_relocs_64_end = .;
129-
}
130-
#endif
131-
132123
#define SB_TRAILER_SIZE 32
133124
/* Trailer needed for Secure Boot */
134125
. += SB_TRAILER_SIZE; /* make sure .sb.trailer does not overwrite the previous section */

arch/s390/include/asm/physmem_info.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ enum reserved_range_type {
2222
RR_DECOMPRESSOR,
2323
RR_INITRD,
2424
RR_VMLINUX,
25-
RR_RELOC,
2625
RR_AMODE31,
2726
RR_IPLREPORT,
2827
RR_CERT_COMP_LIST,

0 commit comments

Comments
 (0)