From 0c6d1dcf7d45f71361cf10e7e9efe1d6a0a6a994 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 12 Apr 2021 16:56:37 +0200 Subject: [PATCH] BUG/MINOR: listener: Handle allocation error when allocating a new bind_conf Allocation error are now handled in bind_conf_alloc() functions. Thus callers, when not already done, are also updated to catch NULL return value. This patch may be backported (at least partially) to all stable versions. However, it only fix errors durung configuration parsing. Thus it is not mandatory. --- include/haproxy/listener.h | 28 ++++++++++++++++++++++------ src/cfgparse-listen.c | 6 +++++- src/cli.c | 4 ++++ src/log.c | 5 +++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 17fe9e090..a8c798c53 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -174,19 +174,27 @@ unsigned int bind_map_thread_id(const struct bind_conf *conf, unsigned int r); /* allocate an bind_conf struct for a bind line, and chain it to the frontend . * If is not NULL, it is duplicated into ->arg to store useful config - * information for error reporting. + * information for error reporting. NULL is returned on error. */ static inline struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *file, int line, const char *arg, struct xprt_ops *xprt) { struct bind_conf *bind_conf = calloc(1, sizeof(struct bind_conf)); - bind_conf->file = strdup(file); - bind_conf->line = line; - LIST_ADDQ(&fe->conf.bind, &bind_conf->by_fe); - if (arg) - bind_conf->arg = strdup(arg); + if (!bind_conf) + goto err; + bind_conf->file = strdup(file); + if (!bind_conf->file) + goto err; + bind_conf->line = line; + if (arg) { + bind_conf->arg = strdup(arg); + if (!bind_conf->arg) + goto err; + } + + LIST_ADDQ(&fe->conf.bind, &bind_conf->by_fe); bind_conf->settings.ux.uid = -1; bind_conf->settings.ux.gid = -1; bind_conf->settings.ux.mode = 0; @@ -200,6 +208,14 @@ static inline struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *fi #endif LIST_INIT(&bind_conf->listeners); return bind_conf; + + err: + if (bind_conf) { + ha_free(&bind_conf->file); + ha_free(&bind_conf->arg); + } + ha_free(&bind_conf); + return NULL; } static inline const char *listener_state_str(const struct listener *l) diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index fba6d019d..3038beb14 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -387,7 +387,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW)); - + if (!bind_conf) { + ha_alert("Out of memory error.\n"); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } /* use default settings for unix sockets */ bind_conf->settings.ux.uid = global.unix_bind.ux.uid; bind_conf->settings.ux.gid = global.unix_bind.ux.gid; diff --git a/src/cli.c b/src/cli.c index 32d7efbe0..13603df5d 100644 --- a/src/cli.c +++ b/src/cli.c @@ -401,6 +401,10 @@ static int cli_parse_global(char **args, int section_type, struct proxy *curpx, } bind_conf = bind_conf_alloc(global.cli_fe, file, line, args[2], xprt_get(XPRT_RAW)); + if (!bind_conf) { + memprintf(err, "'%s %s' : out of memory trying to allocate a bind_conf", args[0], args[1]); + return -1; + } bind_conf->level &= ~ACCESS_LVL_MASK; bind_conf->level |= ACCESS_LVL_OPER; /* default access level */ diff --git a/src/log.c b/src/log.c index 2931ee96d..7930c52ef 100644 --- a/src/log.c +++ b/src/log.c @@ -4031,6 +4031,11 @@ int cfg_parse_log_forward(const char *file, int linenum, char **args, int kwm) bind_conf = bind_conf_alloc(cfg_log_forward, file, linenum, NULL, xprt_get(XPRT_RAW)); + if (!bind_conf) { + ha_alert("parsing [%s:%d] : out of memory error.", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } if (!str2receiver(args[1], cfg_log_forward, bind_conf, file, linenum, &errmsg)) { if (errmsg && *errmsg) {