I attached only the first patch at a time.

ср, 15 июл. 2020 г. в 13:08, Илья Шипицин <[email protected]>:

>
>
> ср, 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
>>
>
From 8c231a2a3b776a623f64b9fe496b3667a4af4bfb Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin <[email protected]>
Date: Thu, 16 Jul 2020 02:02:40 +0500
Subject: [PATCH] BUG/MEDIUM: src/server.c: resolve file handle leak on reload

during reload, server state file is read and file handle is not released
this was indepently reported in #738 and #660

partially resolves #660
---
 src/server.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/server.c b/src/server.c
index 05b19d4e1..bd3dcf886 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3268,6 +3268,11 @@ void apply_server_state(void)
 	}
  out_load_server_state_in_tree:
 
+	if (f) {
+		fclose(f);
+		f = NULL;
+	}
+
 	/* parse all proxies and load states form tree (global file) or from local file */
 	for (curproxy = proxies_list; curproxy != NULL; curproxy = curproxy->next) {
 		/* servers are only in backends */
@@ -3447,9 +3452,11 @@ 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);
 	}
 
 	/* now free memory allocated for the tree */
-- 
2.26.2

Reply via email to