BusyBox 1.36.0 regression: Segfaults on i386 musl libc

Natanael Copa ncopa at alpinelinux.org
Tue Jan 10 12:11:12 UTC 2023


On Sun, 08 Jan 2023 20:22:31 +0100
Sören Tempel <soeren at soeren-tempel.net> wrote:

> Investigated this further. The problem is a text relocation created by
> the hash_md5_sha256_x86-32_shaNI.S file. When compiling BusyBox with
> LDFLAGS=-Wl,-z,text one is warned about the following relocation by gcc:
> 
> 	/usr/lib/gcc/i586-alpine-linux-musl/12.2.1/../../../../i586-alpine-linux-musl/bin/ld: libbb/lib.a(hash_md5_sha_x86-32_shaNI.o): warning: relocation in read-only section `.text.sha1_process_block64_shaNI'
> 	/usr/lib/gcc/i586-alpine-linux-musl/12.2.1/../../../../i586-alpine-linux-musl/bin/ld: read-only segment has dynamic relocations
> 

Also scanelf confirms that there are textrels in 3 places:

$ scanelf --textrels busybox_unstripped
 TYPE   TEXTRELS FILE 
  busybox_unstripped: (memory/data?) [r_offset=0x816E] r_type=8 in (optimized out: previous sha256_process_block64_shaNI) [closest_prev_sym=0x8158]
  busybox_unstripped: (memory/data?) [r_offset=0x8173] r_type=8 in (optimized out: previous sha256_process_block64_shaNI) [closest_prev_sym=0x8158]
  busybox_unstripped: (memory/data?) [r_offset=0x8415] r_type=8 in (optimized out: previous sha1_process_block64_shaNI) [closest_prev_sym=0x8400]
ET_DYN  busybox_unstripped 

> The Linux Kernel, from which the assembly was copied, does addressing
> relative to the %pic register to avoid this relocation it seems [1]:
> 
> 	movdqa PSHUFFLE_BYTE_FLIP_MASK(%rip), SHUF_MASK
> 
> However, the %rip register is AFAIK not available for i386 and since I
> am personally not an x86 wizard I have no idea how to best rewrite this
> code in a way that it doesn't require dynamic relocations.

For sha1 we can (ab)use the stack for the PSHUFFLE_BYTE_FLIP_MASK data when we do position independent code (PIC):

diff --git a/libbb/hash_md5_sha_x86-32_shaNI.S b/libbb/hash_md5_sha_x86-32_shaNI.S
index 7455a29f0..4c3d1ea88 100644
--- a/libbb/hash_md5_sha_x86-32_shaNI.S
+++ b/libbb/hash_md5_sha_x86-32_shaNI.S
@@ -49,7 +49,16 @@ sha1_process_block64_shaNI:
        pinsrd          $3, 76+4*4(%eax), E0    # load to uppermost 32-bit word
        shuf128_32      $0x1B, ABCD, ABCD       # DCBA -> ABCD
 
+#ifdef __PIC__
+       pushl   0x0c0d0e0f
+       pushl   0x08090a0b
+       pushl   0x04050607
+       pushl   0x00010203
+       mova128 (%esp), %xmm7
+       addl    16, %esp
+#else
        mova128         PSHUFFLE_BYTE_FLIP_MASK, %xmm7
+#endif
 
        movu128         0*16(%eax), MSG0
        pshufb          %xmm7, MSG0
@@ -225,10 +234,11 @@ sha1_process_block64_shaNI:
 
        ret
        .size   sha1_process_block64_shaNI, .-sha1_process_block64_shaNI
-
+#ifndef __PIC__
        .section        .rodata.cst16.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 16
        .balign 16
 PSHUFFLE_BYTE_FLIP_MASK:
        .octa   0x000102030405060708090a0b0c0d0e0f
+#endif
 
 #endif


But for the $K256 data we'd need use the global offset table. Not sure exactly how to do that.
> 
> [1]: https://github.com/torvalds/linux/blob/94a855111ed9106971ca2617c5d075269e6aefde/arch/x86/crypto/sha1_ni_asm.S#L112
> 
> Sören Tempel <soeren at soeren-tempel.net> wrote:
> > Hello,
> > 
> > Natanael Copa <ncopa at alpinelinux.org> wrote:  
> > > diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
> > > index 880ffab01..d2351d3e6 100644
> > > --- a/libbb/hash_md5_sha.c
> > > +++ b/libbb/hash_md5_sha.c
> > > @@ -17,8 +17,11 @@
> > >  # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
> > >  static void cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
> > >  {
> > > -       asm ("cpuid"
> > > -               : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
> > > +       asm volatile (
> > > +               "mov %%ebx, %%esi;" /* save %ebx PIC register */
> > > +               "cpuid;"
> > > +               "xchg %%ebx, %%esi;"
> > > +               : "=a"(*eax), "=S"(*ebx), "=c"(*ecx), "=d"(*edx)
> > >                 : "0"(*eax),  "1"(*ebx),  "2"(*ecx),  "3"(*edx)
> > >         );
> > >  }  
> > 
> > Unfortunately, this does not fix the segfault. Since the segfault occurs
> > in musl's dynamic loader I also don't think that this code is
> > reached/executed. Instead, this seems to be a problem with the symbols
> > of the provided assembly file.
> > 
> > I am currently debugging this on a96ccbefe417aaac6a2ce59c788e01fc0f83902f.
> > If I remove the PSHUFFLE_BYTE_FLIP_MASK definition (and the instruction
> > using it) in hash_md5_sha256_x86-32_shaNI.S from the checkout for this
> > commit then the segfault doesn't occur. So this does definitely seem to
> > be a problem with the hash_md5_sha256_x86-32_shaNI.S assembly file...
> > 
> > Greetings,
> > Sören
> > _______________________________________________
> > busybox mailing list
> > busybox at busybox.net
> > http://lists.busybox.net/mailman/listinfo/busybox  



More information about the busybox mailing list