]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: server: Don't load server-state file if a line is corrupted
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 16 Feb 2021 10:51:12 +0000 (11:51 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 25 Feb 2021 09:02:39 +0000 (10:02 +0100)
This change is not huge but may have a visible impact for users. Now, if a
line of a server-state file is corrupted, the whole file is ignored. A
warning is emitted with the corrupted line number.

In fact, there is no way to recover from a corrupted line. A line is
considered as corrupted if it is too long (truncated line) or if it contains
the wrong number of arguments. In both cases, it means the file was forged
(or at least manually edited). It is safer to ignore it.

Note for now, memory allocation errors are not reported and the
corresponding line is silently ignored.

src/server.c

index bbd8d856540c1e78fafdbd9da7175ccaaa768109..6f57cb4a834ff447fedae848f8d666cce44b7624 100644 (file)
@@ -3333,7 +3333,7 @@ void apply_server_state(void)
        FILE *f;
        char mybuf[SRV_STATE_LINE_MAXLEN];
        char file[MAXPATHLEN];
-       int local_vsn, global_vsn, len;
+       int local_vsn, global_vsn, len, linenum;
 
        global_vsn = 0; /* no global file */
        if (!global.server_state_file)
@@ -3359,8 +3359,17 @@ void apply_server_state(void)
                goto close_globalfile;
        }
 
-       while (fgets(mybuf, SRV_STATE_LINE_MAXLEN, f))
-               srv_state_parse_and_store_line(mybuf, global_vsn, &global_state_tree, NULL);
+       for (linenum = 0; fgets(mybuf, SRV_STATE_LINE_MAXLEN, f); linenum++) {
+               int ret;
+
+               ret = srv_state_parse_and_store_line(mybuf, global_vsn, &global_state_tree, NULL);
+               if (ret == -1) {
+                       ha_warning("config: corrupted global server state file '%s' at line %d.\n",
+                                  file, linenum);
+                       global_vsn = 0;
+                       break;
+               }
+       }
 
   close_globalfile:
        fclose(f);
@@ -3419,8 +3428,17 @@ void apply_server_state(void)
                }
 
                /* First, parse lines of the local server-state file and store them in a eb-tree */
-               while (fgets(mybuf, SRV_STATE_LINE_MAXLEN, f))
-                       srv_state_parse_and_store_line(mybuf, local_vsn, &local_state_tree, curproxy);
+               for (linenum = 0; fgets(mybuf, SRV_STATE_LINE_MAXLEN, f); linenum++) {
+                       int ret;
+
+                       ret = srv_state_parse_and_store_line(mybuf, local_vsn, &local_state_tree, curproxy);
+                       if (ret == -1) {
+                               ha_warning("Proxy '%s': corrupted server state file '%s' at line %d.\n",
+                                          curproxy->id, file, linenum);
+                               local_vsn = 0;
+                               break;
+                       }
+               }
 
                if (local_vsn)
                        srv_state_px_update(curproxy, local_vsn, &local_state_tree);
@@ -3432,11 +3450,13 @@ void apply_server_state(void)
                        next_node = eb64_next(node);
                        eb64_delete(node);
 
-                       /* if no server found, then warn */
-                       ha_warning("Proxy '%s': can't find server '%s' in backend '%s'\n",
-                                  curproxy->id, st_line->params[3], curproxy->id);
-                       send_log(curproxy, LOG_NOTICE, "can't find server '%s' in backend '%s'\n",
-                                st_line->params[3], curproxy->id);
+                       if (local_vsn) {
+                               /* if no server found, then warn */
+                               ha_warning("Proxy '%s': can't find server '%s' in backend '%s'\n",
+                                          curproxy->id, st_line->params[3], curproxy->id);
+                               send_log(curproxy, LOG_NOTICE, "can't find server '%s' in backend '%s'\n",
+                                        st_line->params[3], curproxy->id);
+                       }
 
                        free(st_line->line);
                        free(st_line);