haproxy/include/types
Willy Tarreau ad63582eb9 BUG/MEDIUM: samples: make smp_dup() always duplicate the sample
Vedran Furac reported a strange problem where the "base" sample fetch
would not always work for tracking purposes.

In fact, it happens that commit bc8c404 ("MAJOR: stick-tables: use sample
types in place of dedicated types") merged in 1.6 exposed a fundamental
bug related to the way samples use chunks as strings. The problem is that
chunks convey a base pointer, a length and an optional size, which may be
zero when unknown or when the chunk is allocated from a read-only location.
The sole purpose of this size is to know whether or not the chunk may be
appended new data. This size cause some semantics issue in the sample,
which has its own SMP_F_CONST flag to indicate read-only contents.

The problem was emphasized by the commit above because it made use of new
calls to smp_dup() to convert a sample to a table key. And since smp_dup()
would only check the SMP_F_CONST flag, it would happily return read-write
samples indicating size=0.

So some tests were added upon smp_dup() return to ensure that the actual
length is smaller than size, but this in fact made things even worse. For
example, the "sni" server directive does some bad stuff on many occasions
because it limits len to size-1 and effectively sets it to -1 and writes
the zero byte before the beginning of the string!

It is therefore obvious that smp_dup() needs to be modified to take this
nature of the chunks into account. It's not enough but is needed. The core
of the problem comes from the fact that smp_dup() is called for 5 distinct
needs which are not always fulfilled :

  1) duplicate a sample to keep a copy of it during some operations
  2) ensure that the sample is rewritable for a converter like upper()
  3) ensure that the sample is terminated with a \0
  4) set a correct size on the sample
  5) grow the sample in case it was extracted from a partial chunk

Case 1 is not used for now, so we can ignore it. Case 2 indicates the wish
to modify the sample, so its R/O status must be removed if any, but there's
no implied requirement that the chunk becomes larger. Case 3 is used when
the sample has to be made compatible with libc's str* functions. There's no
need to make it R/W nor to duplicate it if it is already correct. Case 4
can happen when the sample's size is required (eg: before performing some
changes that must fit in the buffer). Case 5 is more or less similar but
will happen when the sample by be grown but we want to ensure we're not
bound by the current small size.

So the proposal is to have different functions for various operations. One
will ensure a sample is safe for use with str* functions. Another one will
ensure it may be rewritten in place. And smp_dup() will have to perform an
inconditional duplication to guarantee at least #5 above, and implicitly
all other ones.

This patch only modifies smp_dup() to make the duplication inconditional. It
is enough to fix both the "base" sample fetch and the "sni" server directive,
and all use cases in general though not always optimally. More patches will
follow to address them more optimally and even better than the current
situation (eg: avoid a dup just to add a \0 when possible).

The bug comes from an ambiguous design, so its roots are old. 1.6 is affected
and a backport is needed. In 1.5, the function already existed but was only
used by two converters modifying the data in place, so the bug has no effect
there.
2016-08-09 14:03:23 +02:00
..
acl.h
action.h MINOR: tcp: add "tcp-request connection expect-netscaler-cip layer4" 2016-06-20 23:02:47 +02:00
applet.h MEDIUM: dumpstats: make stats_tlskeys_list() yield-aware during tls-keys dump 2016-06-14 19:42:08 +02:00
arg.h MINOR: sample: Moves ARGS underlying type from 32 to 64 bits. 2016-03-15 22:11:52 +01:00
auth.h
backend.h
capture.h
channel.h MEDIUM: filters: Add pre and post analyzer callbacks 2016-05-18 15:11:54 +02:00
checks.h MINOR: check: add agent-send server parameter 2015-11-04 07:26:51 +01:00
compression.h MAJOR: filters/http: Rewrite the HTTP compression as a filter 2016-02-09 14:53:15 +01:00
connection.h CLEANUP: connection: using internal struct to hold source and dest port. 2016-07-05 14:43:05 +02:00
counters.h
dns.h BUG/MINOR: Fix endiness issue in DNS header creation code 2016-07-13 14:47:58 +02:00
fd.h CLEANUP: fix inconsistency between fd->iocb, proto->accept and accept() 2016-04-14 11:18:22 +02:00
filters.h MEDIUM: filters: Add pre and post analyzer callbacks 2016-05-18 15:11:54 +02:00
freq_ctr.h
global.h BUG/MEDIUM: config: properly adjust maxconn with nbproc when memmax is forced 2015-12-14 13:03:09 +01:00
hdr_idx.h
hlua.h BUG/MEDIUM: lua: the function txn_done() from action wrapper can crash 2016-07-14 16:14:32 +02:00
lb_chash.h
lb_fas.h
lb_fwlc.h
lb_fwrr.h
lb_map.h
listener.h MINOR: listener: add the "accept-netscaler-cip" option to the "bind" keyword 2016-06-20 23:02:47 +02:00
log.h MINOR: log: add the %Td log-format specifier 2016-05-17 18:04:30 +02:00
mailers.h MINOR: mailers: make it possible to configure the connection timeout 2016-02-20 15:33:06 +01:00
map.h CLEANUP: map: it seems that the map were planed to be chained 2016-03-30 15:41:15 +02:00
obj_type.h
pattern.h MINOR: map: Add regex matching replacement 2016-02-10 23:38:34 +01:00
peers.h CLEANUP: proxy: remove last references to appsession 2015-08-10 19:42:30 +02:00
pipe.h
port_range.h
proto_http.h BUG/MAJOR: http: fix breakage of "reqdeny" causing random crashes 2016-05-25 16:23:59 +02:00
proto_udp.h
protocol.h CLEANUP: fix inconsistency between fd->iocb, proto->accept and accept() 2016-04-14 11:18:22 +02:00
proxy.h MEDIUM: proxy: use dynamic allocation for error dumps 2016-03-31 13:49:23 +02:00
queue.h
sample.h BUG/MEDIUM: samples: make smp_dup() always duplicate the sample 2016-08-09 14:03:23 +02:00
server.h MEDIUM: dns: add a "resolve-net" option which allow to prefer an ip in a network 2016-02-19 14:37:49 +01:00
session.h MEDIUM: vars: move the session variables to the session, not the stream 2015-06-19 11:59:02 +02:00
signal.h
ssl_sock.h
stick_table.h MEDIUM: http: implement http-response track-sc* directive 2016-07-26 14:31:14 +02:00
stream.h MINOR: filters: Add stream_filters structure to hide filters info 2016-02-09 14:53:15 +01:00
stream_interface.h
task.h
template.h
vars.h MINOR: samples: rename a struct from sample_storage to sample_data 2015-08-20 17:13:46 +02:00