Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PATCH] 5.28.1: $^X is undefined on Linux without /proc #16808

Open
p5pRT opened this issue Jan 12, 2019 · 7 comments
Open

[PATCH] 5.28.1: $^X is undefined on Linux without /proc #16808

p5pRT opened this issue Jan 12, 2019 · 7 comments
Labels

Comments

@p5pRT
Copy link

p5pRT commented Jan 12, 2019

Migrated from rt.perl.org#133765 (status was 'open')

Searchable as RT133765$

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2019

From viy@altlinux.org

This is a bug report for perl from viy@​altlinux.org,
generated with the help of perlbug 1.40 running under perl 5.22.3.

On normal system
$ perl -le 'use warnings; print $^X'
/usr/bin/perl5.28.1

In a chroot without /proc or just with sudo umount /proc
$ perl -le 'use warnings; print $^X'
Use of uninitialized value ...

Current implementation of $^X assumes that /proc/self/exe
is always available and accessible on Linux.
It is not true; For example, in ALT Linux
secure chroot build environment does not mount /proc
by default.
Other example is early stages of system initialization
or system boot failure where /proc is not yet mounted
or failed to mount.

In that case, $^X should be PL_origargv[0].
Instead, it is undefined.

As a result, perl tools can fail or change its behaviour.

for example, now ExtUtils​::MakeMaker fails without /proc​:
+ /usr/bin/perl Makefile.PL PREFIX=/usr INSTALLDIRS=vendor
Use of uninitialized value $_[0] in substitution (s///) at /usr/share/perl5/File/Basename.pm line 341.
fileparse()​: need a valid pathname at /usr/share/perl5/ExtUtils/MM_Unix.pm line 1128.
[...]
and perl modules can not be built in chroot without /proc.
It is regression compared to perl 5.26.

Proposed patch (tested)

Inline Patch
diff --git a/caretx.c b/caretx.c
index d758f73..aa069cc 100644
--- a/caretx.c
+++ b/caretx.c
@@ -97,7 +97,15 @@ Perl_set_caret_X(pTHX) {
     }
 #elif defined(HAS_PROCSELFEXE)
     char buf[MAXPATHLEN];
-    SSize_t len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
+    SSize_t len;
+    /* NOTE: it is possible for /proc to be unmounted
+     * or for perl to be run in a chroot environment without /proc . */
+    if (access(PROCSELFEXE_PATH, R_OK) != 0) {
+	/* Fallback */
+	sv_setpv(caret_x, PL_origargv[0]);
+	return;
+    }
+    len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
     /* NOTE: if the length returned by readlink() is sizeof(buf) - 1,
      * it is impossible to know whether the result was truncated. */
 
---
Flags:   category=core   severity=high   Type=Patch   PatchStatus=HasPatch

Site configuration information for perl 5.22.3​:

Configured by ALT Linux Team at Wed Feb 1 13​:44​:57 UTC 2017.

Summary of my perl5 (revision 5 version 22 subversion 3) configuration​:
 
  Platform​:
  osname=linux, osvers=4.4.42-std-def-alt1.1, archname=x86_64-linux-thread-multi
  uname='linux localhost.localdomain 4.4.42-std-def-alt1.1 #1 smp fri jan 13 06​:15​:14 utc 2017 x86_64 gnulinux '
  config_args='-ders -Dusethreads -Duseithreads -Duselargefiles -Duseshrplib -Dlibperl=libperl-5.22.so -Dcc=gcc -Doptimize=-pipe -Wall -g -O2 -DDEBUGGING=maybe -Dprefix=/usr -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib64/perl5 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib64/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.22 -Dsitearch=/usr/local/lib64/perl/5.22 -Dotherlibdirs=/etc/perl5​:/usr/lib/perl5/vendor_perl -Dinc_version_list=none -Dpager=/usr/bin/less -isR -Dman1dir=/usr/share/man/man1 -Dman3dir=none -Dcf_by=ALT Linux Team -Dcf_email=Perl Maintainers Team <cpan@​altlinux.ru> -Dmyhostname=localhost -Dperladmin=root@​localhost'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-pipe -Wall -g -O2',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
  ccversion='', gccversion='5.3.1 20151207 (ALT Linux 5.3.1-alt3)', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
  ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='gcc', ldflags =' -fstack-protector-strong -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib /lib64 /usr/lib64 /lib /usr/local/lib64
  libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
  perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.23.so, so=so, useshrplib=true, libperl=libperl-5.22.so
  gnulibc_version='2.23'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -pipe -Wall -g -O2 -L/usr/local/lib -fstack-protector-strong'


@​INC for perl 5.22.3​:
  /usr/local/lib64/perl/5.22
  /usr/local/share/perl/5.22
  /usr/lib64/perl5
  /usr/share/perl5
  /usr/lib64/perl5
  /usr/share/perl5
  /etc/perl5
  /usr/lib/perl5/vendor_perl


Environment for perl 5.22.3​:
  HOME=/home/cpanbuilder
  LANG=ru_RU.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/home/cpanbuilder/bin​:/bin​:/usr/bin​:/usr/local/bin​:/usr/X11R6/bin​:/usr/games
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2019

From viy@altlinux.org

perl-5.28.1-alt-viy-caretx-chroot-support.patch
diff --git a/caretx.c b/caretx.c
index d758f73..aa069cc 100644
--- a/caretx.c
+++ b/caretx.c
@@ -97,7 +97,15 @@ Perl_set_caret_X(pTHX) {
     }
 #elif defined(HAS_PROCSELFEXE)
     char buf[MAXPATHLEN];
-    SSize_t len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
+    SSize_t len;
+    /* NOTE: it is possible for /proc to be unmounted
+     * or for perl to be run in a chroot environment without /proc . */
+    if (access(PROCSELFEXE_PATH, R_OK) != 0) {
+	/* Fallback */
+	sv_setpv(caret_x, PL_origargv[0]);
+	return;
+    }
+    len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
     /* NOTE: if the length returned by readlink() is sizeof(buf) - 1,
      * it is impossible to know whether the result was truncated. */
 

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2019

From viy@altlinux.org

It is my first time reporting to rt.perl.org/,
I used perlbug on the build machine with older perl,
but this bug is about perl 5.28.1.

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2019

From @tonycoz

On Sat, 12 Jan 2019 07​:58​:09 -0800, viy@​altlinux.org wrote​:

This is a bug report for perl from viy@​altlinux.org,
generated with the help of perlbug 1.40 running under perl 5.22.3.

On normal system
$ perl -le 'use warnings; print $^X'
/usr/bin/perl5.28.1

In a chroot without /proc or just with sudo umount /proc
$ perl -le 'use warnings; print $^X'
Use of uninitialized value ...

Current implementation of $^X assumes that /proc/self/exe
is always available and accessible on Linux.
It is not true; For example, in ALT Linux
secure chroot build environment does not mount /proc
by default.
Other example is early stages of system initialization
or system boot failure where /proc is not yet mounted
or failed to mount.

In that case, $^X should be PL_origargv[0].
Instead, it is undefined.

As a result, perl tools can fail or change its behaviour.

for example, now ExtUtils​::MakeMaker fails without /proc​:
+ /usr/bin/perl Makefile.PL PREFIX=/usr INSTALLDIRS=vendor
Use of uninitialized value $_[0] in substitution (s///) at
/usr/share/perl5/File/Basename.pm line 341.
fileparse()​: need a valid pathname at
/usr/share/perl5/ExtUtils/MM_Unix.pm line 1128.
[...]
and perl modules can not be built in chroot without /proc.
It is regression compared to perl 5.26.

The code already has a fallback to​:

  sv_setpv(caret_x, PL_origargv[0]);

if the readlink() fails, which it should if /proc isn't mounted.

If that's not happening can you produce a relevant strace?

Thanks,
Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2019

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 15, 2019

From @ilmari

"Tony Cook via RT" <perlbug-followup@​perl.org> writes​:

On Sat, 12 Jan 2019 07​:58​:09 -0800, viy@​altlinux.org wrote​:

This is a bug report for perl from viy@​altlinux.org,
generated with the help of perlbug 1.40 running under perl 5.22.3.

On normal system
$ perl -le 'use warnings; print $^X'
/usr/bin/perl5.28.1

In a chroot without /proc or just with sudo umount /proc
$ perl -le 'use warnings; print $^X'
Use of uninitialized value ...

Current implementation of $^X assumes that /proc/self/exe
is always available and accessible on Linux.
It is not true; For example, in ALT Linux
secure chroot build environment does not mount /proc
by default.
Other example is early stages of system initialization
or system boot failure where /proc is not yet mounted
or failed to mount.

In that case, $^X should be PL_origargv[0].
Instead, it is undefined.

As a result, perl tools can fail or change its behaviour.

for example, now ExtUtils​::MakeMaker fails without /proc​:
+ /usr/bin/perl Makefile.PL PREFIX=/usr INSTALLDIRS=vendor
Use of uninitialized value $_[0] in substitution (s///) at
/usr/share/perl5/File/Basename.pm line 341.
fileparse()​: need a valid pathname at
/usr/share/perl5/ExtUtils/MM_Unix.pm line 1128.
[...]
and perl modules can not be built in chroot without /proc.
It is regression compared to perl 5.26.

The code already has a fallback to​:

sv_setpv(caret_x, PL_origargv[0]);

if the readlink() fails, which it should if /proc isn't mounted.

If that's not happening can you produce a relevant strace?

It does now, but didn't in 5.28, c.f.
https://rt.perl.org/Public/Bug/Display.html?id=133573 and
https://perl5.git.perl.org/perl.git/commitdiff/03b94aa47e981af3c7b0118bfb11facda2b95251

Since this was a regression in 5.28 (introduced in
https://perl5.git.perl.org/perl.git/commitdiff/fca5fb9612a125f48173bedf2c079778d7bc54dd),
I reckon the fix is eligible for backporting.

- ilmari
--
"I use RMS as a guide in the same way that a boat captain would use
a lighthouse. It's good to know where it is, but you generally
don't want to find yourself in the same spot." - Tollef Fog Heen

@p5pRT
Copy link
Author

p5pRT commented Jan 15, 2019

From @tonycoz

On Mon, 14 Jan 2019 16​:41​:35 -0800, ilmari wrote​:

"Tony Cook via RT" <perlbug-followup@​perl.org> writes​:

On Sat, 12 Jan 2019 07​:58​:09 -0800, viy@​altlinux.org wrote​:

This is a bug report for perl from viy@​altlinux.org,
generated with the help of perlbug 1.40 running under perl 5.22.3.

On normal system
$ perl -le 'use warnings; print $^X'
/usr/bin/perl5.28.1

In a chroot without /proc or just with sudo umount /proc
$ perl -le 'use warnings; print $^X'
Use of uninitialized value ...

Current implementation of $^X assumes that /proc/self/exe
is always available and accessible on Linux.
It is not true; For example, in ALT Linux
secure chroot build environment does not mount /proc
by default.
Other example is early stages of system initialization
or system boot failure where /proc is not yet mounted
or failed to mount.

In that case, $^X should be PL_origargv[0].
Instead, it is undefined.

As a result, perl tools can fail or change its behaviour.

for example, now ExtUtils​::MakeMaker fails without /proc​:
+ /usr/bin/perl Makefile.PL PREFIX=/usr INSTALLDIRS=vendor
Use of uninitialized value $_[0] in substitution (s///) at
/usr/share/perl5/File/Basename.pm line 341.
fileparse()​: need a valid pathname at
/usr/share/perl5/ExtUtils/MM_Unix.pm line 1128.
[...]
and perl modules can not be built in chroot without /proc.
It is regression compared to perl 5.26.

The code already has a fallback to​:

sv_setpv(caret_x, PL_origargv[0]);

if the readlink() fails, which it should if /proc isn't mounted.

If that's not happening can you produce a relevant strace?

It does now, but didn't in 5.28, c.f.
https://rt.perl.org/Public/Bug/Display.html?id=133573 and
https://perl5.git.perl.org/perl.git/commitdiff/03b94aa47e981af3c7b0118bfb11facda2b95251

Since this was a regression in 5.28 (introduced in
https://perl5.git.perl.org/perl.git/commitdiff/fca5fb9612a125f48173bedf2c079778d7bc54dd),
I reckon the fix is eligible for backporting.

Thanks, I've added it to the votes file and voted for it in 758a695.

Tony

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants