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

ARM: zImage: make sure appended DTB doesn't get overwritten by kernel .bss

The appended DTB gets relocated with the decompressor code to get out
of the way of the decompressed kernel. However the kernel's .bss section
may be larger than the relocated code and data, and then the DTB gets
overwritten. Let's make sure the relocation takes care of moving zImage
far enough so no such conflict with .bss occurs.

Thanks to Tony Lindgren <tony@atomide.com> for figuring out this issue.

While at it, let's clean up the code a bit so that the wont_overwrite
symbol is used while determining if a conflict exists, making the above
change more precise as well as eliminating some ARM/THUMB alternates.

Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Acked-by: Tony Lindgren <tony@atomide.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Dave Martin <dave.martin@linaro.org>
Tested-by: Thomas Abraham <thomas.abraham@linaro.org>

authored by

Nicolas Pitre and committed by
Nicolas Pitre
5ffb04f6 e2a6a3aa

+18 -4
+3
arch/arm/boot/compressed/Makefile
··· 104 104 ccflags-y := -fpic -fno-builtin 105 105 asflags-y := -Wa,-march=all 106 106 107 + # Supply kernel BSS size to the decompressor via a linker symbol. 108 + KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}') 109 + LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) 107 110 # Supply ZRELADDR to the decompressor via a linker symbol. 108 111 ifneq ($(CONFIG_AUTO_ZRELADDR),y) 109 112 LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
+15 -4
arch/arm/boot/compressed/head.S
··· 248 248 249 249 mov r8, r6 @ use the appended device tree 250 250 251 + /* 252 + * Make sure that the DTB doesn't end up in the final 253 + * kernel's .bss area. To do so, we adjust the decompressed 254 + * kernel size to compensate if that .bss size is larger 255 + * than the relocated code. 256 + */ 257 + ldr r5, =_kernel_bss_size 258 + adr r1, wont_overwrite 259 + sub r1, r6, r1 260 + subs r1, r5, r1 261 + addhi r9, r9, r1 262 + 251 263 /* Get the dtb's size */ 252 264 ldr r5, [r6, #4] 253 265 #ifndef __ARMEB__ ··· 288 276 * r10 = end of this image, including bss/stack/malloc space if non XIP 289 277 * We basically want: 290 278 * r4 - 16k page directory >= r10 -> OK 291 - * r4 + image length <= current position (pc) -> OK 279 + * r4 + image length <= address of wont_overwrite -> OK 292 280 */ 293 281 add r10, r10, #16384 294 282 cmp r4, r10 295 283 bhs wont_overwrite 296 284 add r10, r4, r9 297 - ARM( cmp r10, pc ) 298 - THUMB( mov lr, pc ) 299 - THUMB( cmp r10, lr ) 285 + adr r9, wont_overwrite 286 + cmp r10, r9 300 287 bls wont_overwrite 301 288 302 289 /*