BUG/MINOR: server: better handling of OOM in srv_set_fqdn()

This function may face an OOM on strdup() in the middle of the hostname
or hostname_dn replacement, leaving NULLs in either or both of the server's
fields, which is definitely not good for other call places.

Let's perform a safe replacement instead: we first allocate the new
values, and only if they are successful, then we release the previous
ones and replace them.

It is not necessary to backport this unless the issue is reported (it
was found via code review).
This commit is contained in:
Willy Tarreau 2026-05-15 16:55:07 +02:00
parent 2a43a1306b
commit 6c663a9374

View file

@ -5226,6 +5226,8 @@ int srv_set_fqdn(struct server *srv, const char *hostname, int resolv_locked)
struct resolv_resolution *resolution;
char *hostname_dn;
int hostname_len, hostname_dn_len;
char *hostname_dup = NULL;
char *hostname_dn_dup = NULL;
/* Note that the server lock is already held. */
if (!srv->resolvers)
@ -5256,13 +5258,18 @@ int srv_set_fqdn(struct server *srv, const char *hostname, int resolv_locked)
resolv_unlink_resolution(srv->resolv_requester);
hostname_dup = strdup(hostname);
hostname_dn_dup = strdup(hostname_dn);
if (!hostname_dup || !hostname_dn_dup)
goto err;
free(srv->hostname);
free(srv->hostname_dn);
srv->hostname = strdup(hostname);
srv->hostname_dn = strdup(hostname_dn);
srv->hostname = hostname_dup;
srv->hostname_dn = hostname_dn_dup;
srv->hostname_dn_len = hostname_dn_len;
if (!srv->hostname || !srv->hostname_dn)
goto err;
hostname_dup = NULL;
hostname_dn_dup = NULL;
if (srv->flags & SRV_F_NO_RESOLUTION)
goto end;
@ -5278,6 +5285,8 @@ int srv_set_fqdn(struct server *srv, const char *hostname, int resolv_locked)
err:
if (!resolv_locked)
HA_SPIN_UNLOCK(DNS_LOCK, &srv->resolvers->lock);
ha_free(&hostname_dup);
ha_free(&hostname_dn_dup);
return -1;
}