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

Segfault due to stack overflow 'use lib sub{eval"use WHATEVER"};use WHATEVER' #15367

Open
p5pRT opened this issue May 27, 2016 · 7 comments
Open

Comments

@p5pRT
Copy link

p5pRT commented May 27, 2016

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

Searchable as RT128256$

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

From @dcollinsn

Greetings Porters,

I have compiled bleadperl with the afl-gcc compiler using​:

./Configure -Dusedevel -Dprefix='/usr/local/perl-afl' -Dcc='ccache afl-gcc' -Uuselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -Dusequadmath -des
AFL_HARDEN=1 make && make test

And then fuzzed the resulting binary using​:

AFL_NO_VAR_CHECK=1 afl-fuzz -i in -o out bin/perl @​@​

After reducing testcases using `afl-tmin` and performing additional minimization by hand, I have located the following testcase that triggers a segfault in the perl interpreter. The testcase is the file below. On normal builds and debug builds, this segfaults.

dcollins@​nightshade64​:~/perl$ ./perl -Ilib -We 'use lib sub{eval"use WHATEVER"};use WHATEVER'
Deep recursion on anonymous subroutine at (eval 99) line 1.
Segmentation fault

This appears to be a stack overflow bug caused by infinite recursion. Here is the iterating series of stack frames​:

#391 0x0000000000449949 in Perl_call_sv (sv=0x1d23290, flags=13) at perl.c​:2841
#392 0x000000000044eb5a in Perl_call_list (oldscope=8832, paramList=0x1d23230) at perl.c​:5009
#393 0x0000000000435f80 in S_process_special_blocks (floor=181937, fullname=0x8780c0 "BEGIN",
  gv=0x86e730, cv=0x1d23290) at op.c​:8793
#394 0x0000000000435b34 in Perl_newATTRSUB_x (floor=181937, o=0x1d30fe0, proto=0x0, attrs=0x0,
  block=0x1d30fa0, o_is_gv=false) at op.c​:8722
#395 0x000000000042c985 in Perl_utilize (aver=1, floor=181937, version=0x0, idop=0x1d30a08,
  arg=0x0) at op.c​:6096
#396 0x000000000048971d in Perl_yyparse (gramtype=258) at perly.y​:351
#397 0x0000000000564f63 in S_try_yyparse (gramtype=258) at pp_ctl.c​:3233
#398 0x0000000000565843 in S_doeval_compile (gimme=3 '\003', outside=0x86e778, seq=2, hh=0x0)
  at pp_ctl.c​:3383
#399 0x0000000000568678 in Perl_pp_entereval () at pp_ctl.c​:4244
#400 0x0000000000508a25 in Perl_runops_standard () at run.c​:41
#401 0x00000000004497ed in Perl_call_sv (sv=0x8a4d80, flags=3) at perl.c​:2824
#402 0x0000000000566ceb in S_require_file (sv=0x1d230b0) at pp_ctl.c​:3832
#403 0x0000000000567f16 in Perl_pp_require () at pp_ctl.c​:4124
#404 0x0000000000508a25 in Perl_runops_standard () at run.c​:41

Valgrind confirms​:

==39283== Stack overflow in thread #1​: can't grow stack to 0xffe801000
==39283==
==39283== Process terminating with default action of signal 11 (SIGSEGV)
==39283== Access not within mapped region at address 0xFFE801F18
==39283== Stack overflow in thread #1​: can't grow stack to 0xffe801000
==39283== at 0x474CA8​: S_pad_findlex (pad.c​:1115)
==39283== If you believe this happened as a result of a stack
==39283== overflow in your program's main thread (unlikely but
==39283== possible), you can try to increase the size of the
==39283== main thread stack using the --main-stacksize= flag.
==39283== The main thread stack size used in this run was 8388608.
==39283== Stack overflow in thread #1​: can't grow stack to 0xffe801000

Bisect has been decidedly unhelpful, this bug has persisted since at least 5.12.0

**PERL -V**

dcollins@​nightshade64​:~/perldebug$ ./perl -Ilib -V
Summary of my perl5 (revision 5 version 25 subversion 2) configuration​:
  Commit id​: c29dfc6
  Platform​:
  osname=linux, osvers=4.5.0-2-amd64, archname=x86_64-linux-ld
  uname='linux nightshade64 4.5.0-2-amd64 #1 smp debian 4.5.3-2 (2016-05-08) x86_64 gnulinux '
  config_args='-Dusedevel -Dprefix=/usr/local/perl-afl -Dcc=ccache gcc-6.1 -Duselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -DDEBUGGING -DPERL_POISON -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  use64bitint=define, use64bitall=define, uselongdouble=define
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='ccache gcc-6.1', ccflags ='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-g',
  cppflags='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
  ccversion='', gccversion='6.1.0', 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='long double', nvsize=16, Off_t='off_t', lseeksize=8
  alignbytes=16, prototype=define
  Linker and Libraries​:
  ld='ccache gcc-6.1', ldflags =' -fstack-protector-strong -L/usr/local/lib'
  libpth=/usr/local/lib /usr/local/lib/gcc/x86_64-pc-linux-gnu/6.1.0/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=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.22.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.22'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -g -L/usr/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl)​:
  Compile-time options​: DEBUGGING HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE
  PERL_DONT_CREATE_GVSV
  PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP
  PERL_OP_PARENT PERL_PRESERVE_IVUV PERL_USE_DEVEL
  USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES
  USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE
  USE_LOCALE_NUMERIC USE_LOCALE_TIME USE_LONG_DOUBLE
  USE_PERLIO USE_PERL_ATOF
  Built under linux
  Compiled at May 26 2016 17​:57​:37
  @​INC​:
  lib
  /usr/local/perl-afl/lib/site_perl/5.25.2/x86_64-linux-ld
  /usr/local/perl-afl/lib/site_perl/5.25.2
  /usr/local/perl-afl/lib/5.25.2/x86_64-linux-ld
  /usr/local/perl-afl/lib/5.25.2
  /usr/local/perl-afl/lib/site_perl/5.25.1
  /usr/local/perl-afl/lib/site_perl/5.24.0
  /usr/local/perl-afl/lib/site_perl
  .

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

From zefram@fysh.org

Dan Collins wrote​:

This appears to be a stack overflow bug caused by infinite
recursion. Here is the iterating series of stack frames​:

Not a bug. You asked for infinite recursion, and you got it. Code refs
in @​INC get invoked when searching for modules to load. Unlike a Perl
sub calling itself, this recursion uses C stack space, which is how it
ends up SEGVing rather than panicking from lack of memory. But this is
far from the only way to get this effect from Perl code.

-zefram

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

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

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

From @demerphq

On 27 May 2016 03​:44, "Zefram" <zefram@​fysh.org> wrote​:

Dan Collins wrote​:

This appears to be a stack overflow bug caused by infinite
recursion. Here is the iterating series of stack frames​:

Not a bug. You asked for infinite recursion, and you got it. Code refs
in @​INC get invoked when searching for modules to load. Unlike a Perl
sub calling itself, this recursion uses C stack space, which is how it
ends up SEGVing rather than panicking from lack of memory. But this is
far from the only way to get this effect from Perl code.

Seems to me that if it segfaults its a bug. Even if this code should
do bad things that bad thing shouldn't be a segv but something more
graceful.

I vote we leave this open as a low priority ticket in case someone decides
to fix it.

Yves

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

From zefram@fysh.org

demerphq wrote​:

Seems to me that if it segfaults its a bug. Even if this code should
do bad things that bad thing shouldn't be a segv but something more
graceful.

The SEGV for running out of stack space is a pretty clean result.
It's not following a wild pointer into a random part of the address
space​: it's predictably running into the page beyond the stack space,
which is always unmapped. It's as good as the "out of memory" panic,
just coming from the kernel rather than from the Perl infrastructure.

-zefram

@p5pRT
Copy link
Author

p5pRT commented May 30, 2016

From @demerphq

On 27 May 2016 at 15​:10, Zefram <zefram@​fysh.org> wrote​:

demerphq wrote​:

Seems to me that if it segfaults its a bug. Even if this code should
do bad things that bad thing shouldn't be a segv but something more
graceful.

The SEGV for running out of stack space is a pretty clean result.
It's not following a wild pointer into a random part of the address
space​: it's predictably running into the page beyond the stack space,
which is always unmapped. It's as good as the "out of memory" panic,
just coming from the kernel rather than from the Perl infrastructure.

I think its a bug that we don't see recursion warnings, and that we
die with a SEGV.

We used to have this problem in the regex engine, and we always
considered it a bug, albeit a low priority difficult to fix bug.

It seems to me that this case is much the same.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented May 30, 2016

From zefram@fysh.org

demerphq wrote​:

I think its a bug that we don't see recursion warnings,

It did give a recursion warning.

We used to have this problem in the regex engine,

Your problem there was for deep finite recursion, busting the stack in
a computation that would actually complete if allowed to. Furthermore,
this recursion behaviour was readily accessible by using quantifiers
in totally reasonable patterns. In the present case, the computation
can't be made to run to completion by better stack handling, and if it
were tweaked to require only a finite stack depth then it would still
be explicitly recursive code of a perverse form.

-zefram

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

No branches or pull requests

2 participants