On Tue, 23 Jul 2019 13:25:38 +0200
Jiri Pirko <j...@resnulli.us> wrote:

> From: Jiri Pirko <j...@mellanox.com>
> 
> When getcmdline fails, there is no valid string in line_next.
> So change the flow and don't process it. Alongside with that,
> free the previous line buffer and prevent memory leak.
> 
> Fixes: 485d0c6001c4 ("tc: Add batchsize feature for filter and actions")
> Signed-off-by: Jiri Pirko <j...@mellanox.com>


This is not sufficient to avoid valgrind detected uninitialized memory.
The following changes to your patch (#2 alone) is enough to fix
the issue.

The logic here is still a mess and needs to be cleaned up to avoid
future related bugs.

From bbcc22899566556ced9692e4811aea2a38817834 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <j...@mellanox.com>
Date: Tue, 23 Jul 2019 13:25:38 +0200
Subject: [PATCH] tc: batch: fix line/line_next processing in batch

When getcmdline fails, there is no valid string in line_next.
So change the flow and don't process it. Alongside with that,
free the previous line buffer and prevent memory leak.

Also, avoid passing uninitialized memory to filters.

Fixes: 485d0c6001c4 ("tc: Add batchsize feature for filter and actions")
Signed-off-by: Jiri Pirko <j...@mellanox.com>
Signed-off-by: Stephen Hemminger <step...@networkplumber.org>
---
 tc/tc.c | 84 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 43 insertions(+), 41 deletions(-)

diff --git a/tc/tc.c b/tc/tc.c
index 64e342dd85bf..95e5481955ad 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -325,11 +325,10 @@ static int batch(const char *name)
 {
        struct batch_buf *head = NULL, *tail = NULL, *buf_pool = NULL;
        char *largv[100], *largv_next[100];
-       char *line, *line_next = NULL;
+       char *line = NULL, *line_next = NULL;
        bool bs_enabled = false;
        bool lastline = false;
        int largc, largc_next;
-       bool bs_enabled_saved;
        bool bs_enabled_next;
        int batchsize = 0;
        size_t len = 0;
@@ -360,47 +359,40 @@ static int batch(const char *name)
        largc = makeargs(line, largv, 100);
        bs_enabled = batchsize_enabled(largc, largv);
        do {
-               if (getcmdline(&line_next, &len, stdin) == -1)
+               if (getcmdline(&line_next, &len, stdin) == -1) {
                        lastline = true;
-
-               largc_next = makeargs(line_next, largv_next, 100);
-               bs_enabled_next = batchsize_enabled(largc_next, largv_next);
-               if (bs_enabled) {
-                       struct batch_buf *buf;
-
-                       buf = get_batch_buf(&buf_pool, &head, &tail);
-                       if (!buf) {
-                               fprintf(stderr,
-                                       "failed to allocate batch_buf\n");
-                               return -1;
-                       }
-                       ++batchsize;
-               }
-
-               /*
-                * In batch mode, if we haven't accumulated enough commands
-                * and this is not the last command and this command & next
-                * command both support the batchsize feature, don't send the
-                * message immediately.
-                */
-               if (!lastline && bs_enabled && bs_enabled_next
-                   && batchsize != MSG_IOV_MAX)
-                       send = false;
-               else
                        send = true;
+               } else {
+                       largc_next = makeargs(line_next, largv_next, 100);
+                       bs_enabled_next = batchsize_enabled(largc_next, 
largv_next);
+                       if (bs_enabled) {
+                               struct batch_buf *buf;
+
+                               buf = get_batch_buf(&buf_pool, &head, &tail);
+                               if (!buf) {
+                                       fprintf(stderr,
+                                               "failed to allocate 
batch_buf\n");
+                                       return -1;
+                               }
+                               ++batchsize;
+                       }
 
-               line = line_next;
-               line_next = NULL;
-               len = 0;
-               bs_enabled_saved = bs_enabled;
-               bs_enabled = bs_enabled_next;
-
-               if (largc == 0) {
-                       largc = largc_next;
-                       memcpy(largv, largv_next, largc * sizeof(char *));
-                       continue;       /* blank line */
+                       /*
+                        * In batch mode, if we haven't accumulated enough
+                        * commands and this is not the last command and this
+                        * command & next command both support the batchsize
+                        * feature, don't send the message immediately.
+                        */
+                       if (bs_enabled && bs_enabled_next
+                           && batchsize != MSG_IOV_MAX)
+                               send = false;
+                       else
+                               send = true;
                }
 
+               if (largc == 0)
+                       goto to_next_line;      /* blank line */
+
                err = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
                             tail == NULL ? 0 : sizeof(tail->buf));
                fflush(stdout);
@@ -411,10 +403,8 @@ static int batch(const char *name)
                        if (!force)
                                break;
                }
-               largc = largc_next;
-               memcpy(largv, largv_next, largc * sizeof(char *));
 
-               if (send && bs_enabled_saved) {
+               if (send && bs_enabled) {
                        struct iovec *iov, *iovs;
                        struct batch_buf *buf;
                        struct nlmsghdr *n;
@@ -438,6 +428,18 @@ static int batch(const char *name)
                        }
                        batchsize = 0;
                }
+
+to_next_line:
+               if (lastline)
+                       continue;
+               free(line);
+               line = line_next;
+               line_next = NULL;
+               len = 0;
+               bs_enabled = bs_enabled_next;
+               largc = largc_next;
+               memcpy(largv, largv_next, largc * sizeof(char *));
+
        } while (!lastline);
 
        free_batch_bufs(&buf_pool);
-- 
2.20.1

Reply via email to