s390/module: fix rela calculation for R_390_GOTENT
authorSumanth Korikkar <sumanthk@linux.ibm.com>
Mon, 5 Jun 2023 07:55:27 +0000 (09:55 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Tue, 20 Jun 2023 17:55:00 +0000 (19:55 +0200)
During  module load, module layout allocation occurs by initially
allowing the architecture to frob the sections. This is performed via
module_frob_arch_sections().

However, the size of each module memory types like text,data,rodata etc
are updated correctly only after layout_sections().

After calculation of required module memory sizes for each types,
move_module() is responsible for allocating the module memory for each
type from modules vaddr range.

Considering the sequence above, module_frob_arch_sections() updates the
module mod_arch_specific got_offset before module memory text type size
is fully updated in layout_sections().  Hence mod_arch_specific
got_offset points to currently zero.

As per s390 ABI,
R_390_GOTENT :  (G + O + A - P) >> 1
where
G=me->mem[MOD_TEXT].base+me->arch.got_offset
O=info->got_offset
A=rela->r_addend
P=loc

fix R_390_GOTENT calculation in apply_rela().

Note: currently this doesn't break anything because me->arch.got_offset
is zero.  However, reordering of functions in the future could break it.

Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/kernel/module.c

index f1b35dc..42215f9 100644 (file)
@@ -352,7 +352,8 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
                        rc = apply_rela_bits(loc, val, 0, 64, 0, write);
                else if (r_type == R_390_GOTENT ||
                         r_type == R_390_GOTPLTENT) {
-                       val += (Elf_Addr) me->mem[MOD_TEXT].base - loc;
+                       val += (Elf_Addr)me->mem[MOD_TEXT].base +
+                               me->arch.got_offset - loc;
                        rc = apply_rela_bits(loc, val, 1, 32, 1, write);
                }
                break;