This can be used to ensure that the tar filter does not read
indefinite amounts of input when opening the tar file.

See: 
https://github.com/kubevirt/containerized-data-importer/pull/2748#issuecomment-1589852102
---
 filters/tar/nbdkit-tar-filter.pod | 19 +++++++++
 tests/Makefile.am                 |  2 +
 filters/tar/tar.c                 | 10 +++++
 tests/test-tar-limit.sh           | 65 +++++++++++++++++++++++++++++++
 4 files changed, 96 insertions(+)

diff --git a/filters/tar/nbdkit-tar-filter.pod 
b/filters/tar/nbdkit-tar-filter.pod
index 96aba16d9..f032d7cc3 100644
--- a/filters/tar/nbdkit-tar-filter.pod
+++ b/filters/tar/nbdkit-tar-filter.pod
@@ -5,6 +5,7 @@ nbdkit-tar-filter - read and write files inside tar files 
without unpacking
 =head1 SYNOPSIS
 
  nbdkit file FILENAME.tar --filter=tar tar-entry=PATH_INSIDE_TAR
+                                       [tar-limit=SIZE]
 
 =head1 EXAMPLES
 
@@ -82,6 +83,24 @@ The path of the file inside the tarball to serve.  This 
parameter is
 required.  It must exactly match the name stored in the tarball, so
 use S<C<tar tf filename.tar>>
 
+=item [B<tar-limit=>]SIZE
+
+When opening the tar file we have to locate the file (C<tar-entry>)
+inside the tarball.  Because tar files do not have a central index we
+must iterate over the tar file to find the entry, and that may be
+costly (especially with untrusted tar files).  In the worst case where
+C<tar-entry> starts near the end of the file we may have to iterate
+over the whole tar file.  If this is a problem you may set
+C<tar-limit> to some smaller value, eg:
+
+ nbdkit -r curl https://example.com/file.tar \
+        --filter=tar tar-entry=disk.img tar-limit=10M
+
+which ensures no more than 10 megabytes are read before we give up and
+reject the tar file (sending an error back to the NBD client).
+
+The default is 0 meaning no limit.
+
 =item B<tar=gtar>
 
 =item B<tar=>/PATH/TO/GTAR
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6694e409e..f2912aa93 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1957,11 +1957,13 @@ TESTS += \
        test-tar.sh \
        test-tar-info.sh \
        test-tar-info-xz.sh \
+       test-tar-limit.sh \
        $(NULL)
 EXTRA_DIST += \
        test-tar.sh \
        test-tar-info.sh \
        test-tar-info-xz.sh \
+       test-tar-limit.sh \
        $(NULL)
 
 # truncate filter tests.
diff --git a/filters/tar/tar.c b/filters/tar/tar.c
index f3adb2c46..efe47684d 100644
--- a/filters/tar/tar.c
+++ b/filters/tar/tar.c
@@ -53,6 +53,7 @@
 #include "utils.h"
 
 static const char *entry;       /* File within tar (tar-entry=...) */
+static int64_t tar_limit = 0;
 static const char *tar_program = "tar";
 
 /* Offset and size within tarball.
@@ -76,6 +77,12 @@ tar_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
     entry = value;
     return 0;
   }
+  else if (strcmp (key, "tar-limit") == 0) {
+    tar_limit = nbdkit_parse_size (value);
+    if (tar_limit == -1)
+      return -1;
+    return 0;
+  }
   else if (strcmp (key, "tar") == 0) {
     tar_program = value;
     return 0;
@@ -98,6 +105,7 @@ tar_config_complete (nbdkit_next_config_complete *next,
 
 #define tar_config_help                                                 \
   "tar-entry=<FILENAME> (required) The path inside the tar file to serve.\n" \
+  "tar-limit=SIZE                  Limit on reading to find entry.\n" \
   "tar=<PATH>                      Path of the tar binary."
 
 static int
@@ -197,6 +205,8 @@ calculate_offset_of_entry (nbdkit_next *next)
   copysize = next->get_size (next);
   if (copysize == -1)
     return -1;
+  if (tar_limit > 0 && copysize > tar_limit)
+    copysize = tar_limit;
 
   /* Run the tar command. */
   nbdkit_debug ("%s", cmd);
diff --git a/tests/test-tar-limit.sh b/tests/test-tar-limit.sh
new file mode 100755
index 000000000..2eba69324
--- /dev/null
+++ b/tests/test-tar-limit.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Test the tar filter and tar-limit filter.
+
+source ./functions.sh
+set -e
+set -x
+
+requires test -f disk
+requires tar --version
+requires test -f disk
+requires_nbdinfo
+
+tar_bad=tar-limit-bad.tar
+tar_good=tar-limit-good.tar
+tar_filler=tar-filler.img
+files="$tar_bad $tar_good $tar_filler"
+rm -f $files
+cleanup_fn rm -f $files
+
+# Create two tar files, one where the disk is located before an
+# arbitrary boundary and one after.
+truncate -s 1M $tar_filler
+tar cf $tar_good disk
+tar cf $tar_bad $tar_filler disk
+
+# Check we can read the good disk and reject the bad disk.
+cmd="nbdkit -U - file --filter=tar tar-entry=disk tar-limit=131072"
+
+$cmd $tar_good --run 'nbdinfo "$uri"'
+
+if $cmd $tar_bad --run 'nbdinfo "$uri"' ; then
+    echo "ERROR: $0: expected $tar_bad to fail"
+    exit 1
+fi
-- 
2.40.1

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to