haproxy/src
Christopher Faulet 04400bc787 BUG/MAJOR: stream-int: Don't receive data from mux until SI_ST_EST is reached
This bug is pretty pernicious and have serious consequences : In 2.1, an
infinite loop in process_stream() because the backend stream-interface remains
in the ready state (SI_ST_RDY). In 2.0, a call in loop to process_stream()
because the stream-interface remains blocked in the connect state
(SI_ST_CON). In both cases, it happens after a connection retry attempt. In 1.9,
it seems to not happen. But it may be just by chance or just because it is
harder to get right conditions to trigger the bug. However, reading the code,
the bug seems to exist too.

Here is how the bug happens in 2.1. When we try to establish a new connection to
a server, the corresponding stream-interface is first set to the connect state
(SI_ST_CON). When the underlying connection is known to be connected (the flag
CO_FL_CONNECTED set), the stream-interface is switched to the ready state
(SI_ST_RDY). It is a transient state between the connect state (SI_ST_CON) and
the established state (SI_ST_EST). It must be handled on the next call to
process_stream(), which is responsible to operate the transition. During all
this time, errors can occur. A connection error or a client abort. The transient
state SI_ST_RDY was introduced to let a chance to process_stream() to catch
these errors before considering the connection as fully established.
Unfortunatly, if a read0 is catched in states SI_ST_CON or SI_ST_RDY, it is
possible to have a shutdown without transition to SI_ST_DIS (in fact, here,
SI_ST_CON is swichted to SI_ST_RDY). This happens if the request was fully
received and analyzed. In this case, the flag SI_FL_NOHALF is set on the backend
stream-interface. If an error is also reported during the connect, the behavior
is undefined because an error is returned to the client and a connection retry
is performed. So on the next connection attempt to the server, if another error
is reported, a client abort is detected. But the shutdown for writes was already
done. So the transition to the state SI_ST_DIS is impossible. We stay in the
state SI_ST_RDY. Because it is a transient state, we loop in process_stream() to
perform the transition.

It is hard to understand how the bug happens reading the code and even harder to
explain. But there is a trivial way to hit the bug by sending h2 requests to a
server only speaking h1. For instance, with the following config :

  listen tst
    bind *:80
    server www 127.0.0.1:8000 proto h2 # in reality, it is a HTTP/1.1 server

It is a configuration error, but it is an easy way to observe the bug. Note it
may happen with a valid configuration.

So, after a careful analyzis, it appears that si_cs_recv() should never be
called for a not fully established stream-interface. This way the connection
retries will be performed before reporting an error to the client. Thus, if a
shutdown is performed because a read0 is handled, the stream-interface is
inconditionnaly set to the transient state SI_ST_DIS.

This patch must be backported to 2.0 and 1.9. However on these versions, this
patch reveals a design flaw about connections and a bad way to perform the
connection retries. We are working on it.
2019-10-26 08:24:45 +02:00
..
51d.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
acl.c BUG/MINOR: acl: Fix memory leaks when an ACL expression is parsed 2019-09-13 10:08:44 +02:00
action.c BUG/MEDIUM: stick-table: Wrong stick-table backends parsing. 2019-08-07 10:32:31 +02:00
activity.c CLEANUP: cli: replace all occurrences of manual handling of return messages 2019-08-09 11:26:10 +02:00
applet.c BUG/MEDIUM: applet: always check a fast running applet's activity before killing 2019-10-11 16:05:57 +02:00
arg.c MEDIUM: tools: improve time format error detection 2019-06-07 19:32:02 +02:00
auth.c BUILD/MINOR: auth: enabling for osx 2019-09-08 12:20:13 +02:00
backend.c MEDIUM: list: Separate "locked" list from regular list. 2019-09-23 18:16:08 +02:00
base64.c BUG/MINOR: base64: dec func ignores padding for output size checking 2019-01-14 19:32:15 +01:00
buffer.c MEDIUM: memory: use pool_destroy_all() to destroy all pools on deinit() 2018-11-26 19:50:32 +01:00
cache.c BUG/MINOR: cache: alloc shctx after check config 2019-10-21 15:05:46 +02:00
calltrace.c REORG: trace: rename trace.c to calltrace.c and mention it's not thread-safe 2019-08-22 20:21:00 +02:00
cfgparse-global.c BUG/MEDIUM: threads: cpu-map designating a single thread/process are ignored 2019-07-16 15:23:09 +02:00
cfgparse-listen.c CLEANUP: bind: handle warning label on bind keywords parsing. 2019-10-18 15:18:52 +02:00
cfgparse.c BUG/MAJOR: idle conns: schedule the cleanup task on the correct threads 2019-10-18 09:04:02 +02:00
channel.c MINOR: channel: Add the function channel_add_input 2019-01-02 20:12:44 +01:00
checks.c BUG/MEDIUM: checks: make sure the connection is ready before trying to recv 2019-09-24 10:59:55 +02:00
chunk.c Revert "MINOR: chunks: Make sure trash_size is only set once." 2019-06-07 15:37:47 +02:00
cli.c BUG/MINOR: cli: don't call the kw->io_release if kw->parse failed 2019-10-25 22:00:49 +02:00
compression.c MINOR: time: move the cpu, mono, and idle time to thread_info 2019-05-20 21:14:14 +02:00
connection.c MEDIUM: connection: enable reading only once the connection is confirmed 2019-09-06 17:50:36 +02:00
da.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
debug.c BUG/MEDIUM: debug: address a possible null pointer dereference in "debug dev stream" 2019-10-25 10:10:07 +02:00
dict.c BUG/MINOR: dict: race condition fix when inserting dictionary entries. 2019-06-11 09:54:12 +02:00
dns.c BUG/MINOR: dns: allow srv record weight set to 0 2019-10-22 13:44:12 +02:00
ev_epoll.c MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore 2019-09-06 19:09:56 +02:00
ev_evports.c BUG/MINOR: build: fix event ports (Solaris) 2019-09-23 19:08:39 +02:00
ev_kqueue.c MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore 2019-09-06 19:09:56 +02:00
ev_poll.c MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore 2019-09-06 19:09:56 +02:00
ev_select.c MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore 2019-09-06 19:09:56 +02:00
fcgi-app.c BUG/MEDIUM: fcgi: fix missing list tail in sample fetch registration 2019-09-27 22:48:27 +02:00
fcgi.c MINOR: fcgi: Add code related to FCGI protocol 2019-09-17 10:18:54 +02:00
fd.c MINOR: fd: make updt_fd_polling() a normal function 2019-09-05 09:31:18 +02:00
filters.c BUG/MINOR: filters: Properly set the HTTP status code on analysis error 2019-09-10 10:29:54 +02:00
flt_http_comp.c MEDIUM: fcgi-app: Add FCGI application and filter 2019-09-17 10:18:54 +02:00
flt_spoe.c MINOR: spoe: Support the async mode with several threads 2019-09-26 16:51:02 +02:00
flt_trace.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
freq_ctr.c BUG/MAJOR: threads/freq_ctr: use a memory barrier to detect changes 2017-10-31 18:01:18 +01:00
frontend.c MINOR: frontend: switch from conn->addr.{from,to} to conn->{src,dst} 2019-07-19 13:50:09 +02:00
h1_htx.c CLEANUP: h1-htx: Move htx-to-h1 formatting functions from htx.c to h1_htx.c 2019-10-14 22:28:50 +02:00
h1.c MINOR: h1: Reject requests if the authority does not match the header host 2019-10-14 22:28:50 +02:00
h2.c MEDIUM: h2: use the normalized URI encoding for absolute form requests 2019-10-09 11:10:19 +02:00
haproxy.c BUG/MINOR: mworker/ssl: close openssl FDs unconditionally 2019-10-17 11:36:22 +02:00
hash.c MINOR: hash: add new function hash_crc32c 2018-03-21 05:04:01 +01:00
hathreads.c BUILD/MEDIUM: threads: rename thread_info struct to ha_thread_info 2019-10-17 07:15:17 +02:00
hlua_fcn.c MINOR: stats: prepare to add a description with each stat/info field 2019-10-10 11:30:07 +02:00
hlua.c BUG/MEDIUM: lua: Store stick tables into the sample's t field 2019-09-30 04:11:36 +02:00
hpack-dec.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
hpack-enc.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
hpack-huff.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
hpack-tbl.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
http_acl.c MEDIUM: init: convert all trivial registration calls to initcalls 2018-11-26 19:50:32 +01:00
http_act.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
http_ana.c MINOR: htx: Add a flag on HTX to known when a response was generated by HAProxy 2019-10-16 10:03:12 +02:00
http_conv.c MEDIUM: init: convert all trivial registration calls to initcalls 2018-11-26 19:50:32 +01:00
http_fetch.c CLEANUP: h1-htx: Move htx-to-h1 formatting functions from htx.c to h1_htx.c 2019-10-14 22:28:50 +02:00
http_htx.c BUG/MINOR: http-htx: Properly set htx flags on error files to support keep-alive 2019-10-16 10:03:12 +02:00
http_rules.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
http.c MINOR: http: Add a function to get the authority into a URI 2019-10-09 11:05:31 +02:00
htx.c CLEANUP: h1-htx: Move htx-to-h1 formatting functions from htx.c to h1_htx.c 2019-10-14 22:28:50 +02:00
i386-linux-vsys.c
lb_chash.c BUG/MEDIUM: lb-chash: Ensure the tree integrity when server weight is increased 2019-08-01 11:35:29 +02:00
lb_fas.c BUG/MEDIUM: lb_fas: Don't test the server's lb_tree from outside the lock 2019-07-05 14:26:15 +02:00
lb_fwlc.c BUG/MINOR: lb/leastconn: ignore the server weights for empty servers 2019-09-06 17:13:44 +02:00
lb_fwrr.c BUG/MAJOR: lb/threads: make sure the avoided server is not full on second pass 2019-05-27 10:29:59 +02:00
lb_map.c MEDIUM: lb/threads: Use the new _HA_ATOMIC_* macros. 2019-03-11 17:02:38 +01:00
listener.c OPTIM: listeners: use tasklets for the multi-queue rings 2019-09-24 06:57:32 +02:00
log.c MINOR: log: Provide a function to emit a log for an application 2019-09-17 10:18:54 +02:00
lru.c MINOR: lru: new function to delete <nb> least recently used keys 2016-01-11 07:31:35 +01:00
mailers.c MEDIUM: Add parsing of mailers section 2015-02-03 00:24:16 +01:00
map.c CLEANUP: cli: replace all occurrences of manual handling of return messages 2019-08-09 11:26:10 +02:00
memory.c MINOR: pools: always pre-initialize allocated memory outside of the lock 2019-07-09 10:40:33 +02:00
mux_fcgi.c BUG/MINOR: mux-h1/mux-fcgi/trace: Fix position of the 4th arg in some traces 2019-10-08 16:28:30 +02:00
mux_h1.c MINOR: mux-h1: Force close mode for proxy responses with an unfinished request 2019-10-16 10:03:12 +02:00
mux_h2.c BUG/MINOR: mux-h2: Don't pretend mux buffers aren't full anymore if nothing sent 2019-10-26 08:24:45 +02:00
mux_pt.c BUG/MEDIUM: mux_pt: Only call the wake emthod if nobody subscribed to receive. 2019-10-18 14:18:29 +02:00
mworker-prog.c MEDIUM: mworker-prog: Add user/group options to program section 2019-07-15 16:43:16 +02:00
mworker.c BUILD: mworker: silence two printf format warnings around getpid() 2019-06-22 07:57:56 +02:00
namespace.c BUG/MEDIUM: namespace: close open namespaces during soft shutdown 2019-09-25 23:33:52 +02:00
pattern.c BUG/MEDIUM: pattern: make the pattern LRU cache thread-local and lockless 2019-10-23 07:27:25 +02:00
payload.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
peers.c CLEANUP: cli: replace all occurrences of manual handling of return messages 2019-08-09 11:26:10 +02:00
pipe.c BUILD: address a few cases of "static <type> inline foo()" 2019-04-15 21:55:48 +02:00
proto_sockpair.c BUG/MEDIUM: protocols: add a global lock for the init/deinit stuff 2019-07-24 16:45:02 +02:00
proto_tcp.c MINOR: tcp: avoid confusion in time parsing init 2019-10-24 10:25:00 +02:00
proto_udp.c CLEANUP: fix inconsistency between fd->iocb, proto->accept and accept() 2016-04-14 11:18:22 +02:00
proto_uxst.c MEDIUM: connection: enable reading only once the connection is confirmed 2019-09-06 17:50:36 +02:00
protocol.c BUG/MEDIUM: protocols: add a global lock for the init/deinit stuff 2019-07-24 16:45:02 +02:00
proxy.c BUG/MINOR: mworker/cli: reload fail with inherited FD 2019-10-18 21:45:42 +02:00
queue.c BUG/MAJOR: queue/threads: avoid an AB/BA locking issue in process_srv_queue() 2019-07-30 14:02:06 +02:00
raw_sock.c MEDIUM: connection: enable reading only once the connection is confirmed 2019-09-06 17:50:36 +02:00
regex.c MEDIUM: regex: modify regex_comp() to atomically allocate/free the my_regex struct 2019-05-07 06:58:15 +02:00
ring.c BUG/MINOR: ring: b_peek_varint() returns a uint64_t, not a size_t 2019-08-30 15:07:25 +02:00
sample.c BUG/MINOR: sample: Make the field converter compatible with -m found 2019-10-21 15:49:42 +02:00
server.c BUG/MINOR: server: check return value of fopen() in apply_server_state() 2019-10-21 16:00:24 +02:00
session.c MAJOR: fd: Get rid of the fd cache. 2019-07-31 14:12:55 +02:00
sha1.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
shctx.c CLEANUP: Fix typos in the shctx subsystem 2018-12-02 18:40:29 +01:00
signal.c CLEANUP: Fix a typo in the signal subsystem 2018-12-02 18:39:52 +01:00
sink.c MINOR: sink: change ring buffer "buf0"'s format to "timed" 2019-09-26 08:13:38 +02:00
ssl_sock.c BUG/MINOR: ssl/cli: out of bounds when built without ocsp/sctl 2019-10-23 15:05:00 +02:00
standard.c MINOR: tools: add a function varint_bytes() to report the size of a varint 2019-08-27 17:14:19 +02:00
stats.c MINOR: stats/debug: maintain a counter of debug commands issued 2019-10-24 18:38:00 +02:00
stick_table.c BUG/MINOR: stick-table: fix an incorrect 32 to 64 bit key conversion 2019-10-23 06:24:58 +02:00
stream_interface.c BUG/MAJOR: stream-int: Don't receive data from mux until SI_ST_EST is reached 2019-10-26 08:24:45 +02:00
stream.c MINOR: http: Add server name header from HTTP multiplexers 2019-09-27 08:48:21 +02:00
task.c MEDIUM: task: Split the tasklet list into two lists. 2019-10-11 16:37:41 +02:00
tcp_rules.c MAJOR: http: Remove the HTTP legacy code 2019-07-19 09:24:12 +02:00
time.c MINOR: time: add timeofday_as_iso_us() to return instant time as ISO 2019-09-26 08:13:38 +02:00
trace.c MINOR: trace: extend default event names to 12 chars 2019-08-30 07:39:59 +02:00
uri_auth.c MINOR: stats: replace the ST_* uri_auth flags with STAT_* 2019-10-10 11:30:07 +02:00
vars.c REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files 2019-07-19 09:24:12 +02:00
version.c MINOR: version: make the version strings variables, not constants 2019-10-16 09:56:57 +02:00
wdt.c BUILD/MEDIUM: threads: rename thread_info struct to ha_thread_info 2019-10-17 07:15:17 +02:00
wurfl.c BUG/MINOR: WURFL: fix send_log() function arguments 2019-10-15 10:47:31 +02:00
xprt_handshake.c CLEANUP: connection: rename the wait_event.task field to .tasklet 2019-06-14 14:42:29 +02:00
xxhash.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00