Skip to content

tcp: fix SSL_CONF_cmd/SSL_new ordering in OpenSSL client connect path#291

Open
Cropi wants to merge 1 commit into
rsyslog:masterfrom
Cropi:fix/ossl-ssl-new-ordering
Open

tcp: fix SSL_CONF_cmd/SSL_new ordering in OpenSSL client connect path#291
Cropi wants to merge 1 commit into
rsyslog:masterfrom
Cropi:fix/ossl-ssl-new-ordering

Conversation

@Cropi

@Cropi Cropi commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Group restrictions configured via tls.tlscfgcmd (e.g. Groups=X25519:P-256) were silently ignored on the OpenSSL client path. The TLS configuration was applied to the SSL context after the per-connection SSL object had already been
created, so the object retained the default group list, including PQC groups on OpenSSL 3.5+ regardless of what was configured.

The fix applies the TLS configuration to the context before creating the SSL
object, matching the ordering already used on the server side.

I hope I did not miss anything by reordering the calls.

relpTcpConnectTLSInit_ossl() called SSL_new(ctx) before
relpTcpSetSslConfCmd_ossl(), so SSL_CONF_cmd("Groups", ...) applied via
tls.tlscfgcmd was updating the SSL_CTX after the SSL object had already
captured its group list.  On OpenSSL 3.x this caused the client to
advertise the full default group set (including X25519MLKEM768 on 3.5+)
regardless of any Groups restriction in tlsConfigCmd.

Move pThis->sslState = osslClient and relpTcpSetSslConfCmd_ossl() to
before SSL_new() so the SSL object inherits the correctly configured
SSL_CTX.  relpTcpTLSSetPrio() stays after SSL_new() because it operates
on pThis->ssl via SSL_set_cipher_list().

The server listen path (relpTcpLstnInitTLS_ossl) already applied
SSL_CONF_cmd to the SSL_CTX before any SSL_new() calls; this brings the
client connect path into the same order.

Signed-off-by: Cropi <alakatos@redhat.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request moves the initialization of pThis->sslState and the execution of relpTcpSetSslConfCmd_ossl to occur before SSL_new is called in relpTcpConnectTLSInit_ossl. The reviewer raised a critical thread-safety issue with this change, noting that applying configuration commands to the global SSL_CTX before SSL_new introduces data races and configuration leakage in multi-threaded environments. The reviewer recommends keeping the configuration step after SSL_new and modifying relpTcpSetSslConfCmd_ossl to target the per-connection SSL object using SSL_CONF_CTX_set_ssl instead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/tcp.c
Comment on lines +1894 to +1901
/* set before relpTcpSetSslConfCmd_ossl: tlsConfigCmd may contain
* flag-restricted commands that require SSL_CONF_FLAG_CLIENT */
pThis->sslState = osslClient;

/* SSL_CONF_cmd targets the SSL_CTX; SSL_new() snapshots the SSL_CTX's
* group list at construction time, so this must run before SSL_new()
* or the SSL object keeps the default groups set by SSL_CTX_new() */
CHKRet(relpTcpSetSslConfCmd_ossl(pThis, pThis->tlsConfigCmd));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Applying configuration commands to the global SSL_CTX (ctx) via SSL_CONF_cmd is problematic in a multi-threaded environment like librelp/rsyslog. Since ctx is a single static global variable shared across all client and server connections:

  1. Data Races: Concurrent connection initializations on different threads will call SSL_CONF_cmd on the same SSL_CTX simultaneously without locking, leading to undefined behavior or crashes.
  2. Configuration Pollution/Leakage: If different connections (or clients and servers) have different tlsConfigCmd settings, they will overwrite each other's configurations on the global ctx. Whichever connection is created next via SSL_new(ctx) will inherit the configuration of the last connection that called SSL_CONF_cmd.

Recommended Solution

Instead of targeting the global SSL_CTX, the configuration should be applied directly to the per-connection SSL object (pThis->ssl) using SSL_CONF_CTX_set_ssl instead of SSL_CONF_CTX_set_ssl_ctx.

To implement this:

  1. Keep relpTcpSetSslConfCmd_ossl after SSL_new (as it was originally) so that pThis->ssl is already allocated.
  2. Modify relpTcpSetSslConfCmd_ossl (around line 1696) to target the SSL object if available:
if (pThis->ssl != NULL) {
    SSL_CONF_CTX_set_ssl(cctx, pThis->ssl);
} else {
    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
}

This ensures thread safety, prevents configuration leakage between connections, and correctly applies the configuration to the active connection.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The race condition is real but pre-dates this patch. The original code called relpTcpSetSslConfCmd_ossl on the same shared global SSL_CTX too just after SSL_new instead of before. This PR didn't introduce it.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Confidence score: 2/5

  • In src/tcp.c, the per-connection TLS setup mutates a shared global SSL_CTX without synchronization before SSL_new, which can cause cross-connection config bleed or nondeterministic handshake failures under concurrency. Protect SSL_CTX access with locking or move to per-connection/per-thread contexts before merging.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/tcp.c">

<violation number="1" location="src/tcp.c:1901">
P1: Race condition: per-connection TLS config modifies shared global SSL_CTX without synchronization before SSL_new</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread src/tcp.c
/* SSL_CONF_cmd targets the SSL_CTX; SSL_new() snapshots the SSL_CTX's
* group list at construction time, so this must run before SSL_new()
* or the SSL object keeps the default groups set by SSL_CTX_new() */
CHKRet(relpTcpSetSslConfCmd_ossl(pThis, pThis->tlsConfigCmd));

@cubic-dev-ai cubic-dev-ai Bot Jun 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Race condition: per-connection TLS config modifies shared global SSL_CTX without synchronization before SSL_new

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tcp.c, line 1901:

<comment>Race condition: per-connection TLS config modifies shared global SSL_CTX without synchronization before SSL_new</comment>

<file context>
@@ -1891,6 +1891,15 @@ relpTcpConnectTLSInit_ossl(relpTcp_t *const pThis)
+	/* SSL_CONF_cmd targets the SSL_CTX; SSL_new() snapshots the SSL_CTX's
+	 * group list at construction time, so this must run before SSL_new()
+	 * or the SSL object keeps the default groups set by SSL_CTX_new() */
+	CHKRet(relpTcpSetSslConfCmd_ossl(pThis, pThis->tlsConfigCmd));
+
 	if(!(pThis->ssl = SSL_new(ctx))) {
</file context>
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant