P J P <ppan...@redhat.com> writes:

> From: Prasad J Pandit <p...@fedoraproject.org>
>
> When invoking qemu-bridge-helper in 'net_bridge_run_helper',
> instead of using fixed sized buffers, use dynamically allocated
> ones initialised and returned by g_strdup_printf().

Does this fix a bug?

> If bridge name 'br_buf' is undefined, pass empty string ("") to
> g_strdup_printf() in its place, to avoid printing "(null)" string.
>
> Signed-off-by: Prasad J Pandit <p...@fedoraproject.org>
> ---
>  net/tap.c | 19 +++++++++++--------
>  1 file changed, 11 insertions(+), 8 deletions(-)
>
> Update v5: add commit message about conditional 'br_buf' argument
>   -> https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg06397.html
>
> diff --git a/net/tap.c b/net/tap.c
> index e8aadd8d4b..fc38029f41 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -498,9 +498,9 @@ static int net_bridge_run_helper(const char *helper, 
> const char *bridge,
>      }
>      if (pid == 0) {
>          int open_max = sysconf(_SC_OPEN_MAX), i;
> -        char fd_buf[6+10];
> -        char br_buf[6+IFNAMSIZ] = {0};
> -        char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];
> +        char *fd_buf = NULL;

Dead initializer.

> +        char *br_buf = NULL;
> +        char *helper_cmd = NULL;

Another one.

>  
>          for (i = 3; i < open_max; i++) {
>              if (i != sv[1]) {
> @@ -508,17 +508,17 @@ static int net_bridge_run_helper(const char *helper, 
> const char *bridge,
>              }
>          }
>  
> -        snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);
> +        fd_buf = g_strdup_printf("%s%d", "--fd=", sv[1]);

Good opportunity to change this to

           fd_buf = g_strdup_printf("--fd=%d", sv[1]);

More of the same below.

>  
>          if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
>              /* assume helper is a command */
>  
>              if (strstr(helper, "--br=") == NULL) {
> -                snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
> +                br_buf = g_strdup_printf("%s%s", "--br=", bridge);
>              }
>  
> -            snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
> -                     helper, "--use-vnet", fd_buf, br_buf);
> +            helper_cmd = g_strdup_printf("%s %s %s %s", helper,
> +                            "--use-vnet", fd_buf, br_buf ? br_buf : "");
>  
>              parg = args;
>              *parg++ = (char *)"sh";
> @@ -527,10 +527,11 @@ static int net_bridge_run_helper(const char *helper, 
> const char *bridge,
>              *parg++ = NULL;
>  
>              execv("/bin/sh", args);
> +            g_free(helper_cmd);
>          } else {
>              /* assume helper is just the executable path name */
>  
> -            snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
> +            br_buf = g_strdup_printf("%s%s", "--br=", bridge);
>  
>              parg = args;
>              *parg++ = (char *)helper;
> @@ -541,6 +542,8 @@ static int net_bridge_run_helper(const char *helper, 
> const char *bridge,
>  
>              execv(helper, args);
>          }
> +        g_free(fd_buf);
> +        g_free(br_buf);
>          _exit(1);
>  
>      } else {

The commit does what it claims to do, and no more, so
Reviewed-by: Markus Armbruster <arm...@redhat.com>

However, the code is still rather ugly, and I'd be tempted to use the
opportunity to clean up some more.  Untested sketch:

diff --git a/net/tap.c b/net/tap.c
index 06af8fb8ad..57bb4c552d 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -402,8 +402,7 @@ static void launch_script(const char *setup_script, const 
char *ifname,
                           int fd, Error **errp)
 {
     int pid, status;
-    char *args[3];
-    char **parg;
+    const char *argv[3];
 
     /* try to launch network script */
     pid = fork();
@@ -413,18 +412,18 @@ static void launch_script(const char *setup_script, const 
char *ifname,
         return;
     }
     if (pid == 0) {
-        int open_max = sysconf(_SC_OPEN_MAX), i;
+        int open_max = sysconf(_SC_OPEN_MAX);
+        int i;
 
         for (i = 3; i < open_max; i++) {
             if (i != fd) {
                 close(i);
             }
         }
-        parg = args;
-        *parg++ = (char *)setup_script;
-        *parg++ = (char *)ifname;
-        *parg = NULL;
-        execv(setup_script, args);
+        argv[0] = setup_script;
+        argv[1] = ifname;
+        argv[2] = NULL;
+        execv(setup_script, (char *const *)argv);
         _exit(1);
     } else {
         while (waitpid(pid, &status, 0) != pid) {
@@ -478,8 +477,7 @@ static int net_bridge_run_helper(const char *helper, const 
char *bridge,
 {
     sigset_t oldmask, mask;
     int pid, status;
-    char *args[5];
-    char **parg;
+    const char *argv[5];
     int sv[2];
 
     sigemptyset(&mask);
@@ -498,10 +496,9 @@ static int net_bridge_run_helper(const char *helper, const 
char *bridge,
         return -1;
     }
     if (pid == 0) {
-        int open_max = sysconf(_SC_OPEN_MAX), i;
-        char fd_buf[6+10];
-        char br_buf[6+IFNAMSIZ] = {0};
-        char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];
+        int open_max = sysconf(_SC_OPEN_MAX);
+        int i;
+        char *fd_opt, *br_opt;
 
         for (i = 3; i < open_max; i++) {
             if (i != sv[1]) {
@@ -509,39 +506,30 @@ static int net_bridge_run_helper(const char *helper, 
const char *bridge,
             }
         }
 
-        snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);
+        fd_opt = g_strdup_printf("--fd=%d", sv[1]);
+        br_opt = g_strdup_printf("--br=%s", bridge);
 
         if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
             /* assume helper is a command */
-
-            if (strstr(helper, "--br=") == NULL) {
-                snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
-            }
-
-            snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
-                     helper, "--use-vnet", fd_buf, br_buf);
-
-            parg = args;
-            *parg++ = (char *)"sh";
-            *parg++ = (char *)"-c";
-            *parg++ = helper_cmd;
-            *parg++ = NULL;
-
-            execv("/bin/sh", args);
+            /* FIXME strstr() is lazy and somewhat fragile */
+            bool need_br = !strstr(helper, "--br=");
+
+            argv[0] = "/bin/sh";
+            argv[1] = "-c";
+            argv[2] = g_strdup_printf("%s --use-vnet %s %s",
+                                      helper, fd_opt,
+                                      need_br ? br_opt : "");
+            argv[3] = NULL;
         } else {
             /* assume helper is just the executable path name */
-
-            snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
-
-            parg = args;
-            *parg++ = (char *)helper;
-            *parg++ = (char *)"--use-vnet";
-            *parg++ = fd_buf;
-            *parg++ = br_buf;
-            *parg++ = NULL;
-
-            execv(helper, args);
+            argv[0] = helper;
+            argv[1] = "--use-vnet";
+            argv[2] = fd_opt;
+            argv[3] = br_opt;
+            argv[4] = NULL;
         }
+
+        execv(argv[0], (char *const *)argv);
         _exit(1);
 
     } else {

Reply via email to