Your message dated Mon, 09 Dec 2024 15:01:49 -0500
with message-id <[email protected]>
and subject line Re: Bug#1089606: Acknowledgement (needrestart: diff for NMU 
version 3.8-0.1)
has caused the Debian Bug report #1089606,
regarding needrestart: diff for NMU version 3.8-0.1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1089606: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1089606
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: needrestart
Version: 3.7-3.3
Severity: normal
Tags: patch  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.

A.
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 <[email protected]>  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.
+  * 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é <[email protected]>  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 <[email protected]> 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 <[email protected]>
-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 <[email protected]>
-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 <[email protected]>
-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 <[email protected]>
-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 <[email protected]>
-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

Attachment: signature.asc
Description: PGP signature


--- End Message ---
--- Begin Message ---
Hmmm... I kind of messed this one up. I forgot to include the bug number
in the changelog, and because of this, nmudiff created a new issue
instead of tagging the old bug instead.

So I'm closing this bug report, see
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087882 instead.

--- End Message ---

Reply via email to