BUG/MEDIUM: server: Add a rwlock to path parameter

Add a rwlock to control the server's path_parameter, to make sure
multiple threads don't set it at the same time, and it can't be seen in
an inconsistent state.
Also don't set the parameter every time, only set them if they have
changed, to prevent needless writes.

This does not need to be backported.
This commit is contained in:
Olivier Houchard 2025-11-04 16:46:50 +01:00 committed by Olivier Houchard
parent efe60745b3
commit 7d4aa7b22b
4 changed files with 19 additions and 7 deletions

View File

@ -320,6 +320,7 @@ enum renegotiate_mode {
#define MAX_ALPN_SIZE 16
struct path_parameters {
__decl_thread(HA_RWLOCK_T param_lock);
char nego_alpn[MAX_ALPN_SIZE];
};

View File

@ -2067,10 +2067,14 @@ int connect_server(struct stream *s)
* that this is skipped in TCP mode as we only want mux-pt
* anyway.
*/
if (IS_HTX_STRM(s) && srv && srv->use_ssl &&
(srv->ssl_ctx.alpn_str || srv->ssl_ctx.npn_str) &&
srv->path_params.nego_alpn[0] == 0)
may_start_mux_now = 0;
if (srv) {
HA_RWLOCK_RDLOCK(SERVER_LOCK, &srv->path_params.param_lock);
if (IS_HTX_STRM(s) && srv->use_ssl &&
(srv->ssl_ctx.alpn_str || srv->ssl_ctx.npn_str) &&
srv->path_params.nego_alpn[0] == 0)
may_start_mux_now = 0;
HA_RWLOCK_RDUNLOCK(SERVER_LOCK, &srv->path_params.param_lock);
}
#endif
/* process the case where the server requires the PROXY protocol to be sent */

View File

@ -141,7 +141,9 @@ static const char *srv_op_st_chg_cause_str[] = {
static void srv_reset_path_parameters(struct server *s)
{
HA_RWLOCK_WRLOCK(SERVER_LOCK, &s->path_params.param_lock);
s->path_params.nego_alpn[0] = 0;
HA_RWLOCK_WRUNLOCK(SERVER_LOCK, &s->path_params.param_lock);
}
const char *srv_op_st_chg_cause(enum srv_op_st_chg_cause cause)
@ -3142,6 +3144,7 @@ struct server *new_server(struct proxy *proxy)
sv->next = srv;
}
HA_RWLOCK_INIT(&srv->path_params.param_lock);
/* please don't put default server settings here, they are set in
* proxy_preset_defaults().
*/

View File

@ -6825,11 +6825,15 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
const char *alpn;
int len;
if (ssl_sock_get_alpn(conn, ctx, &alpn, &len)) {
srv = objt_server(conn->target);
if (srv && len < sizeof(srv->path_params.nego_alpn)) {
srv = objt_server(conn->target);
if (srv && ssl_sock_get_alpn(conn, ctx, &alpn, &len)) {
if (len < sizeof(srv->path_params.nego_alpn) &&
(len != strlen(srv->path_params.nego_alpn) ||
memcmp(&srv->path_params.nego_alpn, alpn, len) != 0)) {
HA_RWLOCK_WRLOCK(SERVER_LOCK, &srv->path_params.param_lock);
memcpy(&srv->path_params.nego_alpn, alpn, len);
srv->path_params.nego_alpn[len] = 0;
HA_RWLOCK_WRUNLOCK(SERVER_LOCK, &srv->path_params.param_lock);
}
}
}