Detailed Description of the Problem
When running HAProxy 2.4.17 on Windows built/run against OpenSSL 1.0.2 series and using certificates on the frontend, application crashes with a SIGSEGV. Removal of the ssl/cert in the bind command makes the HAProxy start up without issues.
Expected Behavior
HAProxy starts up without a segmentation fault
Steps to Reproduce the Behavior
Pre-requisites:
- Windows
- OpenSSL 1.0.2u dlls built with
MSYS2/MinGW-x64
- HAProxy 2.4.17
- Built using Cygwin and following flags:
make PREFIX="${dist_dir}" \
TARGET=cygwin \
USE_LIBCRYPT= \
USE_PCRE= \
USE_PCRE2= \
USE_STATIC_PCRE2= \
USE_PCRE2_JIT= \
USE_THREAD=0 \
USE_ZLIB=1 \
USE_OPENSSL=1 \
DEBUG_FULL=1 \
SSL_INC="${ssl_dir_prefix}/include" \
SSL_LIB="${ssl_dir_prefix}/lib" \
CFLAGS="-O0 -g -w -fwrapv" \
LDFLAGS="-Wl,-rpath=${ssl_dir_prefix}/lib" \
-j8 all
- Run
./haproxy.exe -f ./haproxy.cfg with following in the settings (full config provided as part of this issue):
...
frontend foo
# bind *:3834 # working
bind *:3834 ssl crt "./certs/openssl_rsa_server.pem" ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384
mode http
option tcplog
option http-server-close
option forwardfor
default_backend foo_backend
monitor-uri /haproxy_test
...
Do you have any idea what may have caused this?
Only an educated guess given that this codebase is new to me and that the source file in question is massive:
The context being freed using SSL_CTX_free(bind_conf->default_ctx) here (L2994 in ssl_sock.c) is assumed not to be the same pointer as ckch_inst->ctx but that's not the case:
...
(gdb) p ckch_inst->ctx
$17 = (SSL_CTX *) 0x40f2e0
(gdb) p bind_conf->default_ctx
$18 = (SSL_CTX *) 0x40f2e0
Assumption here from reading the code is that we want to dispose of the old bind_conf->default_ctx which is in actuality also the memory location of ckch_inst->ctx (an incomplete struct that we want to use moving forward) so when SSL_CTX_free(bind_conf->default_ctx) is trying to zeroize this struct, it hits invalid memory pointers. Excerpt from the backtrace:
...
0x000000006318ce8a in x509_verify_param_zero (param=0xfeeefeeefeeefeee) at C:/Users/foo/tmp/haproxy-cert-crash/openssl/openssl-1.0.2u/crypto/x509/x509_vpm.c:138
138 param->name = NULL;
Do you have an idea how to solve the issue?
My guess for the fix patch:
From ae274daea27899bdbebb500510dd2034fdeebf56 Mon Sep 17 00:00:00 2001
From: Srdjan Grubor <sgnn7@sgnn7.org>
Date: Wed, 29 Jun 2022 15:55:54 -0500
Subject: [PATCH] BUG/MEDIUM: ssl: Fix crash when loading certificates from
file
When using certificates from file and running against OpenSSL, the
assumption that the current and the old context are different pointers
may not be valid. This change ensures that we do not zeroize an
incompletely-initialized SSL context.
---
src/ssl_sock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 7f74977e1..52d9bb953 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -2991,7 +2991,7 @@ void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_
}
/* replace the default_ctx if required with the instance's ctx. */
- if (ckch_inst->is_default) {
+ if (ckch_inst->is_default && bind_conf->default_ctx != ckch_inst->ctx) {
SSL_CTX_free(bind_conf->default_ctx);
SSL_CTX_up_ref(ckch_inst->ctx);
bind_conf->default_ctx = ckch_inst->ctx;
--
2.36.1
What is your configuration?
# Basic configuration
global
log 127.0.0.1 local0 debug
ssl-default-server-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384
# Some sane defaults
defaults
log global
option dontlognull
retries 3
# option redispatch
option redispatch httplog
timeout client 5s
timeout server 5s
timeout connect 5s
# This declares a view into HAProxy statistics, on port 3833
# You do not need credentials to view this page and you can
# turn it off once you are done with setup.
listen stats
bind *:3833
mode http
stats enable
stats uri /
# This section is to reload DNS Records
# Replace these addresses with your DNS Server IP addresses.
resolvers my-dns
nameserver dns1 8.8.8.8:53
nameserver dns2 1.1.1.1:53
resolve_retries 3
timeout resolve 2s
timeout retry 1s
accepted_payload_size 8192
hold valid 10s
hold obsolete 60s
frontend e2e_request_frontend
# bind *:3834
bind *:3834 ssl crt "./certs/openssl_rsa_server.pem" ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384
mode http
option tcplog
option http-server-close
option forwardfor
default_backend e2e_request_backend
monitor-uri /haproxy_test
backend e2e_request_backend
# default server ssl ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384
balance roundrobin
mode http
server-template mothership 5 10.17.1.10:443 check port 443 ssl verify none check
# server server1 server:443 check port 443 ssl verify none check
# server server1 server:443 ssl verify none check resolvers my-dns init-addr none resolve-prefer ipv4 maxconn 20
Output of haproxy -vv
$ ./haproxy -vv
HAProxy version 2.4.17-9f97155 2022/05/13 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.17.html
Running on: CYGWIN_NT-10.0-17763 3.3.5-341.x86_64 2022-05-13 12:27 UTC x86_64
Build options :
TARGET = cygwin
CPU = generic
CC = cc
CFLAGS = -O0 -g -w -fwrapv
OPTIONS = USE_PCRE= USE_PCRE2= USE_PCRE2_JIT= USE_THREAD=0 USE_STATIC_PCRE2= USE_LIBCRYPT= USE_OPENSSL=1 USE_ZLIB=1
DEBUG =
Feature list : -EPOLL -KQUEUE -NETFILTER -PCRE -PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED -BACKTRACE -STATIC_PCRE -STATIC_PCRE2 +TPROXY -LINUX_TPROXY -LINUX_SPLICE -LIBCRYPT -CRYPT_H -GETADDRINFO +OPENSSL -LUA -FUTEX -ACCEPT4 -CLOSEFROM +ZLIB -SLZ -CPU_AFFINITY -TFO -NS -DL -RT -DEVICEATLAS -51DEGREES -WURFL -SYSTEMD +OBSOLETE_LINKER -PRCTL -PROCCTL -THREAD_DUMP -EVPORTS -OT -QUIC -PROMEX -MEMORY_PROFILING
Default settings :
bufsize = 16384, maxrewrite = 1024, maxpollevents = 200
Built with multi-threading support (MAX_THREADS=64, default=1).
Built with OpenSSL version : OpenSSL 1.0.2u 20 Dec 2019
Running on OpenSSL version : OpenSSL 1.0.2u 20 Dec 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2
Built with zlib version : 1.2.12
Running on zlib version : 1.2.12
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using:
Built without PCRE or PCRE2 support (using libc's regex instead)
Encrypted password support via crypt(3): no
Built with gcc compiler version 11.3.0
Available polling systems :
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 2 (2 usable), will use poll.
Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
h2 : mode=HTTP side=FE|BE mux=H2 flags=HTX|CLEAN_ABRT|HOL_RISK|NO_UPG
fcgi : mode=HTTP side=BE mux=FCGI flags=HTX|HOL_RISK|NO_UPG
h1 : mode=HTTP side=FE|BE mux=H1 flags=HTX|NO_UPG
<default> : mode=HTTP side=FE|BE mux=H1 flags=HTX
none : mode=TCP side=FE|BE mux=PASS flags=NO_UPG
<default> : mode=TCP side=FE|BE mux=PASS flags=
Available services : none
Available filters :
[SPOE] spoe
[CACHE] cache
[FCGI] fcgi-app
[COMP] compression
[TRACE] trace
Last Outputs and Backtraces
(gdb) bt
#0 0x000000006318ce8a in x509_verify_param_zero (param=0xfeeefeeefeeefeee) at C:/Users/foo/tmp/haproxy-cert-crash/openssl/openssl-1.0.2u/crypto/x509/x509_vpm.c:138
#1 0x000000006318d0f7 in X509_VERIFY_PARAM_free (param=0xfeeefeeefeeefeee) at C:/Users/foo/tmp/haproxy-cert-crash/openssl/openssl-1.0.2u/crypto/x509/x509_vpm.c:202
#2 0x000000027d140e07 in SSL_CTX_free (a=0x40f410) at C:/Users/foo/tmp/haproxy-cert-crash/openssl/openssl-1.0.2u/ssl/ssl_lib.c:2137
#3 0x000000010040bb6e in ssl_sock_load_cert_sni (ckch_inst=ckch_inst@entry=0x8000cae90, bind_conf=bind_conf@entry=0x8000c6920) at src/ssl_sock.c:2995
#4 0x000000010041030e in ssl_sock_load_ckchs (path=0x80007ee44 "./certs/openssl_rsa_server.pem", ssl_conf=0x0, sni_filter=0x0, fcount=0, err=0xffffc380, ckch_inst=0xffffb198,
bind_conf=0x8000c6920, ckchs=0x8000c6d80) at src/ssl_sock.c:3539
#5 ssl_sock_load_ckchs (err=0xffffc380, ckch_inst=0xffffb198, fcount=0, sni_filter=0x0, ssl_conf=0x0, bind_conf=0x8000c6920, ckchs=0x8000c6d80,
path=0x80007ee44 "./certs/openssl_rsa_server.pem") at src/ssl_sock.c:3527
#6 ssl_sock_load_cert (path=0x80007ee44 "./certs/openssl_rsa_server.pem", bind_conf=0x8000c6920, err=0xffffc380) at src/ssl_sock.c:3705
#7 0x000000010051c2b7 in cfg_parse_listen (file=0x80006e230 "haproxy.cfg", linenum=44, args=0xffffc700, kwm=<optimized out>) at src/cfgparse-listen.c:438
#8 0x00000001004dfb0a in readcfgfile (file=0x80006e230 "haproxy.cfg") at src/cfgparse.c:2332
#9 0x00000001005a51cd in init (argv=<optimized out>, argc=<optimized out>) at src/haproxy.c:1834
#10 main (argc=<optimized out>, argv=0xffffcc00) at src/haproxy.c:2921
Additional Information
No response
Detailed Description of the Problem
When running HAProxy 2.4.17 on Windows built/run against OpenSSL 1.0.2 series and using certificates on the frontend, application crashes with a SIGSEGV. Removal of the ssl/cert in the
bindcommand makes the HAProxy start up without issues.Expected Behavior
HAProxy starts up without a segmentation fault
Steps to Reproduce the Behavior
Pre-requisites:
MSYS2/MinGW-x64./haproxy.exe -f ./haproxy.cfgwith following in the settings (full config provided as part of this issue):Do you have any idea what may have caused this?
Only an educated guess given that this codebase is new to me and that the source file in question is massive:
The context being freed using
SSL_CTX_free(bind_conf->default_ctx)here (L2994 inssl_sock.c) is assumed not to be the same pointer asckch_inst->ctxbut that's not the case:Assumption here from reading the code is that we want to dispose of the old
bind_conf->default_ctxwhich is in actuality also the memory location ofckch_inst->ctx(an incomplete struct that we want to use moving forward) so whenSSL_CTX_free(bind_conf->default_ctx)is trying to zeroize this struct, it hits invalid memory pointers. Excerpt from the backtrace:Do you have an idea how to solve the issue?
My guess for the fix patch:
What is your configuration?
Output of
haproxy -vvLast Outputs and Backtraces
Additional Information
No response