From beb71357f929c479a50129e6c6aeed1d3546e7ed Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 14 Oct 2021 08:11:48 +0200 Subject: [PATCH] BUG/MEDIUM: resolver: make sure to always use the correct hostname length In issue #1411, @jjiang-stripe reports that do-resolve() sometimes seems to be trying to resolve crap from random memory contents. The issue is that action_prepare_for_resolution() tries to measure the input string by itself using strlen(), while resolv_action_do_resolve() directly passes it a pointer to the sample, omitting the known length. Thus of course any other header present after the host in memory are appended to the host value. It could theoretically crash if really unlucky, with a buffer that does not contain any zero including in the index at the end, and if the HTX buffer ends on an allocation boundary. In practice it should be too low a probability to have ever been observed. This patch modifies the action_prepare_for_resolution() function to take the string length on with the host name on input and pass that down the chain. This should be backported to 2.0 along with commit "MINOR: resolvers: fix the resolv_str_to_dn_label() API about trailing zero". (cherry picked from commit 947ae125cc3a00c05a5356de177b732fdc55aab5) Signed-off-by: Willy Tarreau (cherry picked from commit a13a610841988fa9713eae50e3fd91e0fd9038f8) Signed-off-by: Christopher Faulet --- src/dns.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/dns.c b/src/dns.c index eaec333..25807ca 100644 --- a/src/dns.c +++ b/src/dns.c @@ -2887,16 +2887,15 @@ INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws); * Returns -1 in case of any allocation failure, 0 if not. * On error, a global failure counter is also incremented. */ -static int action_prepare_for_resolution(struct stream *stream, const char *hostname) +static int action_prepare_for_resolution(struct stream *stream, const char *hostname, int hostname_len) { char *hostname_dn; - int hostname_len, hostname_dn_len; + int hostname_dn_len; struct buffer *tmp = get_trash_chunk(); if (!hostname) return 0; - hostname_len = strlen(hostname); hostname_dn = tmp->area; hostname_dn_len = dns_str_to_dn_label(hostname, hostname_len, hostname_dn, tmp->size); @@ -2926,7 +2925,6 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px, { struct dns_resolution *resolution; struct sample *smp; - char *fqdn; struct dns_requester *req; struct dns_resolvers *resolvers; struct dns_resolution *res; @@ -2987,8 +2985,7 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px, if (smp == NULL) goto end; - fqdn = smp->data.u.str.area; - if (action_prepare_for_resolution(s, fqdn) == -1) + if (action_prepare_for_resolution(s, smp->data.u.str.area, smp->data.u.str.data) == -1) goto end; /* on error, ignore the action */ s->dns_ctx.parent = rule; -- 1.7.10.4