From f61e061cedbd01a9aeec9143532ed7efbf550edf Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 29 Jun 2026 09:37:03 +0000 Subject: [PATCH] Import from CS git --- SOURCES/RHEL-181654.patch | 174 ++++++++++++++++++++++++++++++++++++ SPECS/perl-Archive-Tar.spec | 11 ++- 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 SOURCES/RHEL-181654.patch diff --git a/SOURCES/RHEL-181654.patch b/SOURCES/RHEL-181654.patch new file mode 100644 index 0000000..7e65371 --- /dev/null +++ b/SOURCES/RHEL-181654.patch @@ -0,0 +1,174 @@ +From e4fb3394d935b68ddb36cc6c543cbecd8e9875b5 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 e08b5e5..d4a6d56 100644 +--- a/lib/Archive/Tar.pm ++++ b/lib/Archive/Tar.pm +@@ -918,6 +918,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++; +@@ -931,6 +944,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 4991d9a..c7dc0f8 100644 +--- a/t/04_resolved_issues.t ++++ b/t/04_resolved_issues.t +@@ -216,6 +216,7 @@ use_ok( $FileClass ); + } + + { #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 }; +@@ -227,6 +228,7 @@ use_ok( $FileClass ); + + { #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 9ab74ba586a2328207da232f390968057a9a0ef6 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 d4a6d56..5b968c8 100644 +--- a/lib/Archive/Tar.pm ++++ b/lib/Archive/Tar.pm +@@ -925,7 +925,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; +@@ -953,7 +953,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 ] . +@@ -1964,7 +1964,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 +@@ -1977,6 +1977,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 3d7b406..db7a3bd 100644 +--- a/t/90_symlink.t ++++ b/t/90_symlink.t +@@ -26,6 +26,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/SPECS/perl-Archive-Tar.spec b/SPECS/perl-Archive-Tar.spec index 53d7828..45e21c5 100644 --- a/SPECS/perl-Archive-Tar.spec +++ b/SPECS/perl-Archive-Tar.spec @@ -7,13 +7,16 @@ Name: perl-Archive-Tar Version: 2.30 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A module for Perl manipulation of .tar files License: GPL+ or Artistic 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-181654.patch BuildArch: noarch # Most of the BRS are needed only for tests, compression support at run-time # is optional soft dependency. @@ -88,6 +91,7 @@ will also support compressed or gzipped tar files. %prep %setup -q -n Archive-Tar-%{version} %patch0 -p1 +%patch1 -p1 %build perl Makefile.PL INSTALLDIRS=vendor NO_PACKLIST=1 @@ -109,6 +113,11 @@ make test %changelog +* Fri Jun 05 2026 RHEL Packaging Agent - 2.30-2 +- Fix CVE-2026-42496: validate symlink and hardlink targets in secure + extract mode +- Resolves: RHEL-181654 + * Tue Jun 19 2018 Jitka Plesnikova - 2.30-1 - 2.30 bump