From 6c8f1bb7e0377dfab6cd8ce1b8db9099fd5d8ff7 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Mon, 25 Nov 2024 09:56:34 +0800 Subject: [PATCH] Fix CVE-2024-10224 (cherry picked from commit 0ecb3c7e547cd72f420ee077802f28a1c6af52d4) --- ...4-10224-0001-use-three-argument-open.patch | 20 +++ ...4-10224-0002-replace-eval-constructs.patch | 139 ++++++++++++++++++ ...024-10224-0003-fix-parsing-of-use-if.patch | 31 ++++ perl-Module-ScanDeps.spec | 12 +- 4 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 CVE-2024-10224-0001-use-three-argument-open.patch create mode 100644 CVE-2024-10224-0002-replace-eval-constructs.patch create mode 100644 CVE-2024-10224-0003-fix-parsing-of-use-if.patch diff --git a/CVE-2024-10224-0001-use-three-argument-open.patch b/CVE-2024-10224-0001-use-three-argument-open.patch new file mode 100644 index 0000000..13cdd73 --- /dev/null +++ b/CVE-2024-10224-0001-use-three-argument-open.patch @@ -0,0 +1,20 @@ +From 9a46eab1c78656386ba9d18bc4b341f4b2561635 Mon Sep 17 00:00:00 2001 +From: rschupp +Date: Mon, 21 Oct 2024 14:03:19 +0200 +Subject: [PATCH] use three-argument open() + +--- + lib/Module/ScanDeps.pm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/lib/Module/ScanDeps.pm ++++ b/lib/Module/ScanDeps.pm +@@ -810,7 +810,7 @@ sub scan_file{ + my $file = shift; + my %found; + my $FH; +- open $FH, $file or die "Cannot open $file: $!"; ++ open $FH, "<", $file or die "Cannot open $file: $!"; + + $SeenTk = 0; + # Line-by-line scanning diff --git a/CVE-2024-10224-0002-replace-eval-constructs.patch b/CVE-2024-10224-0002-replace-eval-constructs.patch new file mode 100644 index 0000000..7be04f1 --- /dev/null +++ b/CVE-2024-10224-0002-replace-eval-constructs.patch @@ -0,0 +1,139 @@ +From bc57e5072fc7ace1d206246999dd852652939335 Mon Sep 17 00:00:00 2001 +From: rschupp +Date: Mon, 21 Oct 2024 14:08:01 +0200 +Subject: [PATCH] replace 'eval "..."' constructs + +--- + lib/Module/ScanDeps.pm | 122 ++++++++++++++++++++++++++--------------- + 1 file changed, 78 insertions(+), 44 deletions(-) + +--- a/lib/Module/ScanDeps.pm ++++ b/lib/Module/ScanDeps.pm +@@ -880,41 +880,26 @@ sub scan_line { + # be specified for the "autouse" and "if" pragmas, e.g. + # use autouse Module => qw(func1 func2); + # use autouse "Module", qw(func1); +- # To avoid to parse them ourself, we simply try to eval the +- # string after the pragma (in a list context). The MODULE +- # should be the first ("autouse") or second ("if") element +- # of the list. + my $module; +- { +- no strict; no warnings; +- if ($pragma eq "autouse") { +- ($module) = eval $args; +- } +- else { +- # The syntax of the "if" pragma is +- # use if COND, MODULE => ARGUMENTS +- # The COND may contain undefined functions (i.e. undefined +- # in Module::ScanDeps' context) which would throw an +- # exception. Sneak "1 || " in front of COND so that +- # COND will not be evaluated. This will work in most +- # cases, but there are operators with lower precedence +- # than "||" which will cause this trick to fail. +- (undef, $module) = eval "1 || $args"; +- } +- # punt if there was a syntax error +- return if $@ or !defined $module; +- }; +- $module =~ s{::}{/}g; +- $found{"$pragma.pm"}++; +- $found{"$module.pm"}++; ++ if ($pragma eq "autouse") { ++ ($module) = _parse_module_list($args); ++ } ++ else { ++ # The syntax of the "if" pragma is ++ # use if COND, MODULE => ARGUMENTS ++ (undef, $module) = _parse_module_list($args); ++ } ++ $found{_mod2pm($pragma)}++; ++ $found{_mod2pm($module)}++ if $module; + next CHUNK; + } + +- if (my ($how, $libs) = /^(use \s+ lib \s+ | (?:unshift|push) \s+ \@INC \s+ ,) (.+)/x) ++ if (my ($how, $libs) = /^(use \s+ lib \s+ | (?:unshift|push) \s+ \@INC \s*,\s*) (.+)/x) + { + my $archname = defined($Config{archname}) ? $Config{archname} : ''; + my $ver = defined($Config{version}) ? $Config{version} : ''; +- foreach my $dir (do { no strict; no warnings; eval $libs }) { ++ while ((my $dir, $libs) = _parse_libs($libs)) ++ { + next unless defined $dir; + my @dirs = $dir; + push @dirs, "$dir/$ver", "$dir/$archname", "$dir/$ver/$archname" +@@ -932,6 +917,72 @@ sub scan_line { + return sort keys %found; + } + ++# convert module name to file name ++sub _mod2pm { ++ my $mod = shift; ++ $mod =~ s!::!/!g; ++ return "$mod.pm"; ++} ++ ++# parse a comma-separated list of module names (as string literals or qw() lists) ++sub _parse_module_list { ++ my $list = shift; ++ ++ # split $list on anything that's not a word character or ":" ++ # and ignore "q", "qq" and "qw" ++ return grep { length and !/^:|^q[qw]?$/ } split(/[^\w:]+/, $list); ++} ++ ++# incrementally parse a comma separated list library paths: ++# returning a pair: the contents of the first strings literal and the remainder of the string ++# - for "string", 'string', q/string/, qq/string/ also unescape \\ and \) ++# - for qw(foo bar quux) return ("foo", qw(bar quux)) ++# - otherwise skip over the first comma and return (undef, "remainder") ++# - return () if the string is exhausted ++# - as a special case, if the string starts with $FindBin::Bin, replace it with our $Bin ++sub _parse_libs { ++ local $_ = shift; ++ ++ s/^[\s,]*//; ++ return if $_ eq ""; ++ ++ if (s/^(['"]) ((?:\\.|.)*?) \1//x) { ++ return (_unescape($1, $2), $_); ++ } ++ if (s/^qq? \s* (\W)//x) { ++ my $opening_delim = $1; ++ (my $closing_delim = $opening_delim) =~ tr:([{<:)]}>:; ++ s/^((?:\\.|.)*?) \Q$closing_delim\E//x; ++ return (_unescape($opening_delim, $1), $_); ++ } ++ ++ if (s/^qw \s* (\W)//x) { ++ my $opening_delim = $1; ++ (my $closing_delim = $opening_delim) =~ tr:([{<:)]}>:; ++ s/^((?:\\.|.)*?) \Q$closing_delim\E//x; ++ my $contents = $1; ++ my @list = split(" ", $contents); ++ return (undef, $_) unless @list; ++ my $first = shift @list; ++ return (_unescape($opening_delim, $first), ++ @list ? "qw${opening_delim}@list${closing_delim}$_" : $_); ++ } ++ ++ # nothing recognizable in the first list item, skip to the next ++ if (s/^.*? ,//x) { ++ return (undef, $_); ++ } ++ return; # list exhausted ++} ++ ++sub _unescape { ++ my ($delim, $str) = @_; ++ $str =~ s/\\([\\\Q$delim\E])/$1/g; ++ $str =~ s/^\$FindBin::Bin\b/$FindBin::Bin/; ++ ++ return $str; ++} ++ + # short helper for scan_chunk + my %LoaderRegexp; # cache + sub _build_loader_regexp { diff --git a/CVE-2024-10224-0003-fix-parsing-of-use-if.patch b/CVE-2024-10224-0003-fix-parsing-of-use-if.patch new file mode 100644 index 0000000..0eaac8f --- /dev/null +++ b/CVE-2024-10224-0003-fix-parsing-of-use-if.patch @@ -0,0 +1,31 @@ +From 90476aae7c2b5ef7d94ac1b22672ca8dc4adae20 Mon Sep 17 00:00:00 2001 +From: rschupp +Date: Thu, 14 Nov 2024 23:09:10 +0100 +Subject: [PATCH] fix parsing of "use if ..." + +--- + lib/Module/ScanDeps.pm | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/lib/Module/ScanDeps.pm ++++ b/lib/Module/ScanDeps.pm +@@ -874,7 +874,7 @@ sub scan_line { + } + } + +- if (my ($pragma, $args) = /^use \s+ (autouse|if) \s+ (.+)/x) ++ if (my ($pragma, $args) = /^(?:use|no) \s+ (autouse|if) \s+ (.+)/x) + { + # NOTE: There are different ways the MODULE may + # be specified for the "autouse" and "if" pragmas, e.g. +@@ -887,7 +887,9 @@ sub scan_line { + else { + # The syntax of the "if" pragma is + # use if COND, MODULE => ARGUMENTS +- (undef, $module) = _parse_module_list($args); ++ # NOTE: This works only for simple conditions. ++ $args =~ s/.*? (?:,|=>) \s*//x; ++ ($module) = _parse_module_list($args); + } + $found{_mod2pm($pragma)}++; + $found{_mod2pm($module)}++ if $module; diff --git a/perl-Module-ScanDeps.spec b/perl-Module-ScanDeps.spec index 0e5b701..a11add0 100644 --- a/perl-Module-ScanDeps.spec +++ b/perl-Module-ScanDeps.spec @@ -1,12 +1,17 @@ Name: perl-Module-ScanDeps Version: 1.31 -Release: 1 +Release: 2 Summary: Recursively scan Perl code for dependencies License: GPL+ or Artistic URL: https://metacpan.org/release/Module-ScanDeps Source0: https://cpan.metacpan.org/authors/id/R/RS/RSCHUPP/Module-ScanDeps-%{version}.tar.gz +# https://sources.debian.org/src/libmodule-scandeps-perl/1.31-2%2Bdeb12u1/debian/patches/ +Patch0: CVE-2024-10224-0001-use-three-argument-open.patch +Patch1: CVE-2024-10224-0002-replace-eval-constructs.patch +Patch2: CVE-2024-10224-0003-fix-parsing-of-use-if.patch + BuildArch: noarch BuildRequires: make perl-interpreter perl-generators perl(ExtUtils::MakeMaker) >= 6.76 perl(strict) BuildRequires: perl(warnings) perl(B) perl(Config) perl(constant) perl(Cwd) perl(Data::Dumper) perl(DynaLoader) @@ -26,7 +31,7 @@ names as appears in %INC (e.g. Test/More.pm); the values are hash references. %package_help %prep -%autosetup -n Module-ScanDeps-%{version} +%autosetup -n Module-ScanDeps-%{version} -p1 %build perl Makefile.PL INSTALLDIRS=vendor NO_PACKLIST=1 @@ -53,6 +58,9 @@ make test %{_mandir}/man3/Module::ScanDeps.3pm* %changelog +* Mon Nov 25 2024 yaoxin - 1.31-2 +- Fix CVE-2024-10224 + * Tue Jun 14 2022 SimpleUpdate Robot - 1.31-1 - Upgrade to version 1.31