Control: tags 1087882 + patch Control: tags 1087882 + pending Dear maintainer,
I've prepared an NMU for needrestart (versioned as 3.8-0.1) and uploaded it to DELAYED/10. Please feel free to tell me if I should delay it longer. Regards.
diff -Nru needrestart-3.7/ChangeLog needrestart-3.8/ChangeLog --- needrestart-3.7/ChangeLog 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/ChangeLog 2024-11-18 16:46:03.000000000 -0500 @@ -1,3 +1,54 @@ +needrestart 3.8 + + * Security: + - [Core] CVE-2024-48991: Prevent race condition on /proc/$PID/exec evaluation. + (responsibly reported by Qualys) + - [Interp] CVE-2024-11003: Drop usage of Module::ScanDeps to prevent LPE. + (responsibly reported by Qualys) + - [Interp] CVE-2024-48990: Do not set PYTHONPATH environment variable to prevent a LPE. + (responsibly reported by Qualys) + - [Interp] CVE-2024-48992: Do not set RUBYLIB environment variable to prevent a LPE. + (responsibly reported by Qualys) + + * Features: + - [CONT] Add Incus support. + (github pull request #315 by Colin Watson @cjwatson) + + * Changes: + - [Core] Refactor device number comparison to be independent of leading zeros. + (closes #286) + - [Interp] Enable ruby check for versioned ruby binary names. + (suggested by Qualys) + - [Interp] Chdir into empty directory to prevent python parsing arbitrary files. + (motivated by Qualys) + + * Fixes: + - [VM] Fix spelling mistake. + (github pull request #309 by @fritz-fritz) + - [Core] Make OpenMetrics output prometheus compatible. + (github pull request #311 by Gabriel Filion @lelutin) + - [uCode] Fix error handling logic being dependent on debug level. + (github pull request #313 by Aristarkh Zagorodnikov @onyxmaster) + - [Core] Fix "Use of uninitialized value $sdev in right bitshift". + (github pull request #314 by Aristarkh Zagorodnikov @onyxmaster) + + + This release contains some critical security fixes in the interpreter module. + While the default configuration was vulnerable it is possible to migitate + the issues by disabling the interpeter heuristic: `$nrconf{interpscan} = 0;` + + All CVEs received a CVSS core of: + CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H [7.8 HIGH] + + Qualys Security Advisory: + https://www.qualys.com/2024/11/19/needrestart/needrestart.txt + + Many thanks to the Qualys Security Advisory team and Mark Esler from the + Ubuntu Security Team for the responsible disclosure, reviewing patches and + coordinating the disclosure of these security issues. + + -- Thomas Liske <tho...@fiasko-nw.net> Tue, 19 Nov 2024 17:00:00 +0100 + needrestart 3.7 * Features: diff -Nru needrestart-3.7/debian/changelog needrestart-3.8/debian/changelog --- needrestart-3.7/debian/changelog 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/changelog 2024-12-09 14:28:40.000000000 -0500 @@ -1,3 +1,19 @@ +needrestart (3.8-0.1) experimental; urgency=medium + + * New upstream release (Closes: #1087882) + * Remove patches merged upstream + - 09-recognize-versioned-ruby-interpreter.diff + - 11-spelling-error.diff + - core-prevent-race-condition-on-proc-PID-exec-evaluat.patch + - interp-chdir-into-empty-directory-to-prevent-python-.patch + - interp-do-not-set-PYTHONPATH-environment-variable-to.patch + - interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch + - interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch + * 08-uninitialized-vars-arm.diff kept, but rerolled, seems like upstream + had a different fix, might be unnecessary + + -- Antoine Beaupré <anar...@debian.org> Mon, 09 Dec 2024 14:28:40 -0500 + needrestart (3.7-3.3) unstable; urgency=medium * Non-maintainer upload. diff -Nru needrestart-3.7/debian/patches/08-uninitialized-vars-arm.diff needrestart-3.8/debian/patches/08-uninitialized-vars-arm.diff --- needrestart-3.7/debian/patches/08-uninitialized-vars-arm.diff 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/08-uninitialized-vars-arm.diff 2024-12-09 14:28:40.000000000 -0500 @@ -2,28 +2,23 @@ # warnings on some amd64 and arm systems. # Closes: #1063719 -diff -Naur needrestart-3.6.orig/perl/lib/NeedRestart/uCode.pm needrestart-3.6/perl/lib/NeedRestart/uCode.pm ---- needrestart-3.6.orig/perl/lib/NeedRestart/uCode.pm 2024-04-03 10:26:46.000000000 +0200 -+++ needrestart-3.6/perl/lib/NeedRestart/uCode.pm 2024-04-03 10:34:02.103311355 +0200 -@@ -152,10 +152,15 @@ +Index: b/perl/lib/NeedRestart/uCode.pm +=================================================================== +--- a/perl/lib/NeedRestart/uCode.pm 2024-12-09 14:35:03.292806588 -0500 ++++ b/perl/lib/NeedRestart/uCode.pm 2024-12-09 14:35:31.816801163 -0500 +@@ -152,6 +152,11 @@ sub nr_ucode_check { # call ucode modules foreach my $pkg (@PKGS) { -+ eval "${pkg}::nr_ucode_init();"; -+ if ( $@ ) { -+ print STDERR $@ if ($debug); -+ next; -+ } ++ eval "${pkg}::nr_ucode_init();"; ++ if ( $@ ) { ++ print STDERR $@ if ($debug); ++ next; ++ } my @nvars; eval "\@nvars = ${pkg}::nr_ucode_check_real(\$debug, \$ui, \$processors{\$pid});"; -- if ( $@ && $debug ) { -- print STDERR $@; -+ if ( $@ ) { -+ print STDERR $@ if ($debug); - $ui->progress_step; - next; - } -@@ -174,6 +179,10 @@ + if ( $@ ) { +@@ -175,6 +180,10 @@ sub nr_ucode_check { $ui->progress_fin; diff -Nru needrestart-3.7/debian/patches/09-recognize-versioned-ruby-interpreter.diff needrestart-3.8/debian/patches/09-recognize-versioned-ruby-interpreter.diff --- needrestart-3.7/debian/patches/09-recognize-versioned-ruby-interpreter.diff 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/09-recognize-versioned-ruby-interpreter.diff 1969-12-31 19:00:00.000000000 -0500 @@ -1,15 +0,0 @@ -# Add patch from Helmut Grohne <hel...@subdivi.de> to detect versioned -# ruby interpreters. -# Closes: #1063155 - ---- needrestart-3.6.orig/perl/lib/NeedRestart/Interp/Ruby.pm -+++ needrestart-3.6/perl/lib/NeedRestart/Interp/Ruby.pm -@@ -42,7 +42,7 @@ sub isa { - my $pid = shift; - my $bin = shift; - -- return 1 if($bin =~ m@^/usr/(local/)?bin/ruby$@); -+ return 1 if($bin =~ m@^/usr/(local/)?bin/ruby(\d+\.\d+)?$@); - - return 0; - } diff -Nru needrestart-3.7/debian/patches/11-spelling-error.diff needrestart-3.8/debian/patches/11-spelling-error.diff --- needrestart-3.7/debian/patches/11-spelling-error.diff 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/11-spelling-error.diff 1969-12-31 19:00:00.000000000 -0500 @@ -1,15 +0,0 @@ -# Fix a spelling error in needrestart. -# Closes: #1040673 - -diff -Naur needrestart-3.6.orig/needrestart needrestart-3.6/needrestart ---- needrestart-3.6.orig/needrestart 2024-04-03 10:26:46.000000000 +0200 -+++ needrestart-3.6/needrestart 2024-04-03 10:54:42.819813966 +0200 -@@ -690,7 +690,7 @@ - } - } - print STDERR "$LOGPREF #$pid detected as VM guest with unknown name in group '$value'\n" if($nrconf{verbosity} > 1); -- push(@guests, __x("'Unkown VM' with pid {pid}", pid=>$pid) ); -+ push(@guests, __x("'Unknown VM' with pid {pid}", pid=>$pid) ); - next; - } - elsif($value =~ m@/([^/]+\.service)$@) { diff -Nru needrestart-3.7/debian/patches/core-prevent-race-condition-on-proc-PID-exec-evaluat.patch needrestart-3.8/debian/patches/core-prevent-race-condition-on-proc-PID-exec-evaluat.patch --- needrestart-3.7/debian/patches/core-prevent-race-condition-on-proc-PID-exec-evaluat.patch 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/core-prevent-race-condition-on-proc-PID-exec-evaluat.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,34 +0,0 @@ -From 99d954da8122122fa18bce061fcf2fb307135b64 Mon Sep 17 00:00:00 2001 -From: Thomas Liske <tho...@fiasko-nw.net> -Date: Sat, 12 Oct 2024 16:05:30 +0200 -Subject: [PATCH 1/5] core: prevent race condition on /proc/$PID/exec - evaluation - ---- - needrestart | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/needrestart b/needrestart -index cad58c3..d8cb9a5 100755 ---- a/needrestart -+++ b/needrestart -@@ -530,11 +530,16 @@ if(defined($opt_l)) { - # orphaned binary - $restart++ if (defined($exe) && $exe =~ s/ \(deleted\)$//); # Linux - $restart++ if (defined($exe) && $exe =~ s/^\(deleted\)//); # Linux VServer -+ $restart++ unless(defined($ptable->{$pid}->{exec})); - print STDERR "$LOGPREF #$pid uses obsolete binary $exe\n" if($restart && $nrconf{verbosity} > 1); - - # ignore blacklisted binaries - next if(grep { $exe =~ /$_/; } @{$nrconf{blacklist}}); - -+ # Sync $exe with the initial value from Proc:ProcessTable to prevent race -+ # conditions in later checks. -+ $exe = $ptable->{$pid}->{exec} if(defined($ptable->{$pid}->{exec})); -+ - # read file mappings (Linux 2.0+) - unless($restart) { - if(open(HMAP, '<', "/proc/$pid/maps")) { --- -2.39.5 - diff -Nru needrestart-3.7/debian/patches/interp-chdir-into-empty-directory-to-prevent-python-.patch needrestart-3.8/debian/patches/interp-chdir-into-empty-directory-to-prevent-python-.patch --- needrestart-3.7/debian/patches/interp-chdir-into-empty-directory-to-prevent-python-.patch 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/interp-chdir-into-empty-directory-to-prevent-python-.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,68 +0,0 @@ -From 4f78b080b4cb51b3d3ea4453333ef83ebdc3590e Mon Sep 17 00:00:00 2001 -From: Thomas Liske <tho...@fiasko-nw.net> -Date: Sun, 3 Nov 2024 19:50:31 +0100 -Subject: [PATCH 4/5] interp: chdir into empty directory to prevent python - parsing arbitrary files - ---- - perl/lib/NeedRestart/Interp/Python.pm | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/perl/lib/NeedRestart/Interp/Python.pm b/perl/lib/NeedRestart/Interp/Python.pm -index 7a7002e..96e0f24 100644 ---- a/perl/lib/NeedRestart/Interp/Python.pm -+++ b/perl/lib/NeedRestart/Interp/Python.pm -@@ -29,11 +29,13 @@ use warnings; - - use parent qw(NeedRestart::Interp); - use Cwd qw(abs_path getcwd); -+use File::Temp qw(tempdir); - use Getopt::Std; - use NeedRestart qw(:interp); - use NeedRestart::Utils; - - my $LOGPREF = '[Python]'; -+my $empty_dir; - - needrestart_interp_register(__PACKAGE__, "python"); - -@@ -79,6 +81,14 @@ sub _scan($$$$$) { - } - } - -+# chdir into empty directory to prevent python parsing arbitrary files -+sub chdir_empty() { -+ unless(defined($empty_dir)) { -+ $empty_dir = tempdir(CLEANUP => 1); -+ } -+ chdir($empty_dir); -+} -+ - sub source { - my $self = shift; - my $pid = shift; -@@ -185,6 +195,7 @@ sub files { - - # use cached data if avail - if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { -+ chdir($cwd); - print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); - return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; - } -@@ -200,11 +211,13 @@ sub files { - } - - # get include path from sys.path -+ chdir_empty(); - my ($pyread, $pywrite) = nr_fork_pipe2($self->{debug}, $ptable->{exec}, '-'); - print $pywrite "import sys\nprint(sys.path)\n"; - close($pywrite); - my ($path) = <$pyread>; - close($pyread); -+ chdir("/proc/$pid/root/$ptable->{cwd}"); - - # look for module source files - if(defined($path)) { --- -2.39.5 - diff -Nru needrestart-3.7/debian/patches/interp-do-not-set-PYTHONPATH-environment-variable-to.patch needrestart-3.8/debian/patches/interp-do-not-set-PYTHONPATH-environment-variable-to.patch --- needrestart-3.7/debian/patches/interp-do-not-set-PYTHONPATH-environment-variable-to.patch 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/interp-do-not-set-PYTHONPATH-environment-variable-to.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,54 +0,0 @@ -From 4c1fa7037c54224cef1e077c5ebdc7f2cfc83799 Mon Sep 17 00:00:00 2001 -From: Thomas Liske <tho...@fiasko-nw.net> -Date: Sat, 12 Oct 2024 18:57:39 +0200 -Subject: [PATCH 2/5] interp: do not set PYTHONPATH environment variable to - prevent a LPE - ---- - perl/lib/NeedRestart/Interp/Python.pm | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/perl/lib/NeedRestart/Interp/Python.pm b/perl/lib/NeedRestart/Interp/Python.pm -index 097ac05..7a7002e 100644 ---- a/perl/lib/NeedRestart/Interp/Python.pm -+++ b/perl/lib/NeedRestart/Interp/Python.pm -@@ -190,16 +190,16 @@ sub files { - } - - # prepare include path environment variable -- my %e = nr_parse_env($pid); -+ my @path; - local %ENV; -+ -+ # get include path from env -+ my %e = nr_parse_env($pid); - if(exists($e{PYTHONPATH})) { -- $ENV{PYTHONPATH} = $e{PYTHONPATH}; -- } -- elsif(exists($ENV{PYTHONPATH})) { -- delete($ENV{PYTHONPATH}); -+ @path = map { "/proc/$pid/root/$_"; } split(':', $e{PYTHONPATH}); - } - -- # get include path -+ # get include path from sys.path - my ($pyread, $pywrite) = nr_fork_pipe2($self->{debug}, $ptable->{exec}, '-'); - print $pywrite "import sys\nprint(sys.path)\n"; - close($pywrite); -@@ -207,12 +207,11 @@ sub files { - close($pyread); - - # look for module source files -- my @path; - if(defined($path)) { - chomp($path); - $path =~ s/^\['//; - $path =~ s/'\$//; -- @path = map { "/proc/$pid/root/$_"; } split("', '", $path); -+ push(@path, map { "/proc/$pid/root/$_"; } split("', '", $path)); - } - else { - print STDERR "$LOGPREF #$pid: failed to retrieve include path\n" if($self->{debug}); --- -2.39.5 - diff -Nru needrestart-3.7/debian/patches/interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch needrestart-3.8/debian/patches/interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch --- needrestart-3.7/debian/patches/interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,81 +0,0 @@ -From 840b750f77ff67f950528e87e87045cfa724d1eb Mon Sep 17 00:00:00 2001 -From: Thomas Liske <tho...@fiasko-nw.net> -Date: Sun, 3 Nov 2024 20:00:03 +0100 -Subject: [PATCH 3/5] interp: do not set RUBYLIB environment variable to - prevent a LPE - ---- - perl/lib/NeedRestart/Interp/Ruby.pm | 25 +++++++++++++++++++------ - 1 file changed, 19 insertions(+), 6 deletions(-) - -diff --git a/perl/lib/NeedRestart/Interp/Ruby.pm b/perl/lib/NeedRestart/Interp/Ruby.pm -index 29b121d..37826ff 100644 ---- a/perl/lib/NeedRestart/Interp/Ruby.pm -+++ b/perl/lib/NeedRestart/Interp/Ruby.pm -@@ -29,11 +29,13 @@ use warnings; - - use parent qw(NeedRestart::Interp); - use Cwd qw(abs_path getcwd); -+use File::Temp qw(tempdir); - use Getopt::Std; - use NeedRestart qw(:interp); - use NeedRestart::Utils; - - my $LOGPREF = '[Ruby]'; -+my $empty_dir; - - needrestart_interp_register(__PACKAGE__, "ruby"); - -@@ -76,6 +78,14 @@ sub _scan($$$$$) { - } - } - -+# chdir into empty directory to prevent ruby parsing arbitrary files -+sub chdir_empty() { -+ unless(defined($empty_dir)) { -+ $empty_dir = tempdir(CLEANUP => 1); -+ } -+ chdir($empty_dir); -+} -+ - sub source { - my $self = shift; - my $pid = shift; -@@ -182,25 +192,28 @@ sub files { - - # use cached data if avail - if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { -+ chdir($cwd); - print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); - return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; - } - - # prepare include path environment variable -- my %e = nr_parse_env($pid); -+ my @path; - local %ENV; -+ -+ # get include path from env -+ my %e = nr_parse_env($pid); - if(exists($e{RUBYLIB})) { -- $ENV{RUBYLIB} = $e{RUBYLIB}; -- } -- elsif(exists($ENV{RUBYLIB})) { -- delete($ENV{RUBYLIB}); -+ @path = map { "/proc/$pid/root/$_"; } split(':', $e{RUBYLIB}); - } - - # get include path -+ chdir_empty(); - my $rbread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'puts $:'); -- my @path = map { "/proc/$pid/root/$_"; } <$rbread>; -+ push(@path, map { "/proc/$pid/root/$_"; } <$rbread>); - close($rbread); - chomp(@path); -+ chdir("/proc/$pid/root/$ptable->{cwd}"); - - my %files; - _scan($self->{debug}, $pid, $src, \%files, \@path); --- -2.39.5 - diff -Nru needrestart-3.7/debian/patches/interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch needrestart-3.8/debian/patches/interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch --- needrestart-3.7/debian/patches/interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,161 +0,0 @@ -From d136fce9bba7730b031bff59c609830f3e072866 Mon Sep 17 00:00:00 2001 -From: Thomas Liske <tho...@fiasko-nw.net> -Date: Mon, 4 Nov 2024 22:29:51 +0100 -Subject: [PATCH 5/5] interp: drop usage of Module::ScanDeps to prevent LPE - ---- - INSTALL.md | 1 - - README.Interp.md | 9 +++- - perl/Makefile.PL | 1 - - perl/lib/NeedRestart/Interp/Perl.pm | 70 ++++++++++++++++++++--------- - 4 files changed, 57 insertions(+), 24 deletions(-) - -diff --git a/INSTALL.md b/INSTALL.md -index 34ae956..fb3ae53 100644 ---- a/INSTALL.md -+++ b/INSTALL.md -@@ -5,7 +5,6 @@ Perl - ---- - - - Module::Find --- Module::ScanDeps - - Locale::TextDomain - - Proc::ProcessTable - - Sort::Naturally -diff --git a/README.Interp.md b/README.Interp.md -index d728404..68f8683 100644 ---- a/README.Interp.md -+++ b/README.Interp.md -@@ -35,8 +35,13 @@ NeedRestart::Interp::Perl - Recognized binaries: /usr/(local/)?bin/perl - Find source file by: command line interpretation - --We are using `Module::ScanDeps` to find used packages. This should work on --any static loaded packages, dynamic stuff will fail. -+The source file is scanned only for 'use' lines, other module loading -+mechanisms will not be recognized. -+ -+*This function used the Module::ScanDeps package to get the used Perl packages -+until needrestart 3.7. Module::ScanDeps is not used any more as it seems not -+to be designed to work with untrustworthy perl sources which would allow an -+attacker to use needrestart for local privilege escalation.* - - - NeedRestart::Interp::Python -diff --git a/perl/Makefile.PL b/perl/Makefile.PL -index 50cea0d..e4e274d 100644 ---- a/perl/Makefile.PL -+++ b/perl/Makefile.PL -@@ -6,7 +6,6 @@ WriteMakefile( - 'NAME' => 'NeedRestart', - 'PREREQ_PM' => { - Module::Find => 0, -- Module::ScanDeps => 0, - Proc::ProcessTable => 0, - Sort::Naturally => 0, - Term::ReadKey => 0. -diff --git a/perl/lib/NeedRestart/Interp/Perl.pm b/perl/lib/NeedRestart/Interp/Perl.pm -index f721980..012098b 100644 ---- a/perl/lib/NeedRestart/Interp/Perl.pm -+++ b/perl/lib/NeedRestart/Interp/Perl.pm -@@ -32,7 +32,6 @@ use Cwd qw(abs_path getcwd); - use Getopt::Std; - use NeedRestart qw(:interp); - use NeedRestart::Utils; --use Module::ScanDeps; - - my $LOGPREF = '[Perl]'; - -@@ -48,6 +47,41 @@ sub isa { - return 0; - } - -+sub _scan($$$$$) { -+ my $debug = shift; -+ my $pid = shift; -+ my $src = shift; -+ my $files = shift; -+ my $path = shift; -+ -+ my $fh; -+ open($fh, '<', $src) || return; -+ # find used modules -+ my %modules = map { -+ (/^\s*use\s+([a-zA-Z][\w:]+)/ ? ($1 => 1) : ()) -+ } <$fh>; -+ close($fh); -+ -+ # track file -+ $files->{$src}++; -+ -+ # scan module files -+ if(scalar keys %modules) { -+ foreach my $module (keys %modules) { -+ # skip some well-known Perl pragmas -+ next if ($module =~ /^(constant|strict|vars|v5(\.\d+)?|warnings)$/); -+ -+ $module =~ s@::@/@g; -+ $module .= '.pm'; -+ -+ foreach my $p (@$path) { -+ my $fn = ($p ne '' ? "$p/" : '').$module; -+ &_scan($debug, $pid, $fn, $files, $path) if(!exists($files->{$fn}) && -r $fn && -f $fn); -+ } -+ } -+ } -+} -+ - sub source { - my $self = shift; - my $pid = shift; -@@ -160,32 +194,28 @@ sub files { - } - - # prepare include path environment variable -- my %e = nr_parse_env($pid); -+ my @path; - local %ENV; -+ -+ # get include path from env -+ my %e = nr_parse_env($pid); - if(exists($e{PERL5LIB})) { -- $ENV{PERL5LIB} = $e{PERL5LIB}; -- } -- elsif(exists($ENV{PERL5LIB})) { -- delete($ENV{PERL5LIB}); -+ @path = map { "/proc/$pid/root/$_"; } split(':', $e{PERL5LIB}); - } - -- @Module::ScanDeps::IncludeLibs = (exists($opts{I}) ? ($opts{I}) : ()); -- my $href; -- { -- # Silence warnings of Module::ScanDeps for dynamic loaded modules (github issue #41) -- local $SIG{__WARN__} = sub { }; -+ # get include path from @INC -+ my $plread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'print(join("\n", @INC));'); -+ push(@path, map { "/proc/$pid/root/$_"; } <$plread>); -+ close($plread); -+ chomp(@path); - -- $href = scan_deps( -- files => [$src], -- recurse => 1, -- cache_file => $self->{conf}->{cache_file}, -- ); -- } -+ my %files; -+ _scan($self->{debug}, $pid, $src, \%files, \@path); - - my %ret = map { -- my $stat = nr_stat("/proc/$pid/root/$href->{$_}->{file}"); -- $href->{$_}->{file} => ( defined($stat) ? $stat->{ctime} : undef ); -- } keys %$href; -+ my $stat = nr_stat("/proc/$pid/root/$_"); -+ $_ => ( defined($stat) ? $stat->{ctime} : undef ); -+ } keys %files; - - chdir($cwd); - --- -2.39.5 - diff -Nru needrestart-3.7/debian/patches/series needrestart-3.8/debian/patches/series --- needrestart-3.7/debian/patches/series 2024-11-28 17:21:38.000000000 -0500 +++ needrestart-3.8/debian/patches/series 2024-12-09 14:28:40.000000000 -0500 @@ -1,12 +1,5 @@ 01-use-invoke-rc-d.diff 03-ignore-serial-getty.diff 08-uninitialized-vars-arm.diff -09-recognize-versioned-ruby-interpreter.diff 10-notify-send-timeout.diff -11-spelling-error.diff -core-prevent-race-condition-on-proc-PID-exec-evaluat.patch -interp-do-not-set-PYTHONPATH-environment-variable-to.patch -interp-do-not-set-RUBYLIB-environment-variable-to-pr.patch -interp-chdir-into-empty-directory-to-prevent-python-.patch -interp-drop-usage-of-Module-ScanDeps-to-prevent-LPE.patch core-fix-regression-of-false-positives-for-processes.patch diff -Nru needrestart-3.7/INSTALL.md needrestart-3.8/INSTALL.md --- needrestart-3.7/INSTALL.md 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/INSTALL.md 2024-11-18 16:46:03.000000000 -0500 @@ -5,7 +5,6 @@ ---- - Module::Find -- Module::ScanDeps - Locale::TextDomain - Proc::ProcessTable - Sort::Naturally diff -Nru needrestart-3.7/needrestart needrestart-3.8/needrestart --- needrestart-3.7/needrestart 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/needrestart 2024-11-18 16:46:03.000000000 -0500 @@ -472,6 +472,11 @@ krunning => q(unknown), kexpected => q(unknown), ); +my %ometric_ucode_values = ( + status => q(unknown), + current => q(unknown), + expected => q(unkown), +); my %restart; my %sessions; @@ -525,11 +530,16 @@ # orphaned binary $restart++ if (defined($exe) && $exe =~ s/ \(deleted\)$//); # Linux $restart++ if (defined($exe) && $exe =~ s/^\(deleted\)//); # Linux VServer + $restart++ unless(defined($ptable->{$pid}->{exec})); print STDERR "$LOGPREF #$pid uses obsolete binary $exe\n" if($restart && $nrconf{verbosity} > 1); # ignore blacklisted binaries next if(grep { $exe =~ /$_/; } @{$nrconf{blacklist}}); + # Sync $exe with the initial value from Proc:ProcessTable to prevent race + # conditions in later checks. + $exe = $ptable->{$pid}->{exec} if(defined($ptable->{$pid}->{exec})); + # read file mappings (Linux 2.0+) unless($restart) { if(open(HMAP, '<', "/proc/$pid/maps")) { @@ -568,27 +578,36 @@ # get on-disk info my ($sdev, $sinode) = stat($testp); + unless($sdev) { + print STDERR "$LOGPREF #$pid map stat for $testp failed: $!\n" if($nrconf{skip_mapfiles} == 0 && $nrconf{verbosity} > 1); + next; + } my @sdevs = ( # glibc gnu_dev_* definition from sysmacros.h - sprintf("%02x:%02x", (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff), (($sdev & 0xff) | (($sdev >> 12) & ~0xff))), + sprintf("%x:%x", (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff), ($sdev & 0xff) | (($sdev >> 12) & ~0xff)), # Traditional definition of major(3) and minor(3) - sprintf("%02x:%02x", $sdev >> 8, $sdev & 0xff), + sprintf("%x:%x", $sdev >> 8, $sdev & 0xff), # kFreeBSD: /proc/<pid>/maps does not contain device IDs - qq(00:00) + qq(0:0) ); # Don't compare device numbers on anon filesystems # w/o a backing device (like OpenVZ's simfs). my $major = (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff); - $mdev = "00:00" - if ($major == 0 || $major == 144 || $major == 145 || $major == 146); + if ($major == 0 || $major == 144 || $major == 145 || $major == 146) { + $mdev = "0:0"; + } + else { + # strip leading zeros + $mdev =~ s/(^|:)0+([\da-f]+)/$1$2/g; + } # compare maps content vs. on-disk unless($minode eq $sinode && ((grep {$mdev eq $_} @sdevs) || # BTRFS breaks device ID mapping completely... # ignoring unnamed device IDs for now - $mdev =~ /^00:/)) { + $mdev =~ /^0:/)) { print STDERR "$LOGPREF #$pid uses obsolete $path\n" if($nrconf{verbosity} > 1); $restart++; last; @@ -712,7 +731,7 @@ } } print STDERR "$LOGPREF #$pid detected as VM guest with unknown name in group '$value'\n" if($nrconf{verbosity} > 1); - push(@guests, __x("'Unkown VM' with pid {pid}", pid=>$pid) ); + push(@guests, __x("'Unknown VM' with pid {pid}", pid=>$pid) ); next; } elsif($value =~ m@/([^/]+\.service)$@) { @@ -910,7 +929,12 @@ } } elsif ($opt_o) { - $ometric_kernel_values{kresult} = $kresult; + my %kernel_states = ( + &NRK_NOUPGRADE => "current", + &NRK_ABIUPGRADE => "abi_upgrade", + &NRK_VERUPGRADE => "version_upgrade", + ); + $ometric_kernel_values{kresult} = $kernel_states{$kresult}; $ometric_kernel_values{krunning} = $kvars{KVERSION}; $ometric_kernel_values{kexpected} = $kvars{EVERSION}; } @@ -969,23 +993,35 @@ } } else { - if($ucode_result == NRM_OBSOLETE) { - $nagios{mstr} = "OBSOLETE"; - $nagios{mret} = $nrconf{q(nagios-status)}->{ucode}; - $nagios{mperf} = 1; - } - elsif($ucode_result == NRM_CURRENT) { - $nagios{mstr} = "CURRENT"; - $nagios{mret} = 0; - $nagios{mperf} = 0; - } - - if($nagios{mret} == 1) { - $nagios{mstr} .= " (!)"; - } - elsif($nagios{mret} == 2) { - $nagios{mstr} .= " (!!)"; - } + if ($opt_p) { + if($ucode_result == NRM_OBSOLETE) { + $nagios{mstr} = "OBSOLETE"; + $nagios{mret} = $nrconf{q(nagios-status)}->{ucode}; + $nagios{mperf} = 1; + } + elsif($ucode_result == NRM_CURRENT) { + $nagios{mstr} = "CURRENT"; + $nagios{mret} = 0; + $nagios{mperf} = 0; + } + + if($nagios{mret} == 1) { + $nagios{mstr} .= " (!)"; + } + elsif($nagios{mret} == 2) { + $nagios{mstr} .= " (!!)"; + } + } + elsif ($opt_o) { + my %ucode_states = ( + &NRM_CURRENT => "current", + &NRM_OBSOLETE => "obsolete", + &NRM_UNKNOWN => "unknown", + ); + $ometric_ucode_values{status} = $ucode_states{$ucode_result}; + $ometric_ucode_values{current} = $ucode_result != NRM_UNKNOWN ? $ucode_vars{CURRENT} : "unknown"; + $ometric_ucode_values{expected} = $ucode_result != NRM_UNKNOWN ? $ucode_vars{AVAIL} : "unknown"; + } } } else { @@ -1426,33 +1462,25 @@ exit $ret; } if ($opt_o) { - print "# TYPE needrestart_build info\n"; - print "# HELP needrestart_build information about needrestart's runtime build\n"; - print "needrestart_build_info{version=$NeedRestart::VERSION,perl_version=$^V} 1\n"; + print "# TYPE needrestart_build_info gauge\n"; + print "# HELP needrestart_build_info information about needrestart's runtime build\n"; + print "needrestart_build_info{version=\"$NeedRestart::VERSION\",perl_version=\"$^V\"} 1\n"; if ($opt_k) { - my @ometric_kernel_status = map { $_ == $ometric_kernel_values{kresult} ? 1 : 0 } (NRK_NOUPGRADE, NRK_ABIUPGRADE, NRK_VERUPGRADE); - print "# TYPE needrestart_kernel_status stateset\n"; + print "# TYPE needrestart_kernel_status gauge\n"; print "# HELP needrestart_kernel_status status of kernel as reported by needrestart\n"; - print "needrestart_kernel_status{needrestart_kernel_status=\"current\"} $ometric_kernel_status[0]\n"; - print "needrestart_kernel_status{needrestart_kernel_status=\"abi_upgrade\"} $ometric_kernel_status[1]\n"; - print "needrestart_kernel_status{needrestart_kernel_status=\"version_upgrade\"} $ometric_kernel_status[2]\n"; - print "# TYPE needrestart_kernel info\n"; - print "# HELP needrestart_kernel version information for currenly running and most up to date kernels\n"; - print "needrestart_kernel_info{running=\"$ometric_kernel_values{krunning}\",expected=\"$ometric_kernel_values{kexpected}\"} 1\n"; + print "needrestart_kernel_status{needrestart_kernel_status=\"$ometric_kernel_values{kresult}\"} 1\n"; + print "# TYPE needrestart_kernel_info gauge\n"; + print "# HELP needrestart_kernel_info version information for currenly running and most up to date kernels\n"; + print "needrestart_kernel{running=\"$ometric_kernel_values{krunning}\",expected=\"$ometric_kernel_values{kexpected}\"} 1\n"; } if ($opt_w) { - my $ometric_ucode_current = $ucode_result != NRM_UNKNOWN ? $ucode_vars{CURRENT} : "unknown"; - my $ometric_ucode_expected = $ucode_result != NRM_UNKNOWN ? $ucode_vars{AVAIL} : "unknown"; - my @ometric_ucode_status = map { $_ == $ucode_result ? 1 : 0 } (NRM_CURRENT, NRM_OBSOLETE, NRM_UNKNOWN); - print "# TYPE needrestart_ucode_status stateset\n"; + print "# TYPE needrestart_ucode_status gauge\n"; print "# HELP needrestart_ucode_status status of the host's CPU microcode as reported by needrestart\n"; - print "needrestart_ucode_status{needrestart_ucode_status=\"current\"} $ometric_ucode_status[0]\n"; - print "needrestart_ucode_status{needrestart_ucode_status=\"obsolete\"} $ometric_ucode_status[1]\n"; - print "needrestart_ucode_status{needrestart_ucode_status=\"unknown\"} $ometric_ucode_status[2]\n"; - print "# TYPE needrestart_ucode info\n"; - print "# HELP needrestart_ucode version informaion for currently used and available microcode\n"; - print "needrestart_ucode_info{running=\"$ometric_ucode_current\",expected=\"$ometric_ucode_expected\"} 1\n"; + print "needrestart_ucode_status{needrestart_ucode_status=\"$ometric_ucode_values{status}\"} 1\n"; + print "# TYPE needrestart_ucode_info gauge\n"; + print "# HELP needrestart_ucode_info version informaion for currently used and available microcode\n"; + print "needrestart_ucode{running=\"$ometric_ucode_values{current}\",expected=\"$ometric_ucode_values{expected}\"} 1\n"; } if ($opt_l) { my $ometric_num_services = scalar %restart; diff -Nru needrestart-3.7/perl/lib/NeedRestart/CONT/LXC.pm needrestart-3.8/perl/lib/NeedRestart/CONT/LXC.pm --- needrestart-3.7/perl/lib/NeedRestart/CONT/LXC.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart/CONT/LXC.pm 2024-11-18 16:46:03.000000000 -0500 @@ -50,6 +50,10 @@ $self->{lxd_bin} = q(/snap/bin/lxc); $self->{lxd_container_path} = q(/var/snap/lxd/common/lxd/containers); print STDERR "$LOGPREF LXD installed via snap\n" if($self->{debug}); + } elsif (-x q(/usr/bin/incus)) { + $self->{has_lxd} = 1; + $self->{lxd_bin} = q(/usr/bin/incus); + $self->{lxd_container_path} = q(/var/lib/incus/containers); } else { $self->{has_lxd} = -x q(/usr/bin/lxc); $self->{lxd_bin} = q(/usr/bin/lxc); diff -Nru needrestart-3.7/perl/lib/NeedRestart/Interp/Perl.pm needrestart-3.8/perl/lib/NeedRestart/Interp/Perl.pm --- needrestart-3.7/perl/lib/NeedRestart/Interp/Perl.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart/Interp/Perl.pm 2024-11-18 16:46:03.000000000 -0500 @@ -32,7 +32,6 @@ use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; -use Module::ScanDeps; my $LOGPREF = '[Perl]'; @@ -48,6 +47,41 @@ return 0; } +sub _scan($$$$$) { + my $debug = shift; + my $pid = shift; + my $src = shift; + my $files = shift; + my $path = shift; + + my $fh; + open($fh, '<', $src) || return; + # find used modules + my %modules = map { + (/^\s*use\s+([a-zA-Z][\w:]+)/ ? ($1 => 1) : ()) + } <$fh>; + close($fh); + + # track file + $files->{$src}++; + + # scan module files + if(scalar keys %modules) { + foreach my $module (keys %modules) { + # skip some well-known Perl pragmas + next if ($module =~ /^(constant|strict|vars|v5(\.\d+)?|warnings)$/); + + $module =~ s@::@/@g; + $module .= '.pm'; + + foreach my $p (@$path) { + my $fn = ($p ne '' ? "$p/" : '').$module; + &_scan($debug, $pid, $fn, $files, $path) if(!exists($files->{$fn}) && -r $fn && -f $fn); + } + } + } +} + sub source { my $self = shift; my $pid = shift; @@ -160,32 +194,28 @@ } # prepare include path environment variable - my %e = nr_parse_env($pid); + my @path; local %ENV; + + # get include path from env + my %e = nr_parse_env($pid); if(exists($e{PERL5LIB})) { - $ENV{PERL5LIB} = $e{PERL5LIB}; - } - elsif(exists($ENV{PERL5LIB})) { - delete($ENV{PERL5LIB}); + @path = map { "/proc/$pid/root/$_"; } split(':', $e{PERL5LIB}); } - @Module::ScanDeps::IncludeLibs = (exists($opts{I}) ? ($opts{I}) : ()); - my $href; - { - # Silence warnings of Module::ScanDeps for dynamic loaded modules (github issue #41) - local $SIG{__WARN__} = sub { }; + # get include path from @INC + my $plread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'print(join("\n", @INC));'); + push(@path, map { "/proc/$pid/root/$_"; } <$plread>); + close($plread); + chomp(@path); - $href = scan_deps( - files => [$src], - recurse => 1, - cache_file => $self->{conf}->{cache_file}, - ); - } + my %files; + _scan($self->{debug}, $pid, $src, \%files, \@path); my %ret = map { - my $stat = nr_stat("/proc/$pid/root/$href->{$_}->{file}"); - $href->{$_}->{file} => ( defined($stat) ? $stat->{ctime} : undef ); - } keys %$href; + my $stat = nr_stat("/proc/$pid/root/$_"); + $_ => ( defined($stat) ? $stat->{ctime} : undef ); + } keys %files; chdir($cwd); diff -Nru needrestart-3.7/perl/lib/NeedRestart/Interp/Python.pm needrestart-3.8/perl/lib/NeedRestart/Interp/Python.pm --- needrestart-3.7/perl/lib/NeedRestart/Interp/Python.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart/Interp/Python.pm 2024-11-18 16:46:03.000000000 -0500 @@ -29,11 +29,13 @@ use parent qw(NeedRestart::Interp); use Cwd qw(abs_path getcwd); +use File::Temp qw(tempdir); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Python]'; +my $empty_dir; needrestart_interp_register(__PACKAGE__, "python"); @@ -79,6 +81,14 @@ } } +# chdir into empty directory to prevent python parsing arbitrary files +sub chdir_empty() { + unless(defined($empty_dir)) { + $empty_dir = tempdir(CLEANUP => 1); + } + chdir($empty_dir); +} + sub source { my $self = shift; my $pid = shift; @@ -185,34 +195,36 @@ # use cached data if avail if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { + chdir($cwd); print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; } # prepare include path environment variable - my %e = nr_parse_env($pid); + my @path; local %ENV; + + # get include path from env + my %e = nr_parse_env($pid); if(exists($e{PYTHONPATH})) { - $ENV{PYTHONPATH} = $e{PYTHONPATH}; - } - elsif(exists($ENV{PYTHONPATH})) { - delete($ENV{PYTHONPATH}); + @path = map { "/proc/$pid/root/$_"; } split(':', $e{PYTHONPATH}); } - # get include path + # get include path from sys.path + chdir_empty(); my ($pyread, $pywrite) = nr_fork_pipe2($self->{debug}, $ptable->{exec}, '-'); print $pywrite "import sys\nprint(sys.path)\n"; close($pywrite); my ($path) = <$pyread>; close($pyread); + chdir("/proc/$pid/root/$ptable->{cwd}"); # look for module source files - my @path; if(defined($path)) { chomp($path); $path =~ s/^\['//; $path =~ s/'\$//; - @path = map { "/proc/$pid/root/$_"; } split("', '", $path); + push(@path, map { "/proc/$pid/root/$_"; } split("', '", $path)); } else { print STDERR "$LOGPREF #$pid: failed to retrieve include path\n" if($self->{debug}); diff -Nru needrestart-3.7/perl/lib/NeedRestart/Interp/Ruby.pm needrestart-3.8/perl/lib/NeedRestart/Interp/Ruby.pm --- needrestart-3.7/perl/lib/NeedRestart/Interp/Ruby.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart/Interp/Ruby.pm 2024-11-18 16:46:03.000000000 -0500 @@ -29,11 +29,13 @@ use parent qw(NeedRestart::Interp); use Cwd qw(abs_path getcwd); +use File::Temp qw(tempdir); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Ruby]'; +my $empty_dir; needrestart_interp_register(__PACKAGE__, "ruby"); @@ -42,7 +44,7 @@ my $pid = shift; my $bin = shift; - return 1 if($bin =~ m@^/usr/(local/)?bin/ruby$@); + return 1 if($bin =~ m@^/usr/(local/)?bin/ruby(\d[.\d]*)?$@); return 0; } @@ -76,6 +78,14 @@ } } +# chdir into empty directory to prevent ruby parsing arbitrary files +sub chdir_empty() { + unless(defined($empty_dir)) { + $empty_dir = tempdir(CLEANUP => 1); + } + chdir($empty_dir); +} + sub source { my $self = shift; my $pid = shift; @@ -182,25 +192,28 @@ # use cached data if avail if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { + chdir($cwd); print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; } # prepare include path environment variable - my %e = nr_parse_env($pid); + my @path; local %ENV; + + # get include path from env + my %e = nr_parse_env($pid); if(exists($e{RUBYLIB})) { - $ENV{RUBYLIB} = $e{RUBYLIB}; - } - elsif(exists($ENV{RUBYLIB})) { - delete($ENV{RUBYLIB}); + @path = map { "/proc/$pid/root/$_"; } split(':', $e{RUBYLIB}); } # get include path + chdir_empty(); my $rbread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'puts $:'); - my @path = map { "/proc/$pid/root/$_"; } <$rbread>; + push(@path, map { "/proc/$pid/root/$_"; } <$rbread>); close($rbread); chomp(@path); + chdir("/proc/$pid/root/$ptable->{cwd}"); my %files; _scan($self->{debug}, $pid, $src, \%files, \@path); diff -Nru needrestart-3.7/perl/lib/NeedRestart/uCode.pm needrestart-3.8/perl/lib/NeedRestart/uCode.pm --- needrestart-3.7/perl/lib/NeedRestart/uCode.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart/uCode.pm 2024-11-18 16:46:03.000000000 -0500 @@ -154,8 +154,9 @@ foreach my $pkg (@PKGS) { my @nvars; eval "\@nvars = ${pkg}::nr_ucode_check_real(\$debug, \$ui, \$processors{\$pid});"; - if ( $@ && $debug ) { - print STDERR $@; + if ( $@ ) { + print STDERR $@ + if ($debug); $ui->progress_step; next; } diff -Nru needrestart-3.7/perl/lib/NeedRestart.pm needrestart-3.8/perl/lib/NeedRestart.pm --- needrestart-3.7/perl/lib/NeedRestart.pm 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/lib/NeedRestart.pm 2024-11-18 16:46:03.000000000 -0500 @@ -81,7 +81,7 @@ )], ); -our $VERSION = '3.7'; +our $VERSION = '3.8'; my $LOGPREF = '[Core]'; my %UIs; diff -Nru needrestart-3.7/perl/Makefile.PL needrestart-3.8/perl/Makefile.PL --- needrestart-3.7/perl/Makefile.PL 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/perl/Makefile.PL 2024-11-18 16:46:03.000000000 -0500 @@ -6,7 +6,6 @@ 'NAME' => 'NeedRestart', 'PREREQ_PM' => { Module::Find => 0, - Module::ScanDeps => 0, Proc::ProcessTable => 0, Sort::Naturally => 0, Term::ReadKey => 0. diff -Nru needrestart-3.7/README.Cont.md needrestart-3.8/README.Cont.md --- needrestart-3.7/README.Cont.md 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/README.Cont.md 2024-11-18 16:46:03.000000000 -0500 @@ -27,7 +27,9 @@ `lxc-stop --reboot --name $NAME`. This package also supports LXD containers, which are restarted by `lxc restart -$NAME` or `lxc restart --project=$PROJECT $NAME` for containers in projects. +$NAME` or `lxc restart --project=$PROJECT $NAME` for containers in projects, +and Incus containers, which are restarted by `incus restart $NAME` or `incus +restart --project=$PROJECT $NAME` for containers in projects. NeedRestart::CONT::machined --------------------------- diff -Nru needrestart-3.7/README.Interp.md needrestart-3.8/README.Interp.md --- needrestart-3.7/README.Interp.md 2024-08-11 17:01:18.000000000 -0400 +++ needrestart-3.8/README.Interp.md 2024-11-18 16:46:03.000000000 -0500 @@ -35,8 +35,13 @@ Recognized binaries: /usr/(local/)?bin/perl Find source file by: command line interpretation -We are using `Module::ScanDeps` to find used packages. This should work on -any static loaded packages, dynamic stuff will fail. +The source file is scanned only for 'use' lines, other module loading +mechanisms will not be recognized. + +*This function used the Module::ScanDeps package to get the used Perl packages +until needrestart 3.7. Module::ScanDeps is not used any more as it seems not +to be designed to work with untrustworthy perl sources which would allow an +attacker to use needrestart for local privilege escalation.* NeedRestart::Interp::Python
signature.asc
Description: PGP signature