From 476462010ecc2329e9ecba5afd20f84d9605d809 Mon Sep 17 00:00:00 2001 From: Remi Tricot-Le Breton Date: Wed, 19 May 2021 16:40:28 +0200 Subject: [PATCH] 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. --- include/haproxy/lb_chash.h | 2 +- src/cfgparse.c | 9 +++++++-- src/lb_chash.c | 9 ++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/haproxy/lb_chash.h b/include/haproxy/lb_chash.h index 77d790fbe..79504574b 100644 --- a/include/haproxy/lb_chash.h +++ b/include/haproxy/lb_chash.h @@ -27,7 +27,7 @@ struct proxy; 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_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid); diff --git a/src/cfgparse.c b/src/cfgparse.c index adc903b53..286289ad7 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3658,7 +3658,9 @@ out_uri_auth_compat: init_server_map(curproxy); } else if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) { 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 { curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN; fwrr_init_server_groups(curproxy); @@ -3678,7 +3680,9 @@ out_uri_auth_compat: case BE_LB_KIND_HI: if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) { 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 { curproxy->lbprm.algo |= BE_LB_LKUP_MAP; init_server_map(curproxy); @@ -3964,6 +3968,7 @@ out_uri_auth_compat: cfgerr++; continue; } + } } diff --git a/src/lb_chash.c b/src/lb_chash.c index 709105c0e..469da71f5 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -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 * with their assigned keys. It also sets p->lbprm.wdiv to the eweight to * 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 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 = calloc(srv->lb_nodes_tot, 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++) { srv->lb_nodes[node].server = srv; 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)) chash_queue_dequeue_srv(srv); } + return 0; }