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