From 62da0f8377ff52a7997bc3cab0842449ce3bf845 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 29 Jun 2026 13:58:56 -0400 Subject: [PATCH] import UBI perl-Archive-Tar-3.02-512.el10_2.1 --- RHEL-181651.patch | 174 ++++++++++++++++++++++++++++++++++++++++++ perl-Archive-Tar.spec | 11 ++- 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 RHEL-181651.patch diff --git a/RHEL-181651.patch b/RHEL-181651.patch new file mode 100644 index 0000000..068ad2c --- /dev/null +++ b/RHEL-181651.patch @@ -0,0 +1,174 @@ +From 77c4c507bf91a1821ed3f3bc23718ca5e992cc5a Mon Sep 17 00:00:00 2001 +From: Stig Palmquist +Date: Thu, 21 May 2026 19:59:21 +0100 +Subject: [PATCH 1/2] Validate symlink and hardlink linkname in SECURE MODE + +Signed-off-by: Chris 'BinGOs' Williams +--- + lib/Archive/Tar.pm | 30 ++++++++++++++++++++++++++++++ + t/04_resolved_issues.t | 2 ++ + 2 files changed, 32 insertions(+) + +diff --git a/lib/Archive/Tar.pm b/lib/Archive/Tar.pm +index a2ac409..acded30 100644 +--- a/lib/Archive/Tar.pm ++++ b/lib/Archive/Tar.pm +@@ -954,6 +954,19 @@ sub _make_special_file { + my $err; + + if( $entry->is_symlink ) { ++ if( !$INSECURE_EXTRACT_MODE ) { ++ my $linkname = $entry->linkname; ++ if( File::Spec->file_name_is_absolute($linkname) ) { ++ $self->_error( qq[Symlink '] . $entry->full_path . ++ qq[' has absolute target. Not extracting under SECURE EXTRACT MODE] ); ++ return; ++ } ++ if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) { ++ $self->_error( qq[Symlink '] . $entry->full_path . ++ qq[' target attempts traversal. Not extracting under SECURE EXTRACT MODE] ); ++ return; ++ } ++ } + my $fail; + if( ON_UNIX ) { + symlink( $entry->linkname, $file ) or $fail++; +@@ -967,6 +980,23 @@ sub _make_special_file { + $entry->linkname .q[' failed] if $fail; + + } elsif ( $entry->is_hardlink ) { ++ if( !$INSECURE_EXTRACT_MODE ) { ++ my $linkname = $entry->linkname; ++ if( File::Spec->file_name_is_absolute($linkname) ) { ++ $self->_error( qq[Hardlink '] . $entry->full_path . ++ qq[' has absolute target '$linkname'. Not extracting ] . ++ qq[under SECURE EXTRACT MODE: extraction itself chmods ] . ++ qq[the shared inode.] ); ++ return; ++ } ++ if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) { ++ $self->_error( qq[Hardlink '] . $entry->full_path . ++ qq[' target '$linkname' attempts traversal. Not ] . ++ qq[extracting under SECURE EXTRACT MODE: extraction ] . ++ qq[itself chmods the shared inode.] ); ++ return; ++ } ++ } + my $fail; + if( ON_UNIX ) { + link( $entry->linkname, $file ) or $fail++; +diff --git a/t/04_resolved_issues.t b/t/04_resolved_issues.t +index b7e7860..7e64a07 100644 +--- a/t/04_resolved_issues.t ++++ b/t/04_resolved_issues.t +@@ -220,6 +220,7 @@ if ($^O ne 'msys') # symlink tests fail on Windows/msys2 + } + + { #use case 1 - in memory extraction ++ local $Archive::Tar::INSECURE_EXTRACT_MODE=1; + my $t=Archive::Tar->new; + $t->read( $archname ); + my $r = eval{ $t->extract }; +@@ -231,6 +232,7 @@ if ($^O ne 'msys') # symlink tests fail on Windows/msys2 + + { #use case 2 - iter extraction + #$DB::single = 2; ++ local $Archive::Tar::INSECURE_EXTRACT_MODE=1; + my $next=Archive::Tar->iter( $archname, 1 ); + my $failed = 0; + #use Data::Dumper; +-- +2.52.0 + + +From cbe4e5dba3cff60f294f361487ebba5455a12944 Mon Sep 17 00:00:00 2001 +From: Stig Palmquist +Date: Tue, 2 Jun 2026 16:09:03 +0200 +Subject: [PATCH 2/2] Allow `..` links in secure extract in parent path + +Assisted-by: OpenAI Codex +Signed-off-by: Stig Palmquist +--- + lib/Archive/Tar.pm | 7 ++++--- + t/90_symlink.t | 26 ++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/lib/Archive/Tar.pm b/lib/Archive/Tar.pm +index acded30..c21e216 100644 +--- a/lib/Archive/Tar.pm ++++ b/lib/Archive/Tar.pm +@@ -961,7 +961,7 @@ sub _make_special_file { + qq[' has absolute target. Not extracting under SECURE EXTRACT MODE] ); + return; + } +- if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) { ++ if( !defined _symlinks_resolver( $entry->full_path, $linkname, 1 ) ) { + $self->_error( qq[Symlink '] . $entry->full_path . + qq[' target attempts traversal. Not extracting under SECURE EXTRACT MODE] ); + return; +@@ -989,7 +989,7 @@ sub _make_special_file { + qq[the shared inode.] ); + return; + } +- if( grep { $_ eq '..' } File::Spec->splitdir($linkname) ) { ++ if( !defined _symlinks_resolver( $entry->full_path, $linkname, 1 ) ) { + $self->_error( qq[Hardlink '] . $entry->full_path . + qq[' target '$linkname' attempts traversal. Not ] . + qq[extracting under SECURE EXTRACT MODE: extraction ] . +@@ -2014,7 +2014,7 @@ sub no_string_support { + } + + sub _symlinks_resolver{ +- my ($src, $trg) = @_; ++ my ($src, $trg, $strict) = @_; + my @src = split /[\/\\]/, $src; + my @trg = split /[\/\\]/, $trg; + pop @src; #strip out current object name +@@ -2027,6 +2027,7 @@ sub _symlinks_resolver{ + next if $part eq '.'; #ignore current + if($part eq '..'){ + #got to parent ++ return if $strict && !@src; + pop @src; + } + else{ +diff --git a/t/90_symlink.t b/t/90_symlink.t +index 359ad39..5c740b6 100644 +--- a/t/90_symlink.t ++++ b/t/90_symlink.t +@@ -30,6 +30,32 @@ my %Map = ( + + use_ok( $Class ); + ++{ ++ my $tar = $Class->new; ++ $tar->add_data( '.github/README.md', '', ++ { type => 2, linkname => '../README' } ); ++ ++ local $Archive::Tar::INSECURE_EXTRACT_MODE = 0; ++ ok( $tar->extract_file( '.github/README.md' ), ++ "Extracted symlink target that stays under cwd" ); ++ ++ unlink File::Spec->catfile( qw[.github README.md] ); ++ rmtree( '.github' ); ++} ++ ++{ ++ my $tar = $Class->new; ++ $tar->add_data( 'safe/link', '', ++ { type => 2, linkname => '../../outside' } ); ++ ++ local $Archive::Tar::INSECURE_EXTRACT_MODE = 0; ++ local $Archive::Tar::WARN = 0; ++ ok( !$tar->extract_file( 'safe/link' ), ++ "Refused symlink target escaping cwd" ); ++ ++ rmtree( 'safe' ); ++} ++ + { while( my($file, $aref) = each %Map ) { + + for my $mode ( 0, 1 ) { +-- +2.52.0 + diff --git a/perl-Archive-Tar.spec b/perl-Archive-Tar.spec index 8ce6d8f..d8c0877 100644 --- a/perl-Archive-Tar.spec +++ b/perl-Archive-Tar.spec @@ -7,13 +7,16 @@ Name: perl-Archive-Tar Version: 3.02 -Release: 512%{?dist} +Release: 512%{?dist}.1 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 Source0: https://cpan.metacpan.org/authors/id/B/BI/BINGOS/Archive-Tar-%{version}.tar.gz # Remove annoying sleep after warnings in the build script 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: RHEL-181651.patch BuildArch: noarch # Most of the BRS are needed only for tests, compression support at run-time # is optional soft dependency. @@ -107,6 +110,7 @@ with "%{_libexecdir}/%{name}/test". %prep %setup -q -n Archive-Tar-%{version} %patch -P0 -p1 +%patch -P1 -p1 # Help generators to recognize Perl scripts for F in t/*.t; do @@ -158,6 +162,11 @@ make test %{_libexecdir}/%{name} %changelog +* Fri Jun 05 2026 RHEL Packaging Agent - 3.02-512.1 +- Fix CVE-2026-42496: validate symlink and hardlink targets in secure + extract mode +- Resolves: RHEL-181651 + * Tue Oct 29 2024 Troy Dawson - 3.02-512 - Bump release for October 2024 mass rebuild: Resolves: RHEL-64018