openssl: fix the data race when sharing an SSL session between threads

The SSL_Session object is mutated during connection inside openssl,
and it might not be thread-safe. Besides, according to documentation
of openssl:

```
SSL_SESSION objects keep internal link information about the session
cache list, when being inserted into one SSL_CTX object's session
cache. One SSL_SESSION object, regardless of its reference count,
must therefore only be used with one SSL_CTX object (and the SSL
objects created from this SSL_CTX object).
```
If I understand correctly, it is not safe to share it even in a
single thread.

Instead, serialize the SSL_SESSION before adding it to the cache,
and deserialize it after retrieving it from the cache, so that no
concurrent write to the same object is infeasible.

Also
 - add a ci test for thread sanitizer
 - add a test for sharing ssl sessions concurrently
 - avoid redefining memory functions when not building libcurl, but
   including the soruce in libtest
 - increase the concurrent connections limit in sws

Notice that there are fix for a global data race for openssl which
is not yet release. The fix is cherry pick for the ci test with
thread sanitizer.
d8def79838

Closes #14751
This commit is contained in:
Aki 2024-08-31 11:48:18 +08:00 committed by Daniel Stenberg
parent 2c2292ecaf
commit a2bcec0ee0
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
9 changed files with 499 additions and 22 deletions

View file

@ -149,6 +149,16 @@ jobs:
--with-openssl --enable-debug --enable-websockets
singleuse: --unit
- name: thread-sanitizer
install_packages: zlib1g-dev clang libtsan2
install_steps: pytest openssltsan3
configure: >
CC=clang
CFLAGS="-fsanitize=thread -g"
LDFLAGS="-fsanitize=thread -Wl,-rpath,$HOME/openssl3/lib"
--with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
singleuse: --unit
- name: memory-sanitizer
install_packages: clang
install_steps:
@ -310,6 +320,28 @@ jobs:
./config --prefix=$HOME/openssl3 --libdir=lib
make -j1 install_sw
- name: cache openssltsan3
if: contains(matrix.build.install_steps, 'openssltsan3')
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
id: cache-openssltsan3
env:
cache-name: cache-openssltsan3
with:
path: /home/runner/openssl3
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.openssl3-version }}-d8def798
- name: 'install openssltsan3'
if: contains(matrix.build.install_steps, 'openssltsan3') && steps.cache-openssltsan3.outputs.cache-hit != 'true'
# There are global data race in openssl:
# Cherry-Pick the fix for testing https://github.com/openssl/openssl/pull/24782
run: |
git clone --quiet --depth=1 -b ${{ env.openssl3-version }} https://github.com/openssl/openssl
cd openssl
git fetch --quiet --depth=2 origin d8def79838cd0d5e7c21d217aa26edb5229f0ab4
git cherry-pick -n d8def79838cd0d5e7c21d217aa26edb5229f0ab4
CC="clang" CFLAGS="-fsanitize=thread" LDFLAGS="-fsanitize=thread" ./config --prefix=$HOME/openssl3 --libdir=lib
make -j1 install_sw
- name: cache quictls
if: contains(matrix.build.install_steps, 'quictls')
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4