From: Christopher Faulet Date: Mon, 12 Apr 2021 14:56:37 +0000 (+0200) Subject: BUG/MINOR: listener: Handle allocation error when allocating a new bind_conf X-Git-Tag: v2.4-dev17~124 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0c6d1dcf7d45f71361cf10e7e9efe1d6a0a6a994;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 17fe9e0908..a8c798c53a 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)); + if (!bind_conf) + goto err; + bind_conf->file = strdup(file); + if (!bind_conf->file) + goto err; bind_conf->line = line; - LIST_ADDQ(&fe->conf.bind, &bind_conf->by_fe); - if (arg) + 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 fba6d019d9..3038beb14a 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 32d7efbe00..13603df5dd 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 2931ee96dc..7930c52eff 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) {