BUG/MINOR: proxy: Missing calloc return value check in chash_init_server_tree

A memory allocation failure happening in chash_init_server_tree while
trying to allocate a server's lb_nodes item used in consistent hashing
would have resulted in a crash. This function is only called during
configuration parsing.

It was raised in GitHub issue #1233.
It could be backported to all stable branches.
This commit is contained in:
Remi Tricot-Le Breton 2021-05-19 16:40:28 +02:00 committed by Christopher Faulet
parent 17acbab0ac
commit 476462010e
3 changed files with 16 additions and 4 deletions

View File

@ -27,7 +27,7 @@
struct proxy; struct proxy;
struct server; struct server;
void chash_init_server_tree(struct proxy *p); int chash_init_server_tree(struct proxy *p);
struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid); struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid);
struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid); struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid);

View File

@ -3658,7 +3658,9 @@ out_uri_auth_compat:
init_server_map(curproxy); init_server_map(curproxy);
} else if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) { } else if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) {
curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN; curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
chash_init_server_tree(curproxy); if (chash_init_server_tree(curproxy) < 0) {
cfgerr++;
}
} else { } else {
curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN; curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
fwrr_init_server_groups(curproxy); fwrr_init_server_groups(curproxy);
@ -3678,7 +3680,9 @@ out_uri_auth_compat:
case BE_LB_KIND_HI: case BE_LB_KIND_HI:
if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) { if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN; curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
chash_init_server_tree(curproxy); if (chash_init_server_tree(curproxy) < 0) {
cfgerr++;
}
} else { } else {
curproxy->lbprm.algo |= BE_LB_LKUP_MAP; curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
init_server_map(curproxy); init_server_map(curproxy);
@ -3964,6 +3968,7 @@ out_uri_auth_compat:
cfgerr++; cfgerr++;
continue; continue;
} }
} }
} }

View File

@ -19,6 +19,7 @@
#include <import/eb32tree.h> #include <import/eb32tree.h>
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/backend.h> #include <haproxy/backend.h>
#include <haproxy/errors.h>
#include <haproxy/queue.h> #include <haproxy/queue.h>
#include <haproxy/server-t.h> #include <haproxy/server-t.h>
#include <haproxy/tools.h> #include <haproxy/tools.h>
@ -462,8 +463,9 @@ struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid)
* constistent hashing. The servers receive an array of initialized nodes * constistent hashing. The servers receive an array of initialized nodes
* with their assigned keys. It also sets p->lbprm.wdiv to the eweight to * with their assigned keys. It also sets p->lbprm.wdiv to the eweight to
* uweight ratio. * uweight ratio.
* Return 0 in case of success, -1 in case of allocation failure.
*/ */
void chash_init_server_tree(struct proxy *p) int chash_init_server_tree(struct proxy *p)
{ {
struct server *srv; struct server *srv;
struct eb_root init_head = EB_ROOT; struct eb_root init_head = EB_ROOT;
@ -495,6 +497,10 @@ void chash_init_server_tree(struct proxy *p)
srv->lb_nodes_now = 0; srv->lb_nodes_now = 0;
srv->lb_nodes = calloc(srv->lb_nodes_tot, srv->lb_nodes = calloc(srv->lb_nodes_tot,
sizeof(*srv->lb_nodes)); sizeof(*srv->lb_nodes));
if (!srv->lb_nodes) {
ha_alert("failed to allocate lb_nodes for server %s.\n", srv->id);
return -1;
}
for (node = 0; node < srv->lb_nodes_tot; node++) { for (node = 0; node < srv->lb_nodes_tot; node++) {
srv->lb_nodes[node].server = srv; srv->lb_nodes[node].server = srv;
srv->lb_nodes[node].node.key = full_hash(srv->puid * SRV_EWGHT_RANGE + node); srv->lb_nodes[node].node.key = full_hash(srv->puid * SRV_EWGHT_RANGE + node);
@ -503,4 +509,5 @@ void chash_init_server_tree(struct proxy *p)
if (srv_currently_usable(srv)) if (srv_currently_usable(srv))
chash_queue_dequeue_srv(srv); chash_queue_dequeue_srv(srv);
} }
return 0;
} }