[PATCH v2 0/4] dpkg --memlimit

View: New views
5 Messages — Rating Filter:   Alert me  

[PATCH v2 0/4] dpkg --memlimit

by Jonathan Nieder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

If an archive declares it needs it, lzma -d will allocate 4 GiB of
memory to decompress it.  This shouldn’t be an issue with .deb files
from the Debian archive, but occasionally a person might want to at
least examine the contents of an untrusted package.

If the lzma command is provided by XZ Utils, then "lzma -d" already
limits memory usage, even without this patch.  An option to override
the memory limit is essential to unpack archives exceeding the default
memory limit.

I previously sent these patches as part of the xz support series.
They also apply on top of the compression code refactoring just sent.
Thoughts?

Jonathan Nieder (4):
  Add tuklib_physmem() from XZ Utils
  dpkg-deb: set a memory usage limit for lzma -d
  dpkg: change pass_admindir to a bool
  dpkg: add --memlimit option, passed to dpkg-deb

 configure.ac                   |    2 +
 debian/copyright               |    3 +
 dpkg-deb/dpkg-deb.h            |    3 +
 dpkg-deb/extract.c             |    2 +-
 dpkg-deb/main.c                |   24 ++++++
 lib/dpkg/Makefile.am           |    5 +
 lib/dpkg/compression-backend.c |  100 ++++++++++++++++++++++++-
 lib/dpkg/compression-backend.h |    6 +-
 lib/dpkg/compression.c         |    8 +-
 lib/dpkg/dpkg.h                |    4 +-
 lib/tuklib/sysdefs.h           |  165 ++++++++++++++++++++++++++++++++++++++++
 lib/tuklib/tuklib_common.h     |   71 +++++++++++++++++
 lib/tuklib/tuklib_config.h     |    1 +
 lib/tuklib/tuklib_physmem.c    |  146 +++++++++++++++++++++++++++++++++++
 lib/tuklib/tuklib_physmem.h    |   28 +++++++
 m4/tuklib_common.m4            |   22 +++++
 m4/tuklib_physmem.m4           |  119 +++++++++++++++++++++++++++++
 man/dpkg-deb.1                 |    8 ++
 man/dpkg.1                     |    6 ++
 src/main.c                     |   22 +++++-
 src/main.h                     |    1 +
 src/processarc.c               |   11 +++-
 22 files changed, 745 insertions(+), 12 deletions(-)
 create mode 100644 lib/tuklib/sysdefs.h
 create mode 100644 lib/tuklib/tuklib_common.h
 create mode 100644 lib/tuklib/tuklib_config.h
 create mode 100644 lib/tuklib/tuklib_physmem.c
 create mode 100644 lib/tuklib/tuklib_physmem.h
 create mode 100644 m4/tuklib_common.m4
 create mode 100644 m4/tuklib_physmem.m4


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST@...
with a subject of "unsubscribe". Trouble? Contact listmaster@...


[PATCH v2 1/4] Add tuklib_physmem() from XZ Utils

by Jonathan Nieder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Future versions of liblzma should include this function in the
library, but until then, if we want to know how much RAM is
installed on a system, we must include some function like this
ourselves.

This commit only adds the code; it does not hook it into the dpkg
build infrastructure.

 debian/copyright            |    3 +
 lib/tuklib/sysdefs.h        |  165 +++++++++++++++++++++++++++++++++++++++++++
 lib/tuklib/tuklib_common.h  |   71 ++++++++++++++++++
 lib/tuklib/tuklib_config.h  |    1 +
 lib/tuklib/tuklib_physmem.c |  146 ++++++++++++++++++++++++++++++++++++++
 lib/tuklib/tuklib_physmem.h |   28 +++++++
 m4/tuklib_common.m4         |   22 ++++++
 m4/tuklib_physmem.m4        |  119 +++++++++++++++++++++++++++++++
 8 files changed, 555 insertions(+), 0 deletions(-)
 create mode 100644 lib/tuklib/sysdefs.h
 create mode 100644 lib/tuklib/tuklib_common.h
 create mode 100644 lib/tuklib/tuklib_config.h
 create mode 100644 lib/tuklib/tuklib_physmem.c
 create mode 100644 lib/tuklib/tuklib_physmem.h
 create mode 100644 m4/tuklib_common.m4
 create mode 100644 m4/tuklib_physmem.m4

[Compressed to avoid hitting message length limits.]


0001-Add-tuklib_physmem-from-XZ-Utils.patch.gz (7K) Download Attachment

[PATCH v2 2/4] dpkg-deb: set a memory usage limit for lzma -d

by Jonathan Nieder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Unlike gzip and bzip2, LZ77-based compressors can continue to
improve their compression ratio quite a bit in some cases by
using more memory.  For this reason, the .lzma format allows a
dictionary size (and thus memory usage) up to 4 GiB, which can
present problems for the decompressor, including making a system
unresponsive or summoning the dreaded Linux OOM killer.  Make
sure dpkg does not use more than 100 MiB, nor 40% of available
RAM, when decompressing an lzma-compressed package to unpack it
or examine its contents.

If the lzma command is provided by XZ Utils, also make sure _not_
to set a memory usage limit below 10 MiB.  Without this change,
dpkg would refuse to install packages compressed with the default
lzma settings on memory-starved systems (with less than 20 MiB of
physical memory).

Add a --memlimit command-line option to allow overriding the
memory usage limit in case it is too low.

Signed-off-by: Jonathan Nieder <jrnieder@...>
---
 configure.ac                   |    2 +
 dpkg-deb/dpkg-deb.h            |    3 +
 dpkg-deb/extract.c             |    2 +-
 dpkg-deb/main.c                |   24 ++++++++++
 lib/dpkg/Makefile.am           |    5 ++
 lib/dpkg/compression-backend.c |  100 +++++++++++++++++++++++++++++++++++++++-
 lib/dpkg/compression-backend.h |    6 ++-
 lib/dpkg/compression.c         |    8 ++-
 lib/dpkg/dpkg.h                |    4 +-
 man/dpkg-deb.1                 |    8 +++
 10 files changed, 153 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index 52f019c..7a7458c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,7 @@ fi
 
 # Checks for header files.
 AC_HEADER_STDC
+AC_HEADER_STDBOOL
 AC_CHECK_HEADERS([stddef.h error.h locale.h libintl.h kvm.h \
                   sys/cdefs.h sys/syscall.h])
 DPKG_CHECK_DEFINE(TIOCNOTTY, [sys/ioctl.h])
@@ -102,6 +103,7 @@ DPKG_CHECK_DECL([WCOREDUMP], [sys/wait.h])
 DPKG_CHECK_COMPAT_FUNCS([getopt getopt_long obstack_free \
                          strnlen strerror strsignal \
                          scandir alphasort unsetenv])
+TUKLIB_PHYSMEM
 AC_CHECK_FUNCS([strtoul isascii bcopy memcpy lchown setsid getdtablesize])
 
 DPKG_COMPILER_WARNINGS
diff --git a/dpkg-deb/dpkg-deb.h b/dpkg-deb/dpkg-deb.h
index 2bd6d88..edb8a8f 100644
--- a/dpkg-deb/dpkg-deb.h
+++ b/dpkg-deb/dpkg-deb.h
@@ -22,6 +22,8 @@
 #ifndef DPKG_DEB_H
 #define DPKG_DEB_H
 
+#include <stdint.h>
+
 typedef void dofunction(const char *const *argv);
 dofunction do_build DPKG_ATTR_NORET;
 dofunction do_contents, do_control, do_showinfo;
@@ -37,6 +39,7 @@ void extracthalf(const char *debar, const char *directory,
 extern const char *compression;
 extern const char* showformat;
 extern enum compress_type compress_type;
+extern uint64_t compress_memlimit;
 
 #define ARCHIVEVERSION "2.0"
 
diff --git a/dpkg-deb/extract.c b/dpkg-deb/extract.c
index 4c429d7..f0abce8 100644
--- a/dpkg-deb/extract.c
+++ b/dpkg-deb/extract.c
@@ -292,7 +292,7 @@ void extracthalf(const char *debar, const char *directory,
     m_dup2(readfromfd,0);
     if (admininfo) close(p1[0]);
     if (taroption) { m_dup2(p2[1],1); close(p2[0]); close(p2[1]); }
-    decompress_cat(compress_type, 0, 1, _("data"));
+    decompress_cat(compress_type, 0, 1, compress_memlimit, _("data"));
   }
   if (readfromfd != fileno(ar)) close(readfromfd);
   if (taroption) close(p2[1]);
diff --git a/dpkg-deb/main.c b/dpkg-deb/main.c
index b478ba9..0f2ef19 100644
--- a/dpkg-deb/main.c
+++ b/dpkg-deb/main.c
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -107,6 +108,8 @@ usage(const struct cmdinfo *cip, const char *value)
 "  -z#                              Set the compression level when building.\n"
 "  -Z<type>                         Set the compression type used when building.\n"
 "                                     Allowed values: gzip, bzip2, lzma, none.\n"
+"  -M, --memlimit=<bytes>           Set the memory usage limit used when\n"
+"                                     examining lzma compressed packages.\n"
 "\n"));
 
   printf(_(
@@ -137,11 +140,13 @@ const char printforhelp[]=
 int debugflag=0, nocheckflag=0, oldformatflag=BUILDOLDPKGFORMAT;
 const char* compression=NULL;
 enum compress_type compress_type = compress_type_gzip;
+uint64_t compress_memlimit = 0;
 const struct cmdinfo *cipaction = NULL;
 dofunction *action = NULL;
 
 static void setaction(const struct cmdinfo *cip, const char *value);
 static void setcompresstype(const struct cmdinfo *cip, const char *value);
+static void setmemlimit(const struct cmdinfo *cip, const char *value);
 
 static dofunction *const dofunctions[]= {
   do_build,
@@ -174,6 +179,7 @@ static const struct cmdinfo cmdinfos[]= {
   { "nocheck",       0,   0, &nocheckflag,   NULL,         NULL,          1 },
   { "compression",   'z', 1, NULL,           &compression, NULL,          1 },
   { "compress_type", 'Z', 1, NULL,           NULL,         setcompresstype  },
+  { "memlimit",      'M', 1, NULL,           NULL,         setmemlimit      },
   { "showformat",    0,   1, NULL,           &showformat,  NULL             },
   { "help",          'h', 0, NULL,           NULL,         usage            },
   { "version",       0,   0, NULL,           NULL,         printversion     },
@@ -206,6 +212,24 @@ static void setcompresstype(const struct cmdinfo *cip, const char *value) {
     ohshit(_("unknown compression type `%s'!"), value);
 }
 
+static void setmemlimit(const struct cmdinfo *cip, const char *value) {
+  const char *endp;
+  unsigned long long limit;
+
+  if (strchr(value, '-') != NULL)
+    ohshit(_("invalid integer for -M: '%s'"), value);
+
+  errno = 0;
+  limit = strtoull(value, (char **)&endp, 10);
+
+  if (value == endp || *endp != '\0')
+    ohshit(_("invalid integer for -M: '%s'"), value);
+  if (errno == ERANGE || limit > UINT64_MAX)
+    ohshit(_("argument to -M out of range: '%s'"), value);
+
+  compress_memlimit = (uint64_t)limit;
+}
+
 int main(int argc, const char *const *argv) {
   jmp_buf ejbuf;
 
diff --git a/lib/dpkg/Makefile.am b/lib/dpkg/Makefile.am
index 7428f7c..22cbeff 100644
--- a/lib/dpkg/Makefile.am
+++ b/lib/dpkg/Makefile.am
@@ -23,6 +23,11 @@ libdpkg_a_SOURCES = \
  cleanup.c \
  compression.c \
  compression-backend.c compression-backend.h \
+ $(top_srcdir)/lib/tuklib/tuklib_physmem.c \
+ $(top_srcdir)/lib/tuklib/tuklib_physmem.h \
+ $(top_srcdir)/lib/tuklib/tuklib_common.h \
+ $(top_srcdir)/lib/tuklib/tuklib_config.h \
+ $(top_srcdir)/lib/tuklib/sysdefs.h \
  database.c \
  dbmodify.c \
  dump.c \
diff --git a/lib/dpkg/compression-backend.c b/lib/dpkg/compression-backend.c
index 9bfbcee..3cf561b 100644
--- a/lib/dpkg/compression-backend.c
+++ b/lib/dpkg/compression-backend.c
@@ -4,9 +4,12 @@
 #include <dpkg/i18n.h>
 
 #include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/resource.h>
 #include <errno.h>
 
 #ifdef WITH_ZLIB
@@ -15,10 +18,12 @@
 #ifdef WITH_BZ2
 #include <bzlib.h>
 #endif
+#include <tuklib/tuklib_physmem.h>
 
 #include <dpkg/dpkg.h>
 #include <dpkg/varbuf.h>
 #include <dpkg/buffer.h>
+#include <dpkg/subproc.h>
 #include <dpkg/macros.h>
 
 #include "compression-backend.h"
@@ -58,6 +63,29 @@ fd_fd_filter(int fd_in, int fd_out, const char *desc,
  varbuffree(&argbuf);
 }
 
+/* Default memory usage limit for LZ77-based decompressors. */
+static uint64_t
+default_memlimit()
+{
+ /*
+ * The command-line decoder from XZ Utils limits itself to 40% of
+ * available RAM, so take that as a reasonable default memory
+ * limit.  If tuklib_physmem() fails, this is zero.
+ */
+ uint64_t limit = tuklib_physmem() * 2 / 5;
+
+ /*
+ * Assume one can manage to find 10 MiB even on memory-starved
+ * systems, so dpkg won’t refuse to unpack packages shipped by
+ * Debian.  Do not use more than 100 MiB, as a safety measure
+ * for servers processing untrusted packages.
+ */
+ limit = max(limit, 10 << 20);
+ limit = min(limit, 100 << 20);
+
+ return limit;
+}
+
 #define DECOMPRESS(format, zFile, zdopen, zread, zerror, ERR_ERRNO, \
  fd_in, fd_out, desc) do \
 { \
@@ -180,10 +208,78 @@ compress_bzip2(int fd_in, int fd_out, char compression, const char *desc)
 }
 #endif
 
+static bool
+input_matches(FILE *in, const char *str)
+{
+ char ch;
+
+ while (ch = *str++)
+ if (fgetc(in) != ch)
+ return false;
+
+ return true;
+}
+
+static bool
+lzma_is_xz(const char *desc)
+{
+ int pipefd[2];
+ pid_t cpid;
+
+ m_pipe(pipefd);
+ cpid = m_fork();
+
+ if (cpid == 0) {
+ m_dup2(pipefd[1], 1);
+ close(pipefd[0]);
+ close(pipefd[1]);
+ execlp(LZMA, "lzma", "--version", NULL);
+ ohshite(_("%s: failed to exec '%s %s'"),
+ desc, "lzma", "--version");
+ } else {
+ FILE *pipef;
+ bool ret;
+
+ close(pipefd[1]);
+ pipef = fdopen(pipefd[0], "r");
+
+ ret = input_matches(pipef, "xz ");
+
+ if (ferror(pipef))
+ ohshite(_("%s: error reading lzma's pipe"), desc);
+ if (fclose(pipef))
+ ohshite(_("%s: error closing lzma's pipe"), desc);
+ waitsubproc(cpid, "lzma --version", PROCPIPE);
+
+ return ret;
+ }
+}
+
 void
-decompress_lzma(int fd_in, int fd_out, const char *desc)
+decompress_lzma(int fd_in, int fd_out, uint64_t memlimit, const char *desc)
 {
- fd_fd_filter(fd_in, fd_out, desc, LZMA, "lzma", "-dc");
+ if (memlimit == 0)
+ memlimit = default_memlimit();
+
+ if (lzma_is_xz(desc)) {
+ fd_fd_filter(fd_in, fd_out, desc, LZMA, "lzma",
+ "-dcM%" PRIu64, memlimit);
+ } else {
+ struct rlimit lim;
+
+ if (getrlimit(RLIMIT_AS, &lim))
+ ohshite(_("%s: failed to get address space limit"),
+ desc);
+ if (memlimit > lim.rlim_max)
+ lim.rlim_cur = lim.rlim_max;
+ else
+ lim.rlim_cur = (rlim_t)memlimit;
+
+ if (setrlimit(RLIMIT_AS, &lim))
+ ohshite(_("%s: failed to set address space limit"),
+ desc);
+ fd_fd_filter(fd_in, fd_out, desc, LZMA, "lzma", "-dc");
+ }
 }
 
 void
diff --git a/lib/dpkg/compression-backend.h b/lib/dpkg/compression-backend.h
index 7f3c5d6..86c55f2 100644
--- a/lib/dpkg/compression-backend.h
+++ b/lib/dpkg/compression-backend.h
@@ -12,14 +12,16 @@
 #include <config.h>
 #include <compat.h>
 
+#include <stdint.h>
+
 #include <dpkg/macros.h>
 
 void decompress_gzip(int fd_in, int fd_out, const char *desc)
  DPKG_ATTR_NORET;
 void decompress_bzip2(int fd_in, int fd_out, const char *desc)
  DPKG_ATTR_NORET;
-void decompress_lzma(int fd_in, int fd_out, const char *desc)
- DPKG_ATTR_NORET;
+void decompress_lzma(int fd_in, int fd_out, uint64_t memlimit,
+ const char *desc) DPKG_ATTR_NORET;
 void decompress_noop(int fd_in, int fd_out, const char *desc)
  DPKG_ATTR_NORET;
 
diff --git a/lib/dpkg/compression.c b/lib/dpkg/compression.c
index 813526f..61068be 100644
--- a/lib/dpkg/compression.c
+++ b/lib/dpkg/compression.c
@@ -1,14 +1,16 @@
 #include <config.h>
 #include <compat.h>
 
-#include <stdlib.h>
 #include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
 
 #include <dpkg/dpkg.h>
 #include <dpkg/varbuf.h>
 #include <dpkg/compression-backend.h>
 
-void decompress_cat(enum compress_type type, int fd_in, int fd_out, char *desc, ...) {
+void decompress_cat(enum compress_type type, int fd_in, int fd_out,
+                    uint64_t memlimit, char *desc, ...) {
   va_list al;
   struct varbuf v = VARBUF_INIT;
 
@@ -22,7 +24,7 @@ void decompress_cat(enum compress_type type, int fd_in, int fd_out, char *desc,
     case compress_type_bzip2:
       decompress_bzip2(fd_in, fd_out, v.buf);
     case compress_type_lzma:
-      decompress_lzma(fd_in, fd_out, v.buf);
+      decompress_lzma(fd_in, fd_out, memlimit, v.buf);
     case compress_type_cat:
       decompress_noop(fd_in, fd_out, v.buf);
     default:
diff --git a/lib/dpkg/dpkg.h b/lib/dpkg/dpkg.h
index afe650f..94a5214 100644
--- a/lib/dpkg/dpkg.h
+++ b/lib/dpkg/dpkg.h
@@ -30,6 +30,7 @@ DPKG_BEGIN_DECLS
 #include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #ifdef HAVE_SYS_CDEFS_H
@@ -224,7 +225,8 @@ enum compress_type {
 };
 
 void decompress_cat(enum compress_type type, int fd_in, int fd_out,
-                    char *desc, ...) DPKG_ATTR_NORET DPKG_ATTR_PRINTF(4);
+                    uint64_t memlimit, char *desc, ...)
+                    DPKG_ATTR_NORET DPKG_ATTR_PRINTF(5);
 void compress_cat(enum compress_type type, int fd_in, int fd_out,
                   const char *compression, char *desc, ...)
                   DPKG_ATTR_NORET DPKG_ATTR_PRINTF(5);
diff --git a/man/dpkg-deb.1 b/man/dpkg-deb.1
index bb08dc9..37b43b3 100644
--- a/man/dpkg-deb.1
+++ b/man/dpkg-deb.1
@@ -197,6 +197,14 @@ Specify which compression type to use when building a package. Allowed
 values are \fIgzip\fP, \fIbzip2\fP, \fIlzma\fP, and \fInone\fP (default
 is \fIgzip\fP).
 .TP
+.BR \-M ", " \-\-memlimit= \fImemory_limit\fP
+Specify a maximum in bytes for memory usage when decompressing an lzma
+or xz compressed package.  The default is 40% of the installed RAM,
+clamped to at most 100 MiB and at least 10 MiB, which allows
+decompression of any package built at the default compression level.
+This option allows one to increase the limit to allow decompression of
+packages built with a higher compression level than the default.
+.TP
 .BR \-\-new
 Ensures that
 .B dpkg\-deb
--
1.6.5.rc1.199.g596ec


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST@...
with a subject of "unsubscribe". Trouble? Contact listmaster@...


[PATCH v2 3/4] dpkg: change pass_admindir to a bool

by Jonathan Nieder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This is just for clarity.  Noticed while preparing to add a
similar pass_memlimit option.

Signed-off-by: Jonathan Nieder <jrnieder@...>
---
 src/main.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main.c b/src/main.c
index 78c34c3..ff09fa0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -546,7 +546,7 @@ void execbackend(const char *const *argv) {
   int offset = 0; /* offset for copying argv strings to nargv */
   int argc = 1;   /* for nargv */
   const char *const *arg = argv;
-  int pass_admindir = 0;
+  bool pass_admindir = false;
 
   while (*arg != NULL) {
     arg++; argc++;
@@ -559,7 +559,7 @@ void execbackend(const char *const *argv) {
   if (strcmp(cipaction->parg, DPKGQUERY) == 0 &&
       strcmp(admindir, ADMINDIR) != 0) {
     argc++;
-    pass_admindir = 1;
+    pass_admindir = true;
   }
 
   nargv = m_malloc(sizeof(char *) * (argc + 3));
--
1.6.5.rc1.199.g596ec


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST@...
with a subject of "unsubscribe". Trouble? Contact listmaster@...


[PATCH v2 4/4] dpkg: add --memlimit option, passed to dpkg-deb

by Jonathan Nieder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

If the default decompression memory limit is too low for one's
purposes, it would be nice to be able to set a higher value to be
used in .dpkg.cfg.  This means dpkg should accept the --memlimit
option, too.

Most dpkg operation modes are actually dpkg-deb operation modes,
but that doesn't mean people don't use them directly.  Probably
all options that affect dpkg-deb should be passed to it, but it
is not worth making that happen until there is better
infrastructure for it.  The memlimit option is important because
if a machine with very little memory is regularly using packages
compressed with a high dictionary size, it should be possible to
set an appropriate default in .dpkg.cfg and always have it used.

Unfortunately, this change is not enough to achieve that:
if dpkg-deb is used directly, the configuration in .dpkg.cfg is
not used.

Signed-off-by: Jonathan Nieder <jrnieder@...>
---
 man/dpkg.1       |    6 ++++++
 src/main.c       |   18 ++++++++++++++++++
 src/main.h       |    1 +
 src/processarc.c |   11 ++++++++++-
 4 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/man/dpkg.1 b/man/dpkg.1
index 4bc2ec8..dcb0a1e 100644
--- a/man/dpkg.1
+++ b/man/dpkg.1
@@ -452,6 +452,12 @@ Install a package even if it fails authenticity check.
 Ignore dependency-checking for specified packages (actually, checking is
 performed, but only warnings about conflicts are given, nothing else).
 .TP
+.BR \-M ", " \-\-memlimit= \fIbytes\fR
+Override memory usage limit for decompression.  Don't refuse to read
+lzma- or xz-compressed packages unless it would require more than
+\fIbytes\fP bytes of memory.
+This option is passed to \fBdpkg\-deb\fP(1).
+.TP
 \fB\-\-new\fP, \fB\-\-old\fP
 Select new or old binary package format. This is a \fBdpkg\-deb\fP(1)
 option.
diff --git a/src/main.c b/src/main.c
index ff09fa0..969e192 100644
--- a/src/main.c
+++ b/src/main.c
@@ -136,6 +136,9 @@ usage(const struct cmdinfo *ci, const char *value)
 "  -D|--debug=<octal>         Enable debugging (see -Dhelp or --debug=help).\n"
 "  --status-fd <n>            Send status change updates to file descriptor <n>.\n"
 "  --log=<filename>           Log status changes and actions to <filename>.\n"
+"  -M|--memlimit=<n>          Don't refuse to read lzma- or xz-compressed\n"
+"                             packages unless it would require more than\n"
+"                             <n> bytes of memory (passed to dpkg-deb).\n"
 "  --ignore-depends=<package>,...\n"
 "                             Ignore dependencies involving <package>.\n"
 "  --force-...                Override problems (see --force-help).\n"
@@ -187,6 +190,7 @@ int fc_badverify = 0;
 int errabort = 50;
 const char *admindir= ADMINDIR;
 const char *instdir= "";
+const char *backend_memlimit = NULL;
 struct pkg_list *ignoredependss = NULL;
 
 static const struct forceinfo {
@@ -497,6 +501,7 @@ static const struct cmdinfo cmdinfos[]= {
   { "post-invoke",       0,   1, NULL,          NULL,      set_invoke_hook, 0, &post_invoke_hooks_tail },
   { "status-fd",         0,   1, NULL,          NULL,      setpipe, 0, &status_pipes },
   { "log",               0,   1, NULL,          &log_file, NULL,    0 },
+  { "memlimit",          'M', 1, NULL,          &backend_memlimit, NULL, 0 },
   { "pending",           'a', 0, &f_pending,    NULL,      NULL,    1 },
   { "recursive",         'R', 0, &f_recursive,  NULL,      NULL,    1 },
   { "no-act",            0,   0, &f_noact,      NULL,      NULL,    1 },
@@ -547,6 +552,7 @@ void execbackend(const char *const *argv) {
   int argc = 1;   /* for nargv */
   const char *const *arg = argv;
   bool pass_admindir = false;
+  bool pass_memlimit = false;
 
   while (*arg != NULL) {
     arg++; argc++;
@@ -561,6 +567,11 @@ void execbackend(const char *const *argv) {
     argc++;
     pass_admindir = true;
   }
+  if (strcmp(cipaction->parg, BACKEND) == 0 &&
+      backend_memlimit != NULL) {
+    argc++;
+    pass_memlimit = true;
+  }
 
   nargv = m_malloc(sizeof(char *) * (argc + 3));
   nargv[i] = m_strdup(cipaction->parg);
@@ -572,6 +583,13 @@ void execbackend(const char *const *argv) {
     sprintf(nargv[i], "--admindir=%s", admindir);
     i++, offset++;
   }
+  if (pass_memlimit) {
+    nargv[i] = m_malloc((strlen("--memlimit=") +
+                        strlen(backend_memlimit) + 1));
+    strcpy(nargv[i], "--memlimit=");
+    strcat(nargv[i], backend_memlimit);
+    i++, offset++;
+  }
 
   nargv[i] = m_malloc(2 + strlen(cipaction->olong) + 1);
   strcpy(nargv[i], "--");
diff --git a/src/main.h b/src/main.h
index cbcc2df..6181280 100644
--- a/src/main.h
+++ b/src/main.h
@@ -127,6 +127,7 @@ extern int abort_processing;
 extern int errabort;
 extern const char *admindir;
 extern const char *instdir;
+extern const char *backend_memlimit;
 extern struct pkg_list *ignoredependss;
 extern const char architecture[];
 
diff --git a/src/processarc.c b/src/processarc.c
index 2d6f320..e395239 100644
--- a/src/processarc.c
+++ b/src/processarc.c
@@ -583,7 +583,16 @@ void process_archive(const char *filename) {
   c1= m_fork();
   if (!c1) {
     m_dup2(p1[1],1); close(p1[0]); close(p1[1]);
-    execlp(BACKEND, BACKEND, "--fsys-tarfile", filename, NULL);
+    if (backend_memlimit != NULL) {
+      struct varbuf argbuf = VARBUF_INIT;
+
+      varbufprintf(&argbuf, "--memlimit=%s", backend_memlimit);
+      execlp(BACKEND, BACKEND, argbuf.buf, "--fsys-tarfile", filename, NULL);
+
+      varbuffree(&argbuf);
+    } else {
+      execlp(BACKEND, BACKEND, "--fsys-tarfile", filename, NULL);
+    }
     ohshite(_("unable to exec dpkg-deb to get filesystem archive"));
   }
   close(p1[1]);
--
1.6.5.rc1.199.g596ec


--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST@...
with a subject of "unsubscribe". Trouble? Contact listmaster@...