ср, 15 июл. 2020 г. в 12:00, Willy Tarreau <[email protected]>:

> Hi Ilya,
>
> > From 4f62799eba5db5fe6400d458877677f098da3b13 Mon Sep 17 00:00:00 2001
> > From: Ilya Shipitsin <[email protected]>
> > Date: Sun, 12 Jul 2020 15:24:55 +0500
> > Subject: [PATCH] src/server.c: add extra guards when loading state file
> >
> > this should fix #660
> >
> > we can only load 'local' state file, if file is corrupted,
> > we should check filepath against NULL
> >
> > also, global server state file should be properly closed upon read.
> > otherwise, it might leak on haproxy reload.
> >
> > when reading global server state file we should check string lenght,
> > if file was corrupted we might observe overflow otherwise.
>
> So do I understand it right that there are actually two unrelated, or
> maybe even three bugs there ? If so, please always take care of splitting
> them (one fix per bug) so that they could be independently reviewed and
> backported as needed (or sometimes possibly reverted if the fix causes
> unexpected breakage).
>
> > ---
> >  src/server.c | 9 ++++++---
> >  1 file changed, 6 insertions(+), 3 deletions(-)
> >
> > diff --git a/src/server.c b/src/server.c
> > index 05b19d4e1..54239c63c 100644
> > --- a/src/server.c
> > +++ b/src/server.c
> > @@ -3265,6 +3265,7 @@ void apply_server_state(void)
> >                       /* free up memory in case of error during the
> processing of the line */
> >                       free(line);
> >               }
> > +             fclose(f);
> >       }
> >   out_load_server_state_in_tree:
>
> I had a look at the patch in its context and this will still leak in the
> case where global_file_version == 0.
>
> The right way to do it would instead to add this after this label
> "out_load_server_state_in_tree" :
>
>         if (f) {
>                 fclose(f);
>                 f = NULL;
>         }
>
> > @@ -3360,6 +3361,8 @@ void apply_server_state(void)
> >                                       goto next;
> >
> >                               st = container_of(node, struct state_line,
> name_name);
> > +                             if (strlen(st->line) >
> SRV_STATE_LINE_MAXLEN)
> > +                                     goto next;
>
> So from what I'm seeing elsewhere in the code, this test will never match:
> a line is read using fgets() with a size of SRV_STATE_LINE_MAXLEN (hence it
> will always read one less char), and it is passed to srv_state_parse_line()
> which returns an error when the '\n' is missing, hence the line is skipped
> and never indexed, so this cannot happen at all.
>
> >                               memcpy(mybuf, st->line, strlen(st->line));
> >                               mybuf[strlen(st->line)] = 0;
> >
> > @@ -3375,7 +3378,7 @@ void apply_server_state(void)
> >
> >                       continue; /* next proxy in list */
> >               }
> > -             else {
> > +             else if (filepath) {
>
> Is it a third issue ? The whole code is hard to follow for me but what is
> the exact case you've tried to address here ? Looking through the code, it
> looks like we could land there when the local file name is too large (but
> apparently there is no error handling for this where this path name is
> constructed) :-/
>
> >                       /* load 'local' state file */
> >                       errno = 0;
> >                       f = fopen(filepath, "r");
> > @@ -3447,9 +3450,9 @@ void apply_server_state(void)
> >                               /* now we can proceed with server's state
> update */
> >                               srv_update_state(srv, version, srv_params);
> >                       }
> > +                     fileclose:
> > +                             fclose(f);
> >               }
> > -fileclose:
> > -             fclose(f);
> >       }
>
> I agree, this one definitely makes sense!
>


I will address comments today or tomorrow


>
> Thanks!
> Willy
>

Reply via email to