Richard W.M. Jones
2023-Jun-13 19:31 UTC
[Libguestfs] [PATCH nbdkit 0/3] tar: Implement tar-limit
This patch series cleans up some issues with nbdkit-tar-filter and (in patch 3) implements a new tar-limit feature which limits how much of the tar file we will read to find the entry within the tar file that we will serve. This protects against the case where a tar file is presented that contains much content at the front that we must iterate over (and download) before we get to the entry we are interested in. See also: https://github.com/kubevirt/containerized-data-importer/pull/2748#issuecomment-1589852102 Rich.
Richard W.M. Jones
2023-Jun-13 19:31 UTC
[Libguestfs] [PATCH nbdkit 1/3] tests/test-tar-info*: Remove bogus test requires of guestfish
These tests don't need guestfish so don't test for it. Fixes: commit 05b49f89dccb0ca3fd0919e9502c54dbcadf0b73 --- tests/test-tar-info-xz.sh | 1 - tests/test-tar-info.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/test-tar-info-xz.sh b/tests/test-tar-info-xz.sh index 1f968e9b8..abd854974 100755 --- a/tests/test-tar-info-xz.sh +++ b/tests/test-tar-info-xz.sh @@ -37,7 +37,6 @@ set -e set -x requires test -f disk -requires guestfish --version requires tar --version requires qemu-img --version requires qemu-img info --output=json /dev/null diff --git a/tests/test-tar-info.sh b/tests/test-tar-info.sh index 572768b85..5c015d88e 100755 --- a/tests/test-tar-info.sh +++ b/tests/test-tar-info.sh @@ -37,7 +37,6 @@ set -e set -x requires test -f disk -requires guestfish --version requires tar --version requires qemu-img --version requires qemu-img info --output=json /dev/null -- 2.40.1
Richard W.M. Jones
2023-Jun-13 19:31 UTC
[Libguestfs] [PATCH nbdkit 2/3] tar: Document the optional tar option in --help output
--- filters/tar/tar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/filters/tar/tar.c b/filters/tar/tar.c index c650a3499..f3adb2c46 100644 --- a/filters/tar/tar.c +++ b/filters/tar/tar.c @@ -96,8 +96,9 @@ tar_config_complete (nbdkit_next_config_complete *next, return next (nxdata); } -#define tar_config_help \ - "tar-entry=<FILENAME> (required) The path inside the tar file to serve." +#define tar_config_help \ + "tar-entry=<FILENAME> (required) The path inside the tar file to serve.\n" \ + "tar=<PATH> Path of the tar binary." static int tar_thread_model (void) -- 2.40.1
Richard W.M. Jones
2023-Jun-13 19:31 UTC
[Libguestfs] [PATCH nbdkit 3/3] tar: Implement tar-limit
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