From c78ec7e085e99bfddd0509dece72bf6a8d0188ce Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 6 Feb 2013 14:27:39 +0000 Subject: [PATCH] daemon: Check parameter of base64-out and tar-out before running external command (RHBZ#908322). For base64-out, check the filename parameter exists and is not a directory. For tar-out, check the dir parameter exists and is a directory. --- daemon/base64.c | 31 +++++++++++++++++++++++++++---- daemon/tar.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/daemon/base64.c b/daemon/base64.c index 7f4d85bdf..263c87ab2 100644 --- a/daemon/base64.c +++ b/daemon/base64.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include "guestfs_protocol.h" #include "daemon.h" @@ -97,12 +100,32 @@ do_base64_in (const char *file) int do_base64_out (const char *file) { + CLEANUP_FREE char *buf = NULL; + struct stat statbuf; int r; FILE *fp; CLEANUP_FREE char *cmd = NULL; - char buf[GUESTFS_MAX_CHUNK_SIZE]; + char buffer[GUESTFS_MAX_CHUNK_SIZE]; - if (asprintf_nowarn (&cmd, "%s %R", str_base64, file) == -1) { + /* Check the filename exists and is not a directory (RHBZ#908322). */ + buf = sysroot_path (file); + if (buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + if (stat (buf, &statbuf) == -1) { + reply_with_perror ("stat: %s", file); + return -1; + } + + if (S_ISDIR (statbuf.st_mode)) { + reply_with_error ("%s: is a directory", file); + return -1; + } + + /* Construct the command. */ + if (asprintf_nowarn (&cmd, "%s %s", str_base64, buf) == -1) { reply_with_perror ("asprintf"); return -1; } @@ -122,8 +145,8 @@ do_base64_out (const char *file) */ reply (NULL, NULL); - while ((r = fread (buf, 1, sizeof buf, fp)) > 0) { - if (send_file_write (buf, r) < 0) { + while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) { + if (send_file_write (buffer, r) < 0) { pclose (fp); return -1; } diff --git a/daemon/tar.c b/daemon/tar.c index 4a27dfe2d..9bf85f57a 100644 --- a/daemon/tar.c +++ b/daemon/tar.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include "read-file.h" @@ -279,12 +282,14 @@ int do_tar_out (const char *dir, const char *compress, int numericowner, char *const *excludes) { + CLEANUP_FREE char *buf = NULL; + struct stat statbuf; const char *filter; int r; FILE *fp; CLEANUP_FREE char *excludes_args = NULL; CLEANUP_FREE char *cmd = NULL; - char buf[GUESTFS_MAX_CHUNK_SIZE]; + char buffer[GUESTFS_MAX_CHUNK_SIZE]; if ((optargs_bitmask & GUESTFS_TAR_OUT_COMPRESS_BITMASK)) { if (STREQ (compress, "compress")) @@ -319,10 +324,27 @@ do_tar_out (const char *dir, const char *compress, int numericowner, } } + /* Check the filename exists and is a directory (RHBZ#908322). */ + buf = sysroot_path (dir); + if (buf == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + if (stat (buf, &statbuf) == -1) { + reply_with_perror ("stat: %s", dir); + return -1; + } + + if (! S_ISDIR (statbuf.st_mode)) { + reply_with_error ("%s: not a directory", dir); + return -1; + } + /* "tar -C /sysroot%s -cf - ." but we have to quote the dir. */ - if (asprintf_nowarn (&cmd, "%s -C %R%s%s%s -cf - .", + if (asprintf_nowarn (&cmd, "%s -C %s%s%s%s -cf - .", str_tar, - dir, filter, + buf, filter, numericowner ? " --numeric-owner" : "", excludes_args) == -1) { reply_with_perror ("asprintf"); @@ -344,8 +366,8 @@ do_tar_out (const char *dir, const char *compress, int numericowner, */ reply (NULL, NULL); - while ((r = fread (buf, 1, sizeof buf, fp)) > 0) { - if (send_file_write (buf, r) < 0) { + while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) { + if (send_file_write (buffer, r) < 0) { pclose (fp); return -1; }