Skip Menu |

This queue is for tickets about the POSIX-AtFork CPAN distribution.

Report information
The Basics
Id: 76428
Status: new
Priority: 0/
Queue: POSIX-AtFork

People
Owner: Nobody in particular
Requestors: aleksey.mashanov [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 0.02
Fixed in: (no value)



Subject: Illegal stack write/read in Perl_pp_fork()
In function Perl_pp_fork() EXTEND(SP, 1) is done before call of PerlProc_fork() and PUSHi(childpid) is done after (perl 5.8.8). In situation when stack is extended during callbacks local copy of SP still references to old stack which was destroyed during stack reallocation. Problem can be solved using stack localization during calling of callbacks. Patch is attached.
Subject: perl-POSIX-AtFork-stack.patch
--- AtFork.xs 2010-11-04 04:13:19.000000000 +0300 +++ AtFork.xs 2012-04-09 12:18:38.000000000 +0400 @@ -15,6 +15,66 @@ } my_cxt_t; START_MY_CXT +typedef struct { + PERL_SI *curstackinfo; + AV *curstack; + AV *mainstack; + SV **stack_base; + SV **stack_sp; + SV **stack_max; +} stack_backup_t; + +static void +paf_save_stacks(pTHX, stack_backup_t* bk) { + bk->curstackinfo = PL_curstackinfo; + bk->curstack = PL_curstack; + bk->mainstack = PL_mainstack; + + bk->stack_base = PL_stack_base; + bk->stack_sp = PL_stack_sp; + bk->stack_max = PL_stack_max; +} + +static void +paf_restore_stacks(pTHX, stack_backup_t* bk) { + PL_curstackinfo = bk->curstackinfo; + PL_curstack = bk->curstack; + PL_mainstack = bk->mainstack; + + PL_stack_base = bk->stack_base; + PL_stack_sp = bk->stack_sp; + PL_stack_max = bk->stack_max; +} + +static void +paf_init_stacks(pTHX) { + PL_curstackinfo = new_stackinfo(32, 4); + PL_curstackinfo->si_type = PERLSI_MAIN; + PL_curstack = PL_curstackinfo->si_stack; + PL_mainstack = PL_curstack; + + PL_stack_base = AvARRAY(PL_curstack); + PL_stack_sp = PL_stack_base; + PL_stack_max = PL_stack_base + AvMAX(PL_curstack); +} + +static void +paf_destruct_stacks(pTHX) { + while (PL_curstackinfo->si_next) + PL_curstackinfo = PL_curstackinfo->si_next; + + while (PL_curstackinfo) { + PERL_SI *p = PL_curstackinfo->si_prev; + + if (!PL_dirty) + SvREFCNT_dec (PL_curstackinfo->si_stack); + + Safefree (PL_curstackinfo->si_cxstack); + Safefree (PL_curstackinfo); + PL_curstackinfo = p; + } +} + static void paf_call_list(pTHX_ AV* const av) { const char* const opname = PL_op ? OP_NAME(PL_op) : "(unknown)"; @@ -22,6 +82,9 @@ I32 const len = av_len(av) + 1; I32 i; + stack_backup_t bk; + paf_save_stacks(aTHX, &bk); + paf_init_stacks(aTHX); ENTER; SAVETMPS; opnamesv = sv_2mortal(newSVpv(opname, 0)); @@ -38,6 +101,8 @@ } FREETMPS; LEAVE; + paf_destruct_stacks(aTHX); + paf_restore_stacks(aTHX, &bk); } static void