herumi / mcl

a portable and fast pairing-based cryptography library
BSD 3-Clause "New" or "Revised" License
450 stars 151 forks source link

Segmentation fault when build by gcc and link with libmclbn256.so #172

Closed levyfan closed 1 year ago

levyfan commented 1 year ago

Hi, I meet segmentation fault when building my application by gcc and link with libmclbn256.so (mcl is build and installed to /usr/local/lib by clang). But if I build with clang++, it runs fine. I checked the stack and it crash at memset.

Program received signal SIGSEGV, Segmentation fault.
__memset_generic () at ../sysdeps/aarch64/memset.S:127
127 ../sysdeps/aarch64/memset.S: No such file or directory.
(gdb) where
#0  __memset_generic () at ../sysdeps/aarch64/memset.S:127
#1  0x0000aaaad3f8f180 in void mcl::FpT<mcl::bn::local::FrTag, 256ul>::setArrayMask<unsigned long>(unsigned long const*, unsigned long) ()
#2  0x0000aaaad3f87494 in mcl::FpT<mcl::bn::local::FrTag, 256ul>::setByCSPRNG(bool*, mcl::fp::RandGen) ()
#3  0x0000aaaad3f7c5b8 in mcl::FpT<mcl::bn::local::FrTag, 256ul>::setByCSPRNG(mcl::fp::RandGen) ()
#4  0x0000aaaad3f77774 in SecureID::SecretKey::generate() ()
#5  0x0000aaaad3f77a40 in SecureIDTest::SetUp() ()
#6  0x0000aaaad3fd2384 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#7  0x0000000000000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Do you have any ideas?

herumi commented 1 year ago

Please show me the build options to build mcl, compiler options to build your application, your code (including initializing options of mcl), and other information.

The following commands to use gcc for application and use clang for library run well on my environment (Ubuntu 22.04 LTS g++11 and clang++-14)

make clean
make lib/libmcl.a lib/libmclbn256.so -j CXX=clang++-14
make bin/bn_c256_test.exe CXX=g++ -j
bin/bn_c256_test.exe
levyfan commented 1 year ago

Build mcl by clang++:

root@35459638247c:/home/mcl/build# cmake -DCMAKE_CXX_COMPILER=clang++ ..
-- The CXX compiler identification is Clang 14.0.0
-- The C compiler identification is GNU 11.3.0
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
bint_obj=/home/mcl/build/bint64.o
base_obj=/home/mcl/build/base64.o
-- Found GMP: /usr/include/aarch64-linux-gnu  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mcl/build
root@35459638247c:/home/mcl/build# make
[  7%] Generating base64.o
warning: overriding the module target triple with aarch64-unknown-linux-gnu [-Woverride-module]
1 warning generated.
[  7%] Built target gen_base.o
[ 14%] Generating bint64.o
warning: overriding the module target triple with aarch64-unknown-linux-gnu [-Woverride-module]
1 warning generated.
[ 14%] Built target gen_bint.o
[ 21%] Building CXX object CMakeFiles/mcl.dir/src/fp.cpp.o
[ 28%] Linking CXX shared library lib/libmcl.so
[ 28%] Built target mcl
[ 35%] Building CXX object CMakeFiles/mcl_st.dir/src/fp.cpp.o
[ 42%] Linking CXX static library lib/libmcl.a
[ 57%] Built target mcl_st
[ 64%] Building CXX object CMakeFiles/mclbn256.dir/src/bn_c256.cpp.o
[ 71%] Linking CXX shared library lib/libmclbn256.so
[ 71%] Built target mclbn256
[ 78%] Building CXX object CMakeFiles/mclbn384.dir/src/bn_c384.cpp.o
[ 85%] Linking CXX shared library lib/libmclbn384.so
[ 85%] Built target mclbn384
[ 92%] Building CXX object CMakeFiles/mclbn384_256.dir/src/bn_c384_256.cpp.o
[100%] Linking CXX shared library lib/libmclbn384_256.so
[100%] Built target mclbn384_256
root@35459638247c:/home/mcl/build# 
root@35459638247c:/home/mcl/build# make install
[  7%] Built target gen_base.o
[ 14%] Built target gen_bint.o
Consolidate compiler generated dependencies of target mcl
[ 28%] Built target mcl
Consolidate compiler generated dependencies of target mcl_st
[ 57%] Built target mcl_st
Consolidate compiler generated dependencies of target mclbn256
[ 71%] Built target mclbn256
Consolidate compiler generated dependencies of target mclbn384
[ 85%] Built target mclbn384
Consolidate compiler generated dependencies of target mclbn384_256
[100%] Built target mclbn384_256
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libmcl.so.1.74
-- Up-to-date: /usr/local/lib/libmcl.so.1
-- Up-to-date: /usr/local/lib/libmcl.so
-- Installing: /usr/local/lib/libmcl.a
-- Installing: /usr/local/lib/libmclbn256.so.1.74
-- Up-to-date: /usr/local/lib/libmclbn256.so.1
-- Set runtime path of "/usr/local/lib/libmclbn256.so.1.74" to ""
-- Up-to-date: /usr/local/lib/libmclbn256.so
-- Installing: /usr/local/lib/libmclbn384.so.1.74
-- Up-to-date: /usr/local/lib/libmclbn384.so.1
-- Set runtime path of "/usr/local/lib/libmclbn384.so.1.74" to ""
-- Up-to-date: /usr/local/lib/libmclbn384.so
-- Installing: /usr/local/lib/libmclbn384_256.so.1.74
-- Up-to-date: /usr/local/lib/libmclbn384_256.so.1
-- Set runtime path of "/usr/local/lib/libmclbn384_256.so.1.74" to ""
-- Up-to-date: /usr/local/lib/libmclbn384_256.so
-- Up-to-date: /usr/local/include/mcl
-- Up-to-date: /usr/local/include/mcl/bn256.hpp
-- Up-to-date: /usr/local/include/mcl/bn_c384.h
-- Up-to-date: /usr/local/include/mcl/fp_tower.hpp
-- Up-to-date: /usr/local/include/mcl/ecdsa.hpp
-- Up-to-date: /usr/local/include/mcl/aggregate_sig.hpp
-- Up-to-date: /usr/local/include/mcl/bint_proto.hpp
-- Up-to-date: /usr/local/include/mcl/lagrange.hpp
-- Up-to-date: /usr/local/include/mcl/ec.hpp
-- Up-to-date: /usr/local/include/mcl/paillier.hpp
-- Up-to-date: /usr/local/include/mcl/bn384.hpp
-- Up-to-date: /usr/local/include/mcl/bls12_381.hpp
-- Up-to-date: /usr/local/include/mcl/array.hpp
-- Up-to-date: /usr/local/include/mcl/conversion.hpp
-- Up-to-date: /usr/local/include/mcl/vint.hpp
-- Up-to-date: /usr/local/include/mcl/impl
-- Up-to-date: /usr/local/include/mcl/impl/bn_c_impl.hpp
-- Up-to-date: /usr/local/include/mcl/elgamal.hpp
-- Up-to-date: /usr/local/include/mcl/window_method.hpp
-- Up-to-date: /usr/local/include/mcl/bn.hpp
-- Up-to-date: /usr/local/include/mcl/she.hpp
-- Up-to-date: /usr/local/include/mcl/bn.h
-- Up-to-date: /usr/local/include/mcl/curve_type.h
-- Up-to-date: /usr/local/include/mcl/bint.hpp
-- Up-to-date: /usr/local/include/mcl/operator.hpp
-- Up-to-date: /usr/local/include/mcl/util.hpp
-- Up-to-date: /usr/local/include/mcl/randgen.hpp
-- Up-to-date: /usr/local/include/mcl/bn_c384_256.h
-- Up-to-date: /usr/local/include/mcl/op.hpp
-- Up-to-date: /usr/local/include/mcl/bn_c256.h
-- Up-to-date: /usr/local/include/mcl/fp.hpp
-- Up-to-date: /usr/local/include/mcl/ecparam.hpp
-- Up-to-date: /usr/local/include/mcl/bn512.hpp
-- Up-to-date: /usr/local/include/mcl/gmp_util.hpp
-- Up-to-date: /usr/local/include/mcl/mapto_wb19.hpp
-- Up-to-date: /usr/local/include/mcl/config.hpp
-- Up-to-date: /usr/local/include/cybozu
-- Up-to-date: /usr/local/include/cybozu/critical_section.hpp
-- Up-to-date: /usr/local/include/cybozu/time.hpp
-- Up-to-date: /usr/local/include/cybozu/option.hpp
-- Up-to-date: /usr/local/include/cybozu/endian.hpp
-- Up-to-date: /usr/local/include/cybozu/sha2.hpp
-- Up-to-date: /usr/local/include/cybozu/random_generator.hpp
-- Up-to-date: /usr/local/include/cybozu/array.hpp
-- Up-to-date: /usr/local/include/cybozu/crypto.hpp
-- Up-to-date: /usr/local/include/cybozu/link_mpir.hpp
-- Up-to-date: /usr/local/include/cybozu/mutex.hpp
-- Up-to-date: /usr/local/include/cybozu/file.hpp
-- Up-to-date: /usr/local/include/cybozu/link_ssleay32.hpp
-- Up-to-date: /usr/local/include/cybozu/stream.hpp
-- Up-to-date: /usr/local/include/cybozu/benchmark.hpp
-- Up-to-date: /usr/local/include/cybozu/test.hpp
-- Up-to-date: /usr/local/include/cybozu/unordered_map.hpp
-- Up-to-date: /usr/local/include/cybozu/xorshift.hpp
-- Up-to-date: /usr/local/include/cybozu/atomic.hpp
-- Up-to-date: /usr/local/include/cybozu/link_libeay32.hpp
-- Up-to-date: /usr/local/include/cybozu/exception.hpp
-- Up-to-date: /usr/local/include/cybozu/bit_operation.hpp
-- Up-to-date: /usr/local/include/cybozu/itoa.hpp
-- Up-to-date: /usr/local/include/cybozu/socket.hpp
-- Up-to-date: /usr/local/include/cybozu/hash.hpp
-- Up-to-date: /usr/local/include/cybozu/inttype.hpp
-- Up-to-date: /usr/local/include/cybozu/serializer.hpp
-- Up-to-date: /usr/local/include/cybozu/atoi.hpp
-- Installing: /usr/local/lib/cmake/mcl/mclTargets.cmake
-- Installing: /usr/local/lib/cmake/mcl/mclTargets-noconfig.cmake

Build my application by gcc:

root@35459638247c:/home/SecureID/build# cmake ..
-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found mcl: /usr/local/lib/libmcl.so  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/SecureID/build
root@35459638247c:/home/SecureID/build# make
[ 10%] Creating directories for 'googletest'
[ 20%] Performing download step (git clone) for 'googletest'
Cloning into 'googletest'...
HEAD is now at 58d77fa Updates the version number in CMakeLists.txt to 1.12.1 (#3919)
[ 30%] Performing update step for 'googletest'
[ 40%] No patch step for 'googletest'
[ 50%] Performing configure step for 'googletest'
loading initial cache file /home/SecureID/build/googletest/tmp/googletest-cache-.cmake
-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python: /usr/bin/python3.10 (found version "3.10.6") found components: Interpreter 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/SecureID/build/googletest/src/googletest
[ 60%] Performing build step for 'googletest'
[ 25%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 50%] Linking CXX static library ../lib/libgtest.a
[ 50%] Built target gtest
[ 75%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[100%] Linking CXX static library ../lib/libgtest_main.a
[100%] Built target gtest_main
[ 70%] No install step for 'googletest'
[ 80%] Completed 'googletest'
[ 80%] Built target googletest
[ 90%] Building CXX object CMakeFiles/SecureID_test.dir/secure_id_test.cpp.o
In file included from /home/SecureID/secure_id_test.cpp:2:
/home/SecureID/secure_id.hpp:20:5: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
   20 |     inline Init _init;
      |     ^~~~~~
[100%] Linking CXX executable SecureID_test
[100%] Built target SecureID_test
root@35459638247c:/home/SecureID/build# make test
Running tests...
Test project /home/SecureID/build
    Start 1: UnitTest
1/1 Test #1: UnitTest .........................***Exception: SegFault  0.01 sec

0% tests passed, 1 tests failed out of 1

Total Test time (real) =   0.01 sec

The following tests FAILED:
      1 - UnitTest (SEGFAULT)
Errors while running CTest
Output from these tests are in: /home/SecureID/build/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
make: *** [Makefile:71: test] Error 8

My code here: https://github.com/levyfan/SecureID/blob/main/secure_id_test.cpp and the init take place at https://github.com/levyfan/SecureID/blob/b0940af73c2a58b296083e7b567672fbc09a7d0c/secure_id.hpp#L9

If I build my application by -DCMAKE_CXX_COMPILER=clang++, that is ok.

herumi commented 1 year ago

Could you please simplify your code so that my research time is less?

https://github.com/levyfan/SecureID/blob/b0940af73c2a58b296083e7b567672fbc09a7d0c/secure_id_test.cpp#L39

This is a bad cast. Use 'x = 123;'. cf. https://github.com/herumi/mcl/blob/master/api.md#set-x-to-y

levyfan commented 1 year ago

The crash happens at secret_key = SecureID::SecretKey::generate(); in Setup https://github.com/levyfan/SecureID/blob/b0940af73c2a58b296083e7b567672fbc09a7d0c/secure_id_test.cpp#L7

and that calls into sk.setByCSPRNG(); at here https://github.com/levyfan/SecureID/blob/b0940af73c2a58b296083e7b567672fbc09a7d0c/secure_id.hpp#L45

levyfan commented 1 year ago

Simplify the code as this:

class SecureIDTest : public ::testing::Test {
protected:
    void SetUp() override {
        mcl::bn::Fr fr;
        fr.setByCSPRNG();

        secret_key = SecureID::SecretKey::generate();
        public_key = secret_key.public_key();
    }

    void TearDown() override {
    }

    SecureID::SecretKey secret_key;
    SecureID::PublicKey public_key;
};

And it crash at fr.setByCSPRNG();

Program received signal SIGSEGV, Segmentation fault.
__memset_generic () at ../sysdeps/aarch64/memset.S:127
127 ../sysdeps/aarch64/memset.S: No such file or directory.
(gdb) where
#0  __memset_generic () at ../sysdeps/aarch64/memset.S:127
#1  0x0000aaaae2a5f19c in void mcl::FpT<mcl::bn::local::FrTag, 256ul>::setArrayMask<unsigned long>(unsigned long const*, unsigned long) ()
#2  0x0000aaaae2a574b0 in mcl::FpT<mcl::bn::local::FrTag, 256ul>::setByCSPRNG(bool*, mcl::fp::RandGen) ()
#3  0x0000aaaae2a4c5d4 in mcl::FpT<mcl::bn::local::FrTag, 256ul>::setByCSPRNG(mcl::fp::RandGen) ()
#4  0x0000aaaae2a47a48 in SecureIDTest::SetUp() ()
#5  0x0000aaaae2aa43a4 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#6  0x0000000000000000 in ?? ()
herumi commented 1 year ago

C++ interface requires only libmcl.a. libmclbn256.so is not necessary.

The code is not simplified yet. Please don't use your class and the other library.

Does

#include <mcl/bn256.hpp>
int main()
{
   mcl::bn::initPairing();
   mcl::bn:: fr;
   fr.setByCSPRNG();
  ...
}

reproduce the bug?

levyfan commented 1 year ago

It seems googletest will cause the problem. Any writing below is OK.

#include <mcl/bn256.hpp>
#include "secure_id.hpp"
#include <iostream>

class CLS1 {
public:
    mcl::bn::Fr fr;
};

class CLS2 : public mcl::bn::Fr {
public:
    static CLS2 generate() {
        CLS2 cls2;
        cls2.setByCSPRNG();
        return cls2;
    }
};

class CLS5 {
public:
    SecureID::SecretKey secret_key;

    void SetUp() {
        secret_key = SecureID::SecretKey::generate();
    }
};

int main() {
    mcl::bn::initPairing();

    mcl::bn::Fr fr;
    fr.setByCSPRNG();
    std::cout << "hello0" << std::endl;

    CLS1 cls1;
    cls1.fr.setByCSPRNG();
    std::cout << "hello1" << std::endl;

    CLS2 cls2;
    cls2.setByCSPRNG();
    std::cout << "hello2" << std::endl;

    CLS2 cls3 = CLS2::generate();
    std::cout << "hello3" << std::endl;

    SecureID::SecretKey secret_key = SecureID::SecretKey::generate();
    std::cout << "hello4" << std::endl;

    CLS5 cls5;
    cls5.SetUp();
    std::cout << "hello5" << std::endl;
}
levyfan commented 1 year ago

I create a test repo https://github.com/levyfan/mcl_test to reproduce this crash. You can have a look at the docker file https://github.com/levyfan/mcl_test/blob/master/devel.Dockerfile or the GitHub workflow https://github.com/levyfan/mcl_test/actions/runs/3762329828/jobs/6394924861

main.cpp is OK and mcl_googletest.cpp will crash.

levyfan commented 1 year ago

Finally find that this code will reproduce the crash, @herumi could you have a look?

#include <mcl/bn256.hpp>
#include <iostream>

namespace XXX {

    class Init {
    public:
        Init() {
            std::cerr << "Init constructor" << std::endl;
            mcl::bn::initPairing();
            std::cerr << "Init end" << std::endl;
        }
    };

    inline Init _init;

}

int main() {
    std::cerr << "main" << std::endl;
//    mcl::bn::initPairing();

    mcl::bn::Fr fr;
    fr.setByCSPRNG();
    std::cout << "hello0" << std::endl;

    return 0;
}

the output is:

Init constructor
Init end
main
Segmentation fault

I have uploaded this to https://github.com/levyfan/mcl_test

herumi commented 1 year ago

Thank you for the minimum code. The phenomenon was reproduced. The reason is the implementation-dependent order of initialization of static variables in C++. I'll find out how to fix it.

herumi commented 1 year ago

I've controlled the order of static variables to pass static_init_test.cpp at v1.76. Could you try it?

levyfan commented 1 year ago

That works! Thanks