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.
(cherry picked from commit 476462010ecc2329e9ecba5afd20f84d9605d809)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit c5c5bc4e36ce4a6f3bc113c8e16824fdb276c220)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit a0320ad186fc4e71c1fec692a0e16c337d28c207)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 03f62de95fcf032e1c52725e8960960b5ebcfc07)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/proto/lb_chash.h b/include/proto/lb_chash.h
index 679dff3..54e2762 100644
--- a/include/proto/lb_chash.h
+++ b/include/proto/lb_chash.h
@@ -26,7 +26,7 @@
#include <types/proxy.h>
#include <types/server.h>
-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 2523e21..4e3a691 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3333,7 +3333,9 @@
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);
@@ -3353,7 +3355,9 @@
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);
diff --git a/src/lb_chash.c b/src/lb_chash.c
index 23448df..c3b416d 100644
--- a/src/lb_chash.c
+++ b/src/lb_chash.c
@@ -26,6 +26,7 @@
#include <types/server.h>
#include <proto/backend.h>
+#include <proto/log.h>
#include <proto/queue.h>
/* Return next tree node after <node> which must still be in the tree, or be
@@ -467,8 +468,9 @@
* 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;
@@ -499,6 +501,10 @@
srv->lb_nodes_tot = srv->uweight * BE_WEIGHT_SCALE;
srv->lb_nodes_now = 0;
srv->lb_nodes = calloc(srv->lb_nodes_tot, sizeof(struct tree_occ));
+ 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);
@@ -507,4 +513,5 @@
if (srv_currently_usable(srv))
chash_queue_dequeue_srv(srv);
}
+ return 0;
}