### Description
References: #3635

Early initialization of tls in OpenSSL 3 in rank 0 results in the use of shared 
state (pointers to the same shared memory location). Note: this is not related 
to shared memory allocation contention as this protected by a 
(multi-process)futex. Under heavy traffic the workers will corrupt each others 
state (race condition).  This is only visible under heavy loading and is the 
reason for the intermittent appearance in #3635.

Ping @miconda 
https://github.com/kamailio/kamailio/commit/1a9b0b63617afebcee2aecb3b2240d7684ecabc2
Since qm/fm are already protected by a multi-process futex this commit is 
redundant (it puts a pthread mutex around the futex). I have been able to 
reproduce OpenSSL 3 crashes with heavy loading with this commit.

Example of shared object is the error state (SSL_get_error). It should be per 
worker but 

```
CRITICAL: <core> [core/mem/q_malloc.c:555]: qm_free(): BUG: freeing already 
freed pointer (0x7f1d7f9c77b0), called from tls: tls_init.c: ser_free(535), 
first free tls: tls_init.c: ser_free(535) - ignoring
```

shows that multiple workers are accessing the same object (in OpenSSL this is 
`ERR_STATE *`).

### Troubleshooting
N/A

#### Reproduction
* create heaving loading of TLS clients
* observe shm logging errors


#### Debugging Data

Dump `ERR_STATE *` from two different processes: observe that these are 
identical meaning both workers are using the same struct. 
```
# !!!!IMPORTANT!!!! 2 == OpenSSL thread local key for ERR_STATE *
(gdb) p err_thread_local
$3 = 2

# this is worker 1, process_no 7
Reading symbols from /usr/local/kamailio/lib64/kamailio/modules/debugger.so...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x00007f1df054e80a in epoll_wait (epfd=5, events=0x7f1db0504990, maxevents=1, 
timeout=2000) at ../sysdeps/unix/sysv/linux/epoll_wait.c:30
30        return SYSCALL_CANCEL (epoll_wait, epfd, events, maxevents, timeout);
(gdb) p pthread_getspecific(2)
$1 = (void *) 0x7f1d700a65a0

# this is worker 2, process_no 8, rank 4
Reading symbols from /usr/local/kamailio/lib64/kamailio/modules/stun.so...
Reading symbols from /usr/local/kamailio/lib64/kamailio/modules/debugger.so...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
--Type <RET> for more, q to quit, c to continue without paging--c
0x00007f1df054e80a in epoll_wait (epfd=5, events=0x7f1db0504990, maxevents=1, 
timeout=2000) at ../sysdeps/unix/sysv/linux/epoll_wait.c:30
30        return SYSCALL_CANCEL (epoll_wait, epfd, events, maxevents, timeout);
(gdb) p pthread_getspecific(2)
$2 = (void *) 0x7f1d700a65a0
```
#### Log Messages
```
CRITICAL: <core> [core/mem/q_malloc.c:555]: qm_free(): BUG: freeing already 
freed pointer (0x7f1d7f9c77b0), called from tls: tls_init.c: ser_free(535), 
first free tls: tls_init.c: ser_free(535) - ignoring
```

#### SIP Traffic

N/A

### Possible Solutions

- avoid doing TLS initialization in rank 0; this will require cooperation from 
all modules that use OpenSSL 3 themselves. If an OpenSSL-using module 
initializes state before `fork()` then all workers will reuse global state


### Additional Information

- OpenSSL 3 has  initialize-once and initialize-once-per-thread states.  An 
example of this is `ERR_STATE *`  - this is of the type 
initialize-once-per-thread.

- when kamailio does OpenSSL initialization in rank 0, the workers inherit all 
"global" objects. If these objects are in shared memory then the worker 
processes will contend for the same state leading to corruption

- due to the design of the OpenSSL 3 alot of this state (static variables, one 
time initialization) cannot be reinitialized after `fork()`. 
"initialize-once-per-thread" can be reinitialized if the child were to spawn 
threads.



-- 
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/issues/3695
You are receiving this because you are subscribed to this thread.

Message ID: <kamailio/kamailio/issues/3...@github.com>
_______________________________________________
Kamailio (SER) - Development Mailing List
To unsubscribe send an email to sr-dev-le...@lists.kamailio.org

Reply via email to