mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-11 05:48:41 +00:00
BUG/MEDIUM: htx: smp_prefetch_htx() must always validate the direction
It is possible to process a channel based on desynchronized info if a request fetch is called from a response and conversely. However, the code in smp_prefetch_htx() already makes sure the analysis has already started before trying to fetch from a buffer, so the problem effectively lies in response rules making use of request expressions only. Usually it's not a problem as extracted data are checked against the current HTTP state, except when it comes to the start line, which is usually accessed directly from sample fetch functions such as status, path, url, url32, query and so on. In this case, trying to access the request buffer from the response path will lead to unpredictable results. When building with DEBUG_STRICT, a process violating these rules will simply die after emitting: FATAL: bug condition "htx->first == -1" matched at src/http_htx.c:67 But when this is not enabled, it may or may not crash depending on what the pending request buffer data look like when trying to spot a start line there. This is typically what happens in issue #806. This patch adds a test in smp_prefetch_htx() so that it does not try to parse an HTX buffer in a channel belonging to the wrong direction. There's one special case on the "method" sample fetch since it can retrieve info even without a buffer, from the other direction, as long as the method is one of the well known ones. Three, we call smp_prefetch_htx() only if needed. This was reported in 2.0 and must be backported there (oldest stable version with HTX).
This commit is contained in:
parent
e3a5f84e53
commit
a6d9879e69
@ -163,6 +163,8 @@ static int get_http_auth(struct sample *smp, struct htx *htx)
|
||||
* decide whether or not an HTTP message is present ;
|
||||
* NULL if the requested data cannot be fetched or if it is certain that
|
||||
* we'll never have any HTTP message there; this includes null strm or chn.
|
||||
* NULL if the sample's direction does not match the channel's (i.e. the
|
||||
* function was asked to work on the wrong channel)
|
||||
* The HTX message if ready
|
||||
*/
|
||||
struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct check *check, int vol)
|
||||
@ -173,6 +175,11 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che
|
||||
struct http_msg *msg;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (chn &&
|
||||
(((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ && (chn->flags & CF_ISRESP)) ||
|
||||
((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES && !(chn->flags & CF_ISRESP))))
|
||||
return 0;
|
||||
|
||||
/* Note: it is possible that <s> is NULL when called before stream
|
||||
* initialization (eg: tcp-request connection), so this function is the
|
||||
* one responsible for guarding against this case for all HTTP users.
|
||||
@ -323,24 +330,29 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che
|
||||
static int smp_fetch_meth(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
struct channel *chn = SMP_REQ_CHN(smp);
|
||||
struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 0);
|
||||
struct http_txn *txn;
|
||||
int meth;
|
||||
|
||||
if (!htx)
|
||||
txn = smp->strm->txn;
|
||||
if (!txn)
|
||||
return 0;
|
||||
|
||||
txn = smp->strm->txn;
|
||||
meth = txn->meth;
|
||||
smp->data.type = SMP_T_METH;
|
||||
smp->data.u.meth.meth = meth;
|
||||
if (meth == HTTP_METH_OTHER) {
|
||||
struct htx *htx;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) {
|
||||
/* ensure the indexes are not affected */
|
||||
return 0;
|
||||
}
|
||||
|
||||
htx = smp_prefetch_htx(smp, chn, NULL, 0);
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_get_stline(htx);
|
||||
smp->flags |= SMP_F_CONST;
|
||||
smp->data.u.meth.str.area = HTX_SL_REQ_MPTR(sl);
|
||||
|
Loading…
Reference in New Issue
Block a user