194 lines
6.5 KiB
Diff
194 lines
6.5 KiB
Diff
From ae3fb4def811f5bc42563128e8fae0a4288584d1 Mon Sep 17 00:00:00 2001
|
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
Date: Tue, 13 Jun 2023 20:01:05 +0100
|
|
Subject: [PATCH 03/16] 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 | 24 +++++++++++-
|
|
tests/Makefile.am | 2 +
|
|
filters/tar/tar.c | 10 +++++
|
|
tests/test-tar-limit.sh | 65 +++++++++++++++++++++++++++++++
|
|
4 files changed, 99 insertions(+), 2 deletions(-)
|
|
create mode 100755 tests/test-tar-limit.sh
|
|
|
|
diff --git a/filters/tar/nbdkit-tar-filter.pod b/filters/tar/nbdkit-tar-filter.pod
|
|
index eb0cfd4ab..a3c2d1328 100644
|
|
--- a/filters/tar/nbdkit-tar-filter.pod
|
|
+++ b/filters/tar/nbdkit-tar-filter.pod
|
|
@@ -4,8 +4,9 @@ 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=TAR_COMMAND]
|
|
+ nbdkit file FILENAME.tar
|
|
+ --filter=tar tar-entry=PATH_INSIDE_TAR
|
|
+ [tar=TAR_COMMAND] [tar-limit=SIZE]
|
|
|
|
=head1 EXAMPLES
|
|
|
|
@@ -83,6 +84,25 @@ 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..168f2c497
|
|
--- /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-limit-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.41.0
|
|
|