Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.9k stars 541 forks source link

ext/POSIX/t/wrappers.t fails when compiling on OpenLDAP user because of getgrgid() + fork() interaction #13779

Open p5pRT opened 10 years ago

p5pRT commented 10 years ago

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

Searchable as RT121755$

p5pRT commented 10 years ago

From lvaliukas@cyber.law.harvard.edu

Created by lvaliukas@cyber.law.harvard.edu

When compiling Perl-blead with Perlbrew\, the ext/POSIX/t/wrappers.t unit test fails with​:

  ext/POSIX/t/wrappers .......................................... # Failed test 'getc'   # at t/wrappers.t line 217.   # got​: undef   # expected​: '1'   FAILED at test 82

I suspect that the unit test doesn't pass because fork() silently fails right after the getgrgid() call. For example\, when running this script​:

  use strict;   use warnings;  
  my $id = $(;   say STDERR "group id​: $id";   my $getgrgid_result = getgrgid $id;   say STDERR "getgrgid​: $getgrgid_result";

  my $pid = fork();

  fail("fork failed​: $!") unless defined $pid;

  if ($pid) {   say STDERR "MAIN PROCESS";   } else {   say STDERR "CHILD PROCESS";   }

The *expected* output is​:

  group id​: 10018 113 10018   getgrgid​: bcis-interns   MAIN PROCESS   CHILD PROCESS

But the *actual* output I get with Perl-blead is​:

  group id​: 10018 113 10018   getgrgid​: bcis-interns   MAIN PROCESS

I should also note that we're building Perl on an OpenLDAP user\, and that the sample script (or the unit test) doesn't fail on a "normal" user (the one from /etc/passwd). Also\, Perl v5.16.3 provides the *expected* output for the test script listed above.

I would be very thankful if you could provide me with any tips and hints on how I could debug / help you to fix this issue.

Perl Info ``` Flags: category=library severity=high module=POSIX Site configuration information for perl 5.19.12: Configured by lvaliukas at Mon Apr 28 11:20:18 EDT 2014. Summary of my perl5 (revision 5 version 19 subversion 12) configuration: Snapshot of: 96258673547f51dc588c290d9c8ff3d9b2b93397 Platform: osname=linux, osvers=3.11.0-19-generic, archname=x86_64-linux uname='linux new-chloe.law.harvard.edu 3.11.0-19-generic #33~precise1-ubuntu smp wed mar 12 21:16:27 utc 2014 x86_64 x86_64 x86_64 gnulinux ' config_args='-de -Dprefix=/berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead -Dusedevel -Aeval:scriptdir=/berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead/bin' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.6.3', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=libc-2.15.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.15' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector' @INC for perl 5.19.12: /berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead/lib/site_perl/5.19.12/x86_64-linux /berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead/lib/site_perl/5.19.12 /berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead/lib/5.19.12/x86_64-linux /berkman/home/lvaliukas/perl5/perlbrew/perls/perl-blead/lib/5.19.12 . Environment for perl 5.19.12: HOME=/berkman/home/lvaliukas LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/space/mediacloud/bin/bin:/mediacloud/data/mongoDB/mongodb-linux-x86_64-2.2.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 10 years ago

From @eserte

Dana Pon 28. Tra 2014\, 09​:24​:40\, lvaliukas@​cyber.law.harvard.edu reče​:

When compiling Perl-blead with Perlbrew\, the ext/POSIX/t/wrappers.t unit test fails with​:

ext/POSIX/t/wrappers .......................................... # Failed test 'getc' # at t/wrappers.t line 217. # got​: undef # expected​: '1' FAILED at test 82

I suspect that the unit test doesn't pass because fork() silently fails right after the getgrgid() call. For example\, when running this script​:

I also saw this problem in an environment where LDAP for user authentication is in use. My current workaround is​:

  if ($] >= 5.018) {   warn "perl $]\, we need the LDAP hack :-(...\n";   $SIG{PIPE}='IGNORE'; # XXX the ldap hack :-(   }

The problem does not appear with perl 5.16.3 on the same system.

Regards\,   Slaven

p5pRT commented 10 years ago

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

p5pRT commented 10 years ago

From lvaliukas@cyber.law.harvard.edu

On Fri May 02 07​:01​:31 2014\, slaven@​rezic.de wrote​:

I also saw this problem in an environment where LDAP for user authentication is in use. My current workaround is​:

if ($] >= 5.018) { warn "perl $]\, we need the LDAP hack :-(...\n"; $SIG{PIPE}='IGNORE'; # XXX the ldap hack :-( }

The problem does not appear with perl 5.16.3 on the same system.

Regards\, Slaven

Thanks Slaven! It's good to see that we're not the only ones who encounter this bug!

The workaround would probably do fine in our own code (at least temporary)\, but I'm worried that dependency CPAN modules (which we do not control) might be using getgrgid() themselves and potentially crashing Perl / introducing security issues to the rest of the system.

Would you be able to comment on your OpenLDAP infrastructure? In other words\, have you found a way to replicate a bug on a "clean" system?

p5pRT commented 10 years ago

From @eserte

Dana Pet 02. Svibanj 2014\, 11​:22​:19\, lvaliukas@​cyber.law.harvard.edu reče​:

On Fri May 02 07​:01​:31 2014\, slaven@​rezic.de wrote​:

I also saw this problem in an environment where LDAP for user authentication is in use. My current workaround is​:

if ($] >= 5.018) { warn "perl $]\, we need the LDAP hack :-(...\n"; $SIG{PIPE}='IGNORE'; # XXX the ldap hack :-( }

The problem does not appear with perl 5.16.3 on the same system.

Regards\, Slaven

Thanks Slaven! It's good to see that we're not the only ones who encounter this bug!

The workaround would probably do fine in our own code (at least temporary)\, but I'm worried that dependency CPAN modules (which we do not control) might be using getgrgid() themselves and potentially crashing Perl / introducing security issues to the rest of the system.

Would you be able to comment on your OpenLDAP infrastructure? In other words\, have you found a way to replicate a bug on a "clean" system?

I am just a user in a company LDAP setup. Actually I wasn't aware that LDAP was in use\, until I stumbled over this problem and tried to find out what's going on using strace. I found out that some Linux component was opening the LDAP connection when the perl process was calling getpwuid(). After a fork() strange things happen to the (also forked) LDAP connection\, leading to a SIGPIPE and the child being killed.

This smells like a bug in the LDAP implementation. But nevertheless it would be a good thing if it could be workaround in the Perl interpreter.

Regards\,   Slaven

p5pRT commented 10 years ago

From @Leont

On Fri\, May 2\, 2014 at 11​:34 PM\, slaven@​rezic.de via RT \< perlbug-followup@​perl.org> wrote​:

Thanks Slaven! It's good to see that we're not the only ones who encounter this bug!

The workaround would probably do fine in our own code (at least temporary)\, but I'm worried that dependency CPAN modules (which we do not control) might be using getgrgid() themselves and potentially crashing Perl / introducing security issues to the rest of the system.

Would you be able to comment on your OpenLDAP infrastructure? In other words\, have you found a way to replicate a bug on a "clean" system?

I am just a user in a company LDAP setup. Actually I wasn't aware that LDAP was in use\, until I stumbled over this problem and tried to find out what's going on using strace. I found out that some Linux component was opening the LDAP connection when the perl process was calling getpwuid(). After a fork() strange things happen to the (also forked) LDAP connection\, leading to a SIGPIPE and the child being killed.

This smells like a bug in the LDAP implementation. But nevertheless it would be a good thing if it could be workaround in the Perl interpreter.

Indeed it does. I'm guessing the a shutdown(2) is involved. This is a sensible thing to do if your process actually owns the connection but unlike close it's actually global so if the other process.

Swapping libnss-ldap/libnss-ldapd might help (but may not be an option in production).

Leon

p5pRT commented 10 years ago

From bitcard@larochelle.name

According to The Open Group Specification getpwuid() is not thread safe.

( See http​://pubs.opengroup.org/onlinepubs/009695399/functions/getpwuid.html).

I realize the fork()ing is very different from threads but I wonder if getpwuid_r()\, the thread-safe version of getpwuid() should be used instead.

On Fri May 02 14​:34​:40 2014\, slaven@​rezic.de wrote​:

I am just a user in a company LDAP setup. Actually I wasn't aware that LDAP was in use\, until I stumbled over this problem and tried to find out what's going on using strace. I found out that some Linux component was opening the LDAP connection when the perl process was calling getpwuid(). After a fork() strange things happen to the (also forked) LDAP connection\, leading to a SIGPIPE and the child being killed.

p5pRT commented 10 years ago

From @Leont

On Mon\, May 5\, 2014 at 11​:57 PM\, dlarochelle via RT \< perlbug-followup@​perl.org> wrote​:

According to The Open Group Specification getpwuid() is not thread safe.

( See http​://pubs.opengroup.org/onlinepubs/009695399/functions/getpwuid.html).

I realize the fork()ing is very different from threads but I wonder if getpwuid_r()\, the thread-safe version of getpwuid() should be used instead.

The reentrant APIs are already used on threaded perls (in a rather confusing manner)\, and are not relevant to fork() anyway.

Leon

p5pRT commented 10 years ago

From @lizmat

On 06 May 2014\, at 12​:09\, Leon Timmermans \fawaka@&#8203;gmail\.com wrote​:

On Mon\, May 5\, 2014 at 11​:57 PM\, dlarochelle via RT \perlbug\-followup@&#8203;perl\.org wrote​: According to The Open Group Specification getpwuid() is not thread safe.

( See http​://pubs.opengroup.org/onlinepubs/009695399/functions/getpwuid.html).

I realize the fork()ing is very different from threads but I wonder if getpwuid_r()\, the thread-safe version of getpwuid() should be used instead.

The reentrant APIs are already used on threaded perls (in a rather confusing manner)\, and are not relevant to fork() anyway.

Still\, some XS might want to do threads on a non-threaded perl​: for those cases it would make sense to also use the re-entrant versions. And are we talking about hot paths here?

Liz

p5pRT commented 10 years ago

From @Leont

On Tue\, May 6\, 2014 at 12​:46 PM\, Elizabeth Mattijsen \liz@&#8203;dijkmat\.nl wrote​:

Still\, some XS might want to do threads on a non-threaded perl​: for those cases it would make sense to also use the re-entrant versions. And are we talking about hot paths here?

Agreed. It can be enabled on non-threaded perls with the -Dusereentrant option. Another issue is that these wrappers are not exposed to XS modules by default (though it seems a «#define PERL_REENTR_API 1» would fix that). Path hotness isn't really a factor\, I don't expect the functions to be slower (they just use an explicit buffer instead of an implicit static one\, otherwise they're the same)\, but it does increase the size of the interpreter struct (not that I personally care much about that).

Leon

p5pRT commented 10 years ago

From lvaliukas@cyber.law.harvard.edu

On Tue May 06 05​:16​:26 2014\, LeonT wrote​:

Agreed. It can be enabled on non-threaded perls with the -Dusereentrant option.

I've recompiled Perl-blead with "-Dusereentrant"\, but the bug is still present.

p5pRT commented 10 years ago

From @Leont

On Tue\, May 13\, 2014 at 5​:39 PM\, Linas Valiukas via RT \< perlbug-followup@​perl.org> wrote​:

On Tue May 06 05​:16​:26 2014\, LeonT wrote​:

Agreed. It can be enabled on non-threaded perls with the -Dusereentrant option.

I've recompiled Perl-blead with "-Dusereentrant"\, but the bug is still present.

We were getting side-tracked\, of course that didn't fix it. Everything points at the bug being in your ldap nss implementation\, not in Perl. One could test this with a simple C program.

Leon