diff mbox

Possible regression: module insertion, relocation misalignement

Message ID 87egil26sn.fsf@belgarion.home (mailing list archive)
State New, archived
Headers show

Commit Message

Robert Jarzmik Aug. 29, 2015, 8:12 p.m. UTC
Hello,

I have a strange regression with linux-next on module insertion. The stack I get
when inserting a module is in [3]. I'm using the gcc in [1], and added a small
print in [2]. This happens on a pxa310 cm-x300 platform.

As far as I understand the Oops, this is an unaligned access on the following
relocation (0xbf009a26):
	*(u32 *)loc += sym->st_value;

This happens regardless of the module I try, by that fat.ko, pxa3xx-nand.ko, etc
.. I add that I have not changed my toolchain for quite some time.

Is there anyone also affected by this bug ?

Cheers.

Comments

Robert Jarzmik Aug. 31, 2015, 11 p.m. UTC | #1
Robert Jarzmik <robert.jarzmik@free.fr> writes:
> Hello,
>
> I have a strange regression with linux-next on module insertion. The stack I get
> when inserting a module is in [3]. I'm using the gcc in [1], and added a small
> print in [2]. This happens on a pxa310 cm-x300 platform.
>
> As far as I understand the Oops, this is an unaligned access on the following
> relocation (0xbf009a26):
> 	*(u32 *)loc += sym->st_value;
>
> This happens regardless of the module I try, by that fat.ko, pxa3xx-nand.ko, etc
> .. I add that I have not changed my toolchain for quite some time.
Hi Russell,

After digging a bit in the problem, and even if I don't understand why this
happens, I know at least _what_ happens. I'd like to know if this is specific to
xscale or a wider problem, hence this mail to you.

The summary of my problem :
 - on linux-next (20150828), module insertion Oopses (see [3])
 - the Oops is as far as I understand an unaligned access (message above)
   It is in arch/arm/kernel/module.h, the line:
		*(u32 *)loc += sym->st_value;
 - the unalignement comes from a relocation in section __bug_table (see [1])
   The address is 0xbf0021ea.
 - the module readelf in [2] shows the relocation in __bug_table

Do you know if other ARM platform are affected, and if an alignement of "1" is
normal for a __bug_table section (as opposed to an alignement of 4) ? And I'm
wondering how it is I have never seen that before also ...

If I have omitted some data, please tell me so that I can complete this report.

Cheers.
Russell King - ARM Linux Aug. 31, 2015, 11:46 p.m. UTC | #2
On Tue, Sep 01, 2015 at 01:00:39AM +0200, Robert Jarzmik wrote:
> [2] readelf -Sr pxa3xx_nand.ko
> ==============================
> There are 36 section headers, starting at offset 0x6a58:
> 
> Section Headers:
>   [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
>   [ 0]                   NULL            00000000 000000 000000 00      0   0  0
>   [ 1] .note.gnu.build-i NOTE            00000000 000034 000024 00   A  0   0  4
>   [ 2] .text             PROGBITS        00000000 000058 0020c4 00  AX  0   0  4
>   [ 3] .rel.text         REL             00000000 006378 0004b8 08   I 34   2  4
>   [ 4] .init.text        PROGBITS        00000000 00211c 000014 00  AX  0   0  4
>   [ 5] .rel.init.text    REL             00000000 006830 000018 08   I 34   4  4
>   [ 6] .exit.text        PROGBITS        00000000 002130 00000c 00  AX  0   0  4
>   [ 7] .rel.exit.text    REL             00000000 006848 000010 08   I 34   6  4
>   [ 8] .ARM.extab        PROGBITS        00000000 00213c 000000 00   A  0   0  1
>   [ 9] .ARM.exidx        ARM_EXIDX       00000000 00213c 0000b8 00  AL  2   0  4
>   [10] .rel.ARM.exidx    REL             00000000 006858 0000c0 08   I 34   9  4
>   [11] .rodata.str       PROGBITS        00000000 0021f4 00003e 01 AMS  0   0  1
>   [12] __bug_table       PROGBITS        00000000 002232 000018 00   A  0   0  1

This shows that the bug table has an alignment of 1, which is silly as
it contains 32-bit values - this really ought to be indicating an
alignment of 4.

I notice that a bunch of my modules are the same as well.  Try adding
".align 2" into arch/arm/include/asm/bug.h, __BUG() macro, just after
".pushsection __bug_table" which should have the effect of increasing
the alignment of the section.

It probably hasn't been noticed on ARMv6 and later because they'll
always fix up these relocations transparently.

For ARMv5 and older, you really ought to have the alignment handler
enabled - IP networking pretty much relies on this being present to
catch corner cases (eg, with TCP options mis-aligning subsequent data.)
diff mbox

Patch

===============
rj@belgarion:~/mio_linux/kernel$ arm-linux-gnueabi-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/arm-linux-gnueabi-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabi/4.9/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion=' 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,go,fortran,objc --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --enable-objc-gc --enable-multiarch --disable-sjlj-exceptions --with-arch=armv4t --with-float=soft --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabi --program-prefix=arm-linux-gnueabi-
Thread model: posix
gcc version 4.9.2 ( 4.9.2-10) 

[2] Debug patch in arch/arm/kernel/module.c
===========================================
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index efdddcb97dd1..aed935c55d63 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -88,6 +88,9 @@  apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
                        return -ENOEXEC;
                }
 
+               pr_info("%s():%d dstsec=%p dstsec->sh_addr=%p rel=%p rel->r_offset=%u\n",
+                       __func__, __LINE__, dstsec, dstsec,
+                       dstsec->sh_addr, rel, rel->r_offset);
                loc = dstsec->sh_addr + rel->r_offset;
 
                switch (ELF32_R_TYPE(rel->r_info)) {