SIGILL crash in Mirage_crypto_pk.Rsa.generate

when building a static binary on my development machine with a rather fresh switch and copying the binary to a 2nd machine I get a crashing binary. The minimum program is

let () =
  Mirage_crypto_rng_lwt.initialize (module Mirage_crypto_rng.Fortuna);
  let _ = Mirage_crypto_pk.Rsa.generate ~bits:2048 () in
  ()

switch and os is

$ opam switch | fgrep →
→  4.11.2+musl+static+flambda  ocaml-variants.4.11.2+musl+static+flambda  4.11.2+musl+static+flambda
$ uname -sm
Linux x86_64
$ dune --version
3.7.1
$ musl-gcc --version
x86_64-linux-gnu-gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

When building on that 2nd machine from older opam packages things work on both. @hannes how could I narrow this down further?

P.S.: the ‘old’ machine:

$ opam switch | fgrep →
→  4.11.2+musl+static+flambda  ocaml-variants.4.11.2+musl+static+flambda  4.11.2+musl+static+flambda
$ uname -sm
Linux x86_64
$ dune --version
3.7.1
$ musl-gcc --version
cc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Perhaps the library is using a specialized cryptographic instruction that is not available on your “old” machine.
Can you try getting the location of the crash with gdb or lldb ?

$ gdb ./a.out
(gdb) run
(gdb) f
1 Like
$ gdb /tmp/seppo_bin.exe
(gdb) run -V
Starting program: /tmp/seppo_bin.exe -V
[Detaching after fork from child process 4176]

Program received signal SIGILL, Illegal instruction.
0x000000000087fda6 in __gmpn_sqr_basecase ()
(gdb) backtrace 
#0  0x000000000087fda6 in __gmpn_sqr_basecase ()
#1  0x00007fffffffcd20 in ?? ()
#2  0x000000000087edf5 in __gmpn_sqr ()
#3  0x000000000089e8c5 in __gmpn_powm ()
#4  0x00000000008792c6 in __gmpz_powm ()
#5  0x00000000008a3b3f in millerrabin ()
#6  0x00000000008a3e20 in __gmpz_millerrabin ()
#7  0x0000000000879044 in __gmpz_nextprime ()
#8  0x0000000000874571 in ml_z_nextprime ()
#9  0x00000000006cf3e6 in camlMirage_crypto_pk__Z_extra__prime_inner_780 () at pk/z_extra.ml:116
#10 0x00000000006d19e4 in camlMirage_crypto_pk__Rsa__generate_inner_1604 () at pk/rsa.ml:183
#11 0x0000000000407ef1 in camlDune__exe__Seppo_bin__entry () at bin/seppo_bin.ml:31
#12 0x0000000000402db9 in caml_program ()
#13 0x00000000008f0294 in caml_start_program ()
#14 0x00000000008cecbc in caml_startup_common (argv=0x7fffffffe938, pooling=<optimized out>, pooling@entry=0) at startup_nat.c:165
#15 0x00000000008ced3f in caml_startup_exn (argv=<optimized out>) at startup_nat.c:172
#16 caml_startup (argv=<optimized out>) at startup_nat.c:177
#17 caml_main (argv=<optimized out>) at startup_nat.c:184
#18 0x00000000004010c2 in main (argc=<optimized out>, argv=<optimized out>) at main.c:44
(gdb) 

P.S.: I build zarith/gmp like this seppo/zarith-musl.sh at ma - seppo - Codeberg.org

Try compiling your libgmp with the --enable-fat option so that it dynamically detects CPU options at runtime, and not at buildtime. Build Options (GNU MP 6.2.1)

1 Like

Thanks for your report. So, where does “libgmp” come from? Is it dynamically or statically linked (a ldd <my-binary> should have it dynamically linked, i.e. one line of output should be /lib/libgmp.so.10).

And libgmp should be provided by your host system package repository – do you have any idea which configuration flags they used for producing that artifact?

my host system package repo is devuan (debian) and comes with a libgmp with a glibc dependency - so the musl static build toolchain needs it’s own.

libgmp is a dependency of opam - zarith

Built here: seppo/zarith-musl.sh at ma - seppo - Codeberg.org

P.S.: opened a ticket to follow the history. #2 - SIGILL crash in Mirage_crypto_pk.Rsa.generate - seppo - Codeberg.org

Thanks for your information. Indeed gmp is a dependency of zarith, which is used by mirage-crypto-pk.

Your build script for gmp should, as @avsm mention, include --enable-fat in the configure - then it’ll defer to run-time CPU feature detection.

awesome, thanks a lot, works great: build cpu-independant binaries. · d87448d4df - seppo - Codeberg.org