Fix CVE-2026-9538: cap per-entry declared size to prevent memory DoS
Backport upstream fix (commit f9af014) for CVE-2026-9538 which
adds a $MAX_FILE_SIZE cap (default 1 GiB) checked per entry
in _read_tar() to defend against attacker-controlled size-field
memory denial of service. A malicious tar archive with a small
compressed payload but a huge declared entry size could trigger
multi-GB memory allocation before the read completes.
CVE: CVE-2026-9538
Upstream patches:
- f9af014260.patch
Resolves: RHEL-191919
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
This commit is contained in:
parent
3af7e02570
commit
8771fc464c
73
perl-Archive-Tar-3.02-CVE-2026-9538.patch
Normal file
73
perl-Archive-Tar-3.02-CVE-2026-9538.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From fab9cd792f450b74f8dc6041572fb927454d673c Mon Sep 17 00:00:00 2001
|
||||
From: Stig Palmquist <stig@stig.io>
|
||||
Date: Mon, 25 May 2026 19:11:34 +0100
|
||||
Subject: [PATCH] Cpan entry size during read
|
||||
|
||||
Cap entry size during read to defend against attacker-controlled
|
||||
size-field memory DoS
|
||||
|
||||
The tar header's 12-byte size field is attacker-controlled. Archive::Tar's
|
||||
non-skip extract path at Tar.pm:501 allocates a Perl scalar of the declared
|
||||
size before returning the read-short error, allowing a few-KB compressed
|
||||
archive declaring a 100 GB inner entry to trigger immediate multi-GB
|
||||
allocation. The existing $EXTRACT_BLOCK_SIZE is an output-side syswrite
|
||||
chunk size, not an input cap.
|
||||
|
||||
Add $MAX_FILE_SIZE (default 1 GiB) checked once per entry, gating both the
|
||||
chunked-skip and full-slurp branches. Set to 0 to disable the cap.
|
||||
|
||||
Signed-off-by: Chris 'BinGOs' Williams <chris@bingosnet.co.uk>
|
||||
---
|
||||
lib/Archive/Tar.pm | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/Archive/Tar.pm b/lib/Archive/Tar.pm
|
||||
index c21e216..a34c80d 100644
|
||||
--- a/lib/Archive/Tar.pm
|
||||
+++ b/lib/Archive/Tar.pm
|
||||
@@ -24,7 +24,7 @@ use strict;
|
||||
use vars qw[$DEBUG $error $VERSION $WARN $FOLLOW_SYMLINK $CHOWN $CHMOD
|
||||
$DO_NOT_USE_PREFIX $HAS_PERLIO $HAS_IO_STRING $SAME_PERMISSIONS
|
||||
$INSECURE_EXTRACT_MODE $ZERO_PAD_NUMBERS @ISA @EXPORT $RESOLVE_SYMLINK
|
||||
- $EXTRACT_BLOCK_SIZE
|
||||
+ $EXTRACT_BLOCK_SIZE $MAX_FILE_SIZE
|
||||
];
|
||||
|
||||
@ISA = qw[Exporter];
|
||||
@@ -41,6 +41,7 @@ $INSECURE_EXTRACT_MODE = 0;
|
||||
$ZERO_PAD_NUMBERS = 0;
|
||||
$RESOLVE_SYMLINK = $ENV{'PERL5_AT_RESOLVE_SYMLINK'} || 'speed';
|
||||
$EXTRACT_BLOCK_SIZE = 1024 * 1024 * 1024;
|
||||
+$MAX_FILE_SIZE = 1024 * 1024 * 1024;
|
||||
|
||||
BEGIN {
|
||||
use Config;
|
||||
@@ -444,6 +445,14 @@ sub _read_tar {
|
||||
|
||||
my $block = BLOCK_SIZE->( $entry->size );
|
||||
|
||||
+ if ( $MAX_FILE_SIZE && $entry->size > $MAX_FILE_SIZE ) {
|
||||
+ $self->_error( qq[Entry '] . $entry->full_path .
|
||||
+ qq[' declared size ] . $entry->size .
|
||||
+ qq[ bytes exceeds \$Archive::Tar::MAX_FILE_SIZE ] .
|
||||
+ qq[($MAX_FILE_SIZE); refusing to allocate] );
|
||||
+ next LOOP;
|
||||
+ }
|
||||
+
|
||||
$data = $entry->get_content_by_ref;
|
||||
|
||||
my $skip = 0;
|
||||
@@ -2218,6 +2227,13 @@ cannot be arbitrarily large since some operating systems limit the number of
|
||||
bytes that can be written in one call to C<write(2)>, so if this is too large,
|
||||
extraction may fail with an error.
|
||||
|
||||
+=head2 $Archive::Tar::MAX_FILE_SIZE
|
||||
+
|
||||
+This variable holds an upper bound on the per-entry declared size that
|
||||
+C<Archive::Tar> will accept when reading an archive. Entries whose header
|
||||
+claims a larger size are refused with an error before any read allocation.
|
||||
+Defaults to 1 GiB. Set to 0 to disable the cap.
|
||||
+
|
||||
=cut
|
||||
|
||||
=head1 FAQ
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
Name: perl-Archive-Tar
|
||||
Version: 3.02
|
||||
Release: 513%{?dist}
|
||||
Release: 514%{?dist}
|
||||
Summary: A module for Perl manipulation of .tar files
|
||||
License: GPL-1.0-or-later OR Artistic-1.0-Perl
|
||||
URL: https://metacpan.org/release/Archive-Tar
|
||||
@ -19,6 +19,10 @@ Patch0: Archive-Tar-2.02-Do-not-sleep-in-Makefile.PL.patch
|
||||
# https://github.com/jib/archive-tar-new/commit/17c873492a05eddc0de18c1485e0b2cccd5a9158
|
||||
# https://github.com/jib/archive-tar-new/commit/484f71ea0189ed46690f50dc7ee71d4b8bc0e70f
|
||||
Patch1: perl-Archive-Tar-3.02-RHEL-181653.patch
|
||||
# https://issues.redhat.com/browse/RHEL-191919
|
||||
# CVE-2026-9538
|
||||
# https://github.com/jib/archive-tar-new/commit/f9af01426038e29d9578825a0cd3626946ab08c7
|
||||
Patch2: perl-Archive-Tar-3.02-CVE-2026-9538.patch
|
||||
BuildArch: noarch
|
||||
# Most of the BRS are needed only for tests, compression support at run-time
|
||||
# is optional soft dependency.
|
||||
@ -113,6 +117,7 @@ with "%{_libexecdir}/%{name}/test".
|
||||
%setup -q -n Archive-Tar-%{version}
|
||||
%patch -P0 -p1
|
||||
%patch -P1 -p1
|
||||
%patch -P2 -p1
|
||||
|
||||
# Help generators to recognize Perl scripts
|
||||
for F in t/*.t; do
|
||||
@ -164,6 +169,11 @@ make test
|
||||
%{_libexecdir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Mon Aug 03 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 3.02-514
|
||||
- Fix memory DoS via attacker-controlled tar entry size field
|
||||
(CVE-2026-9538)
|
||||
Resolves: RHEL-191919
|
||||
|
||||
* Wed Jul 29 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 3.02-513
|
||||
- Fix symlink and hardlink path traversal in secure extract mode
|
||||
(CVE-2026-42496, CVE-2026-42497)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user