BUG/MAJOR: ensure that hdr_idx is always reserved when L7 fetches are used

Baptiste Assmann reported a bug causing a crash on recent versions when
sticking rules were set on layer 7 in a TCP proxy. The bug is easier to
reproduce with the "defer-accept" option on the "bind" line in order to
have some contents to parse when the connection is accepted. The issue
is that the acl_prefetch_http() function called from HTTP fetches relies
on hdr_idx to be preinitialized, which is not the case if there is no L7
ACL.

The solution consists in adding a new SMP_CAP_L7 flag to fetches to indicate
that they are expected to work on L7 data, so that the proxy knows that the
hdr_idx has to be initialized. This is already how ACL and HTTP mode are
handled.

The bug was present since 1.5-dev9.
This commit is contained in:
Willy Tarreau 2012-10-05 22:41:26 +02:00
parent 71e451c74c
commit 1b6c00cb99
3 changed files with 14 additions and 9 deletions

View File

@ -50,6 +50,7 @@ enum {
enum {
SMP_CAP_REQ = 1 << 0, /* fetch supported on request */
SMP_CAP_RES = 1 << 1, /* fetch supported on response */
SMP_CAP_L7 = 1 << 2, /* fetch may require access to L7 */
};
/* Sample fetch options are passed to sample fetch functions to add precision

View File

@ -2945,6 +2945,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
}
}
/* check if we need to allocate an hdr_idx struct for HTTP parsing */
if (expr->fetch->cap & SMP_CAP_L7)
curproxy->acl_requires |= ACL_USE_L7_ANY;
if (strcmp(args[myidx], "table") == 0) {
myidx++;
name = args[myidx++];

View File

@ -8780,15 +8780,15 @@ static struct acl_kw_list acl_kws = {{ },{
/************************************************************************/
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
{ "hdr", smp_fetch_hdr, ARG2(1,STR,SINT), val_hdr, SMP_T_CSTR, SMP_CAP_REQ },
{ "base", smp_fetch_base, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ },
{ "path", smp_fetch_path, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ },
{ "url", smp_fetch_url, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ },
{ "url_ip", smp_fetch_url_ip, 0, NULL, SMP_T_IPV4, SMP_CAP_REQ },
{ "url_port", smp_fetch_url_port, 0, NULL, SMP_T_UINT, SMP_CAP_REQ },
{ "url_param", smp_fetch_url_param, ARG2(1,STR,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ },
{ "cookie", smp_fetch_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
{ "set-cookie", smp_fetch_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_RES }, /* deprecated */
{ "hdr", smp_fetch_hdr, ARG2(1,STR,SINT), val_hdr, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ },
{ "base", smp_fetch_base, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ },
{ "path", smp_fetch_path, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ },
{ "url", smp_fetch_url, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ },
{ "url_ip", smp_fetch_url_ip, 0, NULL, SMP_T_IPV4, SMP_CAP_L7|SMP_CAP_REQ },
{ "url_port", smp_fetch_url_port, 0, NULL, SMP_T_UINT, SMP_CAP_L7|SMP_CAP_REQ },
{ "url_param", smp_fetch_url_param, ARG2(1,STR,STR), NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ },
{ "cookie", smp_fetch_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ|SMP_CAP_RES },
{ "set-cookie", smp_fetch_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_RES }, /* deprecated */
{ NULL, NULL, 0, 0, 0 },
}};