On Fri, 22 Nov 2019, Nick Desaulniers wrote: > From: Kees Cook <keescook@xxxxxxxxxxxx> > > There's an implicit dependency on the section ordering of the orphaned > section .fixup that can break arm_copy_from_user if the linker places > the .fixup section before the .text section. Since .fixup is not > explicitly placed in the existing ARM linker scripts, the linker is free > to order it anywhere with respect to the rest of the sections. > > Multiple users from different distros (Raspbian, CrOS) reported kernel > panics executing seccomp() syscall with Linux kernels linked with LLD. > > Documentation/x86/exception-tables.rst alludes to the ordering > dependency. The relevant quote: > > ``` > NOTE: > Due to the way that the exception table is built and needs to be ordered, > only use exceptions for code in the .text section. Any other section > will cause the exception table to not be sorted correctly, and the > exceptions will fail. > > Things changed when 64-bit support was added to x86 Linux. Rather than > double the size of the exception table by expanding the two entries > from 32-bits to 64 bits, a clever trick was used to store addresses > as relative offsets from the table itself. The assembly code changed > from:: > > .long 1b,3b > to: > .long (from) - . > .long (to) - . > > and the C-code that uses these values converts back to absolute addresses > like this:: > > ex_insn_addr(const struct exception_table_entry *x) > { > return (unsigned long)&x->insn + x->insn; > } > ``` > > Since the addresses stored in the __ex_table are RELATIVE offsets and > not ABSOLUTE addresses, ordering the fixup anywhere that's not > immediately preceding .text causes the relative offset of the faulting > instruction to be wrong, causing the wrong (or no) address of the fixup > handler to looked up in __ex_table. This explanation makes no sense. The above is valid only when ARCH_HAS_RELATIVE_EXTABLE is defined. On ARM32 it is not, nor would it make sense to be. Nicolas