[Pkg-libvirt-commits] [libguestfs] 09/26: lib: Limit space and time used by 'qemu-img info' subprocess.

Hilko Bengen bengen at moszumanska.debian.org
Sun Nov 1 17:11:26 UTC 2015


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag upstream/1.28.12
in repository libguestfs.

commit 84dd5f8e60df0ae561f9c4700d31be4e6f1af2e6
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Tue May 26 13:21:19 2015 +0100

    lib: Limit space and time used by 'qemu-img info' subprocess.
    
    After fuzzing 'qemu-img info' I found that certain files can cause the
    command to use lots of memory and time.  Modify the command
    mini-library to allow us to place resource limits on subprocesses, and
    use these to limit the amount of space and time used by 'qemu-img info'.
    
    (cherry picked from commit 9db0f807a917ec00d24297d5bf63c19065f930cf)
---
 configure.ac           |  3 +++
 src/command.c          | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/guestfs-internal.h |  1 +
 src/info.c             | 20 +++++++++++++++++++
 4 files changed, 76 insertions(+)

diff --git a/configure.ac b/configure.ac
index 908fb18..6d618e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -302,8 +302,10 @@ AC_CHECK_HEADERS([\
     linux/raid/md_u.h \
     printf.h \
     sys/inotify.h \
+    sys/resource.h \
     sys/socket.h \
     sys/statvfs.h \
+    sys/time.h \
     sys/types.h \
     sys/un.h \
     sys/wait.h \
@@ -331,6 +333,7 @@ AC_CHECK_FUNCS([\
     posix_fadvise \
     removexattr \
     setitimer \
+    setrlimit \
     setxattr \
     sigaction \
     statvfs \
diff --git a/src/command.c b/src/command.c
index 4bb469b..7d7842a 100644
--- a/src/command.c
+++ b/src/command.c
@@ -77,6 +77,13 @@
 #include <sys/wait.h>
 #include <sys/select.h>
 
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #include "guestfs.h"
 #include "guestfs-internal.h"
 
@@ -101,6 +108,12 @@ struct buffering {
   void (*close_data) (struct command *cmd);
 };
 
+struct child_rlimits {
+  struct child_rlimits *next;
+  int resource;
+  long limit;
+};
+
 struct command
 {
   guestfs_h *g;
@@ -134,6 +147,9 @@ struct command
 
   /* PID of subprocess (if > 0). */
   pid_t pid;
+
+  /* Optional child limits. */
+  struct child_rlimits *child_rlimits;
 };
 
 /* Create a new command handle. */
@@ -308,6 +324,21 @@ guestfs___cmd_clear_close_files (struct command *cmd)
   cmd->close_files = false;
 }
 
+/* Set up child rlimits, in case the process we are running could
+ * consume lots of space or time.
+ */
+void
+guestfs___cmd_set_child_rlimit (struct command *cmd, int resource, long limit)
+{
+  struct child_rlimits *p;
+
+  p = safe_malloc (cmd->g, sizeof *p);
+  p->resource = resource;
+  p->limit = limit;
+  p->next = cmd->child_rlimits;
+  cmd->child_rlimits = p;
+}
+
 /* Finish off the command by either NULL-terminating the argv array or
  * adding a terminating \0 to the string, or die with an internal
  * error if no command has been added.
@@ -367,6 +398,10 @@ run_command (struct command *cmd)
   int errorfd[2] = { -1, -1 };
   int outfd[2] = { -1, -1 };
   char status_string[80];
+#ifdef HAVE_SETRLIMIT
+  struct child_rlimits *child_rlimit;
+  struct rlimit rlimit;
+#endif
 
   /* Set up a pipe to capture command output and send it to the error log. */
   if (cmd->capture_errors) {
@@ -458,6 +493,23 @@ run_command (struct command *cmd)
   /* Set the umask for all subcommands to something sensible (RHBZ#610880). */
   umask (022);
 
+#ifdef HAVE_SETRLIMIT
+  for (child_rlimit = cmd->child_rlimits;
+       child_rlimit != NULL;
+       child_rlimit = child_rlimit->next) {
+    rlimit.rlim_cur = rlimit.rlim_max = child_rlimit->limit;
+    if (setrlimit (child_rlimit->resource, &rlimit) == -1) {
+      /* EPERM means we're trying to raise the limit (ie. the limit is
+       * already more restrictive than what we want), so ignore it.
+       */
+      if (errno != EPERM) {
+        perror ("setrlimit");
+        _exit (EXIT_FAILURE);
+      }
+    }
+  }
+#endif /* HAVE_SETRLIMIT */
+
   /* Run the command. */
   switch (cmd->style) {
   case COMMAND_STYLE_EXECV:
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 03c6e4b..441cea5 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -835,6 +835,7 @@ extern void guestfs___cmd_set_stdout_callback (struct command *, cmd_stdout_call
 #define CMD_STDOUT_FLAG_UNBUFFERED      1
 #define CMD_STDOUT_FLAG_WHOLE_BUFFER    2
 extern void guestfs___cmd_set_stderr_to_stdout (struct command *);
+extern void guestfs___cmd_set_child_rlimit (struct command *, int resource, long limit);
 extern void guestfs___cmd_clear_capture_errors (struct command *);
 extern void guestfs___cmd_clear_close_files (struct command *);
 extern int guestfs___cmd_run (struct command *);
diff --git a/src/info.c b/src/info.c
index e3f1805..8186b53 100644
--- a/src/info.c
+++ b/src/info.c
@@ -31,6 +31,14 @@
 #include <assert.h>
 #include <string.h>
 
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #if HAVE_YAJL
 #include <yajl/yajl_tree.h>
 #endif
@@ -270,6 +278,12 @@ get_json_output (guestfs_h *g, const char *filename)
   guestfs___cmd_add_arg (cmd, fdpath);
   guestfs___cmd_set_stdout_callback (cmd, parse_json, &tree,
                                      CMD_STDOUT_FLAG_WHOLE_BUFFER);
+#ifdef RLIMIT_AS
+  guestfs___cmd_set_child_rlimit (cmd, RLIMIT_AS, 1000000000 /* 1GB */);
+#endif
+#ifdef RLIMIT_CPU
+  guestfs___cmd_set_child_rlimit (cmd, RLIMIT_CPU, 10 /* seconds */);
+#endif
   r = guestfs___cmd_run (cmd);
   close (fd);
   if (r == -1)
@@ -548,6 +562,12 @@ old_parser_run_qemu_img_info (guestfs_h *g, const char *filename,
   guestfs___cmd_add_arg (cmd, "info");
   guestfs___cmd_add_arg (cmd, safe_filename);
   guestfs___cmd_set_stdout_callback (cmd, fn, data, 0);
+#ifdef RLIMIT_AS
+  guestfs___cmd_set_child_rlimit (cmd, RLIMIT_AS, 1000000000 /* 1GB */);
+#endif
+#ifdef RLIMIT_CPU
+  guestfs___cmd_set_child_rlimit (cmd, RLIMIT_CPU, 10 /* seconds */);
+#endif
   r = guestfs___cmd_run (cmd);
   if (r == -1)
     return -1;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list