Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s2n links static version libcrypto #2735

Open
bmildner-xt opened this issue Nov 6, 2023 · 4 comments
Open

s2n links static version libcrypto #2735

bmildner-xt opened this issue Nov 6, 2023 · 4 comments
Labels
bug This issue is a bug. Cmake Cmake related submissions p2 This is a standard priority issue

Comments

@bmildner-xt
Copy link

Describe the bug

After updating aws-sdk-cpp from version 1.9.212 to 1.11.189 we experienced very strange failures during initialization of an TLS capable HTTP server (httplib::SSLServer, https://github.com/yhirose/cpp-httplib).

What we found it that:

  1. The issue happens within a OpenSSL function (SSL_CTX_use_certificate_chain_file())
  2. It is cause by multiple copies of global data within OpenSSL (err_thread_local used as "key" to get the thread local instance of the struct OpenSSL uses to store errors)
  3. The exact location of the problem is deep within the call to PEM_read_bio_X509() from use_certificate_chain_file() in ssl_rsa.c:634. The function get_name() in pem_lib.c:745 sets a PEM_R_NO_START_LINE error to signal "end-of-file", but when use_certificate_chain_file() in ssl_rsa.c:653 checks for it, no error code is set and a "real error" is assumed (see ssl_rsa.c:658).
    This all is within one thread and in a single OpenSSL function!
    => use_certificate_chain_file() returns with error.
  4. This is apparently cause by linking both libcrypto.a and libcrypto.so
  5. Which is cause by the cmake aws-sdk-cpp targets that have PUBLIC or INTERFACE dependencies set to libcrypto.a

Workaround we currently use is to rename/delete libcrypto.a (and libssl.a) after we built OpenSSL and before building aws-sdk-cpp.
IMHO there is no (documented) build option in OpenSSL to not build the static libs ...

Callstack where PEM_R_NO_START_LINE error is set:

ERR_put_error err.c:454
get_name pem_lib.c:745
PEM_read_bio_ex pem_lib.c:926
pem_bytes_read_bio_flags pem_lib.c:247
PEM_bytes_read_bio pem_lib.c:278
PEM_ASN1_read_bio pem_oth.c:28
PEM_read_bio_X509 pem_x509.c:18
use_certificate_chain_file ssl_rsa.c:634
SSL_CTX_use_certificate_chain_file ssl_rsa.c:669
httplib::SSLServer::SSLServer httplib.cc:6084
std::make_unique<httplib::SSLServer, const char *, const char *> unique_ptr.h:1065
web_api::server::server server.cpp:175
std::make_unique<web_api::server, vau::vau_system &, const config::vau::web_api_config &> unique_ptr.h:1065
web_api_server::set_up server_test.cpp:135
...

Callstack with check for PEM_R_NO_START_LINE:

use_certificate_chain_file ssl_rsa.c:653
SSL_CTX_use_certificate_chain_file ssl_rsa.c:669
httplib::SSLServer::SSLServer httplib.cc:6084
std::make_unique<httplib::SSLServer, const char *, const char *> unique_ptr.h:1065
web_api::server::server server.cpp:175
std::make_unique<web_api::server, vau::vau_system &, const config::vau::web_api_config &> unique_ptr.h:1065
web_api_server::set_up server_test.cpp:135
...

Expected Behavior

When building aws-sdk-cpp resp. S3 and OpenSSL is used, s2n should always link libcrypto.so (if present).

Current Behavior

When building aws-sdk-cpp (resp. S3) and OpenSSL is used, s2n always links libcrypto.a (static link library) even if libcrypto.so is available on the same path and was found by FindCrypto!

Reproduction Steps

Build openssl 1.1.1w:

./config
make -j$(nproc)
make install

Build libcurl 8.4:

./configure --with-openssl=/usr/local --without-zstd
make -j$(nproc)
make install

Build S3 part of aws-sdk-cpp:

cmake .. -DBUILD_ONLY="s3" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=/usr/local/ -DCPP_STANDARD=20 -DENABLE_TESTING=OFF -GNinja -DCMAKE_PREFIX_PATH=/usr/local/
ninja -j$(nproc)
ninja install

We include the aws-sdk-cpp in our cmake projekt using this:

set(CMAKE_PREFIX_PATH /usr/local/;${CMAKE_PREFIX_PATH})
find_package(CURL REQUIRED)
find_package(AWSSDK REQUIRED COMPONENTS s3)

set(AWS_INCLUDE_DIRS "")

foreach (LIB_TARGET ${AWSSDK_LINK_LIBRARIES})
  # get the correct name of the library target
  get_target_property(LIB_LOCATION ${LIB_TARGET} LOCATION)
  set(LIB_INCLUDE_DIRS "$<TARGET_PROPERTY:${LIB_TARGET},INCLUDE_DIRECTORIES>")
  set(AWS_INCLUDE_DIRS
      "${AWS_INCLUDE_DIRS};$<$<BOOL:${LIB_INCLUDE_DIRS}>:-I$<JOIN:${LIB_INCLUDE_DIRS}, -I>>"
  )

  file(GLOB LIB_NAME CONFIGURE_DEPENDS "${LIB_LOCATION}*")
  # install all versions from this library
  install(
    PROGRAMS ${LIB_NAME}
    DESTINATION lib
    COMPONENT vau
  )
endforeach ()

# add an interface for all awssdk include dirs
add_library(awssdk_dirs INTERFACE)
target_include_directories(awssdk_dirs SYSTEM INTERFACE ${AWS_INCLUDE_DIRS})

# and an interface for the libraries (the targets)
add_library(awssdk_libs INTERFACE)
target_link_libraries(awssdk_libs INTERFACE ${AWSSDK_LINK_LIBRARIES})

# aws depends on curl
find_package(CURL REQUIRED)
file(GLOB LIB_NAME CONFIGURE_DEPENDS "${CURL_LIBRARIES}*")
# install all versions from this library
install(
  PROGRAMS ${LIB_NAME}
  DESTINATION lib
  COMPONENT vau
)

So our binaries (shared libs and executables) link "awssdk_libs".
When inspecting the compiler/linker command lines both libcrypto.a and libcrypto.so are linked!

Possible Solution

Always link shared OpenSSL libraries if found and not explicitely configured to link static versions.

Additional Information/Context

openssl 1.1.1w
libcurl 8.4
aws-sdk-cpp 1.11.189
cpp-httplib 0.14.1
boost 1.80
fmt 9.1.0
nlohmann json 3.11.2
range-v3 0.12.0
spdlog 1.11.0
and some more libs

cmake 3.24.3

So libcrypto is at least used in our software via:

  • aws-sdk-cpp: (IMHO via s2n and libcurl)
  • cpp-httplib: HTTPS server and HTTPS client
    We also have code that uses functions from libcrypto directly.

We build all our code with visibility=hidden, "position independent code" on, C++20

AWS CPP SDK version used

1.11.189

Compiler and Version used

gcc 12.2.1 (Red Hat 12.2.1-7)

Operating System and version

RHEL 8.8

@bmildner-xt bmildner-xt added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Nov 6, 2023
@jmklix jmklix self-assigned this Nov 8, 2023
@jmklix jmklix added investigating This issue is being investigated and/or work is in progress to resolve the issue. p2 This is a standard priority issue Cmake Cmake related submissions and removed needs-triage This issue or PR still needs to be triaged. labels Nov 14, 2023
@jmklix
Copy link
Member

jmklix commented Nov 14, 2023

We have make some cmake changes from v1.9 to v1.11 so that might be what is causing this error that you are seeing. Looking into this, but you can follow the tracking issue here: #1888

@bmildner-xt
Copy link
Author

Thanks for looking into this!

BTW:
I notices that with aws-sdk-cpp 1.9.212 there is also something off around FindCrypto ...
Maybe 1.9.212 was also linking the static version of libcrypto but (due to another bug?) always found the dynamic (.so) and not the static (.a) library? (see LibCrypto Static Lib: /usr/local/lib64/libcrypto.so below)

-- Found AWS SDK for C++, Version: 1.9.212, Install Root:/usr/local, Platform Prefix:, Platform Dependent Libraries: pthread;crypto;ssl;z;curl
-- Components specified for AWSSDK: s3, application will be depending on libs: aws-cpp-sdk-s3;aws-cpp-sdk-core
-- Try finding aws-cpp-sdk-core
-- LibCrypto Include Dir: /usr/local/include
-- LibCrypto Shared Lib:  /usr/local/lib64/libcrypto.so
-- LibCrypto Static Lib:  /usr/local/lib64/libcrypto.so

@jmklix jmklix removed the investigating This issue is being investigated and/or work is in progress to resolve the issue. label Apr 3, 2024
@jmklix jmklix removed their assignment Apr 3, 2024
@sbiscigl
Copy link
Contributor

sbiscigl commented Jun 4, 2024

I notices that with aws-sdk-cpp 1.9.212 there is also something off around FindCrypto ...

We removed finding libcryto all together in a recent release, can you please confirm if this is still a problem? I tried building off of main using the implicit BUILD_SHARED_LIBS=ON by default and im seeing it working as expected

cmake build commands:

cmake3 -DCMAKE_BUILD_TYPE=Debug -DBUILD_ONLY="s3" -DCMAKE_INSTALL_PREFIX="~/test-install" ..
cmake --build .
cmake3 --install .

looking at the installed binary i see it linking against a shared libcrypto:

$ldd ~/test-install/lib64/libs2n.so
	linux-vdso.so.1 (0x00007ffe2793b000)
	libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007ff343e4e000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007ff343c4a000)
	librt.so.1 => /lib64/librt.so.1 (0x00007ff343a42000)
	libm.so.6 => /lib64/libm.so.6 (0x00007ff343702000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ff3434e4000)
	libc.so.6 => /lib64/libc.so.6 (0x00007ff343137000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ff34465d000)
	libz.so.1 => /lib64/libz.so.1 (0x00007ff342f22000)

so interested if you are still seeing this

@bmildner-xt
Copy link
Author

Thanks for looking into this!

Unfortunately the project i ran into this issue with, is no longer active and so i can not check with a recent release!
Sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. Cmake Cmake related submissions p2 This is a standard priority issue
Projects
None yet
Development

No branches or pull requests

3 participants