On Tue, Nov 28, 2017 at 11:58:50PM +0100, PiBa-NL wrote:
> Hi List, Willy / Willliam,
>
Hi Pieter,
> A patch i came up with that might make it a little 'safer' with regard
> to getenv and its return value or possible lack thereof.. I'm not sure
> it it will ever happen. But if it does it wont fail on a null pointer or
> empty string conversion to a long value.. Though a arithmetic conversion
> error could still happen if the value is present but not a number..but
> well that would be a really odd case.
>
The getenv returning NULL should never happen, but the test is wrong, it should
have been a strtol with an errno check instead of an atol. However that's
overkill in this case, we just need to check the return value of getenv().
> There are a few things i'm not sure about though.
>
> - What would/could possibly break if mworker_pipe values are left as -1
> and the process continues and tries to use it?
That does not seems to be a good idea, because we try to register the fd in the
poller after that. We don't need to do this, it's better to quit the
master-worker if something this simple failed, because we can't trust the
process anymore.
> - wont the rd wr char* values leak memory?
No because you don't need to free the return value of a getenv, it's a pointer
to the environment.
> Anyhow the biggest part that should be noticed of the bug is the
> sometimes wrongful alert when the fd is actually '0'...
>
That's right, the check was not coherent there, we should check only if
getenv return NULL, if the env was modified between the master or the worker
there is a big problem on the system, so no need to check the converted value.
> If anything needs to be changed let me know.
>
> Regards,
>
> PiBa-NL / Pieter
>
>
> From 486d7c759af03f9193ae3e38005d8325ab069b37 Mon Sep 17 00:00:00 2001
> From: PiBa-NL <pba_...@yahoo.com>
> Date: Tue, 28 Nov 2017 23:22:14 +0100
> Subject: [PATCH] [PATCH] BUG/MINOR: Check if master-worker pipe getenv
> succeeded, also allow pipe fd 0 as valid.
>
> On FreeBSD in quiet mode the stdin/stdout/stderr are closed which lets the
> mworker_pipe to use fd 0 and fd 1.
> ---
> src/haproxy.c | 12 +---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/src/haproxy.c b/src/haproxy.c
> index 891a021..c3c8281 100644
> --- a/src/haproxy.c
> +++ b/src/haproxy.c
> @@ -2688,9 +2688,15 @@ int main(int argc, char **argv)
> free(msg);
> }
> } else {
> - mworker_pipe[0] =
> atol(getenv("HAPROXY_MWORKER_PIPE_RD"));
> - mworker_pipe[1] =
> atol(getenv("HAPROXY_MWORKER_PIPE_WR"));
> - if (mworker_pipe[0] <= 0 || mworker_pipe[1] <=
> 0) {
> + mworker_pipe[0] = -1;
> + mworker_pipe[1] = -1;
We don't need to init to -1;
> + char* rd = getenv("HAPROXY_MWORKER_PIPE_RD");
> + char* wr = getenv("HAPROXY_MWORKER_PIPE_WR");
In my opinion we can simplify:
> + if (rd && wr && strlen(rd) > 0 && strlen(wr) >
> 0) {
> + mworker_pipe[0] = atol(rd);
> + mworker_pipe[1] = atol(wr);
> + }
> + if (mworker_pipe[0] < 0 || mworker_pipe[1] < 0)
> {
> ha_warning("[%s.main()] Cannot get
> master pipe FDs.\n", argv[0]);
> }
By doing this, which is more secure, and assure us that it won't start with
this kind of problem:
if (!rd || !wd) {
ha_alert("[%s.main()] Cannot get master
pipe FDs.\n", argv[0]);
exit(1);
}
mworker_pipe[0] = atoi(rd);
mworker_pipe[1] = atoi(wr);
And we can do the same thing with the pipe return value:
ret = pipe(mworker_pipe);
if (ret < 0) {
ha_alert("[%s.main()] Cannot create
master pipe.\n", argv[0]);
exit(1);
}
This code will guarantee that the whole master-worker quit if there is a
problem.
--
William Lallemand