You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Joel Palmius <jo...@mh.se> on 2003/07/24 13:16:24 UTC

[mp1] "Safe" segfaults with mp1

This works, separate file /tmp/test.pl:

  use Safe;

  my($compartment) = new Safe;
  $compartment->permit(qw(:browse));
  $compartment->reval("print \"gnu\n\";");

  if($@)
  {
    die $@;
  }

  print "\n\n";

(Script prints "gnu")

This does not work, in perl-handler Handler.pm:

  [...]

  use Safe;

  sub handler
  {
    my $r = shift;

    return DECLINED unless $r->content_type() eq 'text/html';

    [...]

    print "Content-type: text/plain\n\n";
 
    my($compartment) = new Safe;
    $compartment->permit(qw(:browse));
    $compartment->reval("print \"gnu\n\";");

    if($@)
    {
      die $@;
    }

    [...]

Request results in segfault:

  [Thu Jul 24 12:59:56 2003] [notice] child pid 3003 exit signal 
  Segmentation fault (11)

If I comment out $compartment->reval(), then the process does not 
segfault. 

Since Safe works outside mod_perl, I'm guessing there's something with the 
mod_perl environment that messes things up. 

I have run the rest of the setup for several months now without noticing
any other ill effects, so I don't think it is a bad installation of
something. Setup is:

  Gentoo linux
  perl 5.8.0
  apache 1.3.27
  mod_perl 1.27

Ideas anyone?

  // Joel

Re: [mp1] "Safe" segfaults with mp1

Posted by Stas Bekman <st...@stason.org>.
Joel Palmius wrote:
> Ah, well, after a five hours of experimentation I thought up a working
> workaround anyway.
> 
> This works with an unpatched version of mp1 ($substr is any perl code 
> fetched from external source):
> 
>       my(@ops) = split(/\x0a/,$substr);
>       my($cell,$reval);
> 
>       foreach $cell (@ops)
>       {
>         $cell =~ s/^[\x09\ ]+//g;
>         $cell =~ s/^print\ /\$output\ \.\=\ /;
>         if($cell)
>         {
>           $reval .= $cell . "\n";
>         }
>       }
> 
>       my($output);
> 
>       $reval .= "\$output;\n";
> 
>       my($compartment) = new Safe("Tempo");
>       $compartment->permit(qw(:browse));
>       $output = $compartment->reval($reval);
>       if($@)
>       {
>         $self->{ERROR} = gettext("Security exception: " . $@);
>         $self->{ERRORCODE} = 99;
>       }
> 
>       print $output;
> 
> I just replace all print statements with "$output .= ", and then make 
> sure that the reval results in the final contents of $output, which I then 
> print outside the reval().
> 
> Works fine now. So far nothing else has crashed, although I'm somewhat
> suspicious of a number of rather random events in the code. I'm almost
> certain this is me having messed up something else though.

Neat. I expect it to work as long as you do simple things, it's going to be 
much harder to make it working with more complex code. However I was trying to 
simplify your logic and use IO::String to catch the output:

   print "Content-type: text/plain\n\n";
   use warnings;
   use strict;

   use Safe;

   our $output = '';
   my($cmpt) = new Safe 'MyRoot';
   $cmpt->share('$output');
   $cmpt->permit(qw(leaveeval entereval caller require :browse ));

   $cmpt->reval(<<'EOI');

   # redirect prints to a buffer
   use IO::String;
   my $str_fh = IO::String->new($output);
   select $str_fh;

   # put the normal code here
   print "gnu\n";
EOI

   if($@)
   {
     die $@;
   }

   select STDOUT;
   print $output;


> However, if I'm not supposed to use Safe in conjunction with mp, what *am* 
> I supposed to use? 

I didn't say that. I just said that if it doesn't work for you... but as you 
have just shown that TIMTOWTDI ;)

> I might be possible to convince to write a version of Safe specifically
> for mp1, although I expect I shall have to experience more problems with
> the existing Safe code to be bothered. :-)

You can always give it a try.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: [mp1] "Safe" segfaults with mp1

Posted by Joel Palmius <jo...@mh.se>.
Ah, well, after a five hours of experimentation I thought up a working
workaround anyway.

This works with an unpatched version of mp1 ($substr is any perl code 
fetched from external source):

      my(@ops) = split(/\x0a/,$substr);
      my($cell,$reval);

      foreach $cell (@ops)
      {
        $cell =~ s/^[\x09\ ]+//g;
        $cell =~ s/^print\ /\$output\ \.\=\ /;
        if($cell)
        {
          $reval .= $cell . "\n";
        }
      }

      my($output);

      $reval .= "\$output;\n";

      my($compartment) = new Safe("Tempo");
      $compartment->permit(qw(:browse));
      $output = $compartment->reval($reval);
      if($@)
      {
        $self->{ERROR} = gettext("Security exception: " . $@);
        $self->{ERRORCODE} = 99;
      }

      print $output;

I just replace all print statements with "$output .= ", and then make 
sure that the reval results in the final contents of $output, which I then 
print outside the reval().

Works fine now. So far nothing else has crashed, although I'm somewhat
suspicious of a number of rather random events in the code. I'm almost
certain this is me having messed up something else though.

However, if I'm not supposed to use Safe in conjunction with mp, what *am* 
I supposed to use? 

I might be possible to convince to write a version of Safe specifically
for mp1, although I expect I shall have to experience more problems with
the existing Safe code to be bothered. :-)

  // Joel


On Thu, 24 Jul 2003, Stas Bekman wrote:

> Joel, I have reproduced the segfault using your test script.
> 
> It's handy to have p5p people sitting next to you. Just asked this question 
> Tim Bunce, and he replied:
> 
>    "Safe is a failed experiment. It works only for several cases. TIEHANDLE is
>    not one of them [print under mod_perl uses a tied STDOUT]. Do not use it if
>    it doesn't work for you."
> 
> I'm supposed to ask Dan Sugalsky whether perl6 will have this functionality 
> designed from the ground up.
> 
> We could prevent the segfault in mod_perl, but you still won't be able to use 
> Safe under it. So IMHO it's not worth the slowdown to do extra checks.
> 
> Should probably add it to the troubleshooting section.
> 
> __________________________________________________________________
> Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
> http://stason.org/     mod_perl Guide ---> http://perl.apache.org
> mailto:stas@stason.org http://use.perl.org http://apacheweek.com
> http://modperlbook.org http://apache.org   http://ticketmaster.com
> 
> 

Re: [mp1] "Safe" segfaults with mp1

Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
> Joel Palmius wrote:
> 

>>   use Safe;
>>
>>   my($compartment) = new Safe;
>>   $compartment->permit(qw(:browse));
>>   $compartment->reval("print \"gnu\n\";");

[...]

>> Request results in segfault:
>>
>>   [Thu Jul 24 12:59:56 2003] [notice] child pid 3003 exit signal   
>> Segmentation fault (11)

[...]

> Joel, I have reproduced the segfault using your test script.
> 
> It's handy to have p5p people sitting next to you. Just asked this 
> question Tim Bunce, and he replied:
> 
>   "Safe is a failed experiment. It works only for several cases. 
> TIEHANDLE is
>   not one of them [print under mod_perl uses a tied STDOUT]. Do not use 
> it if
>   it doesn't work for you."
> 
> I'm supposed to ask Dan Sugalsky whether perl6 will have this 
> functionality designed from the ground up.
> 
> We could prevent the segfault in mod_perl, but you still won't be able 
> to use Safe under it. So IMHO it's not worth the slowdown to do extra 
> checks.
> 
> Should probably add it to the troubleshooting section.

And here is the patch that prevents the segfault. I'm not sure whether it 
should go in. I have attached it as well, since the original had \t in it and 
it'll be certainly mangled.

Index: src/modules/perl/Apache.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Apache.xs,v
retrieving revision 1.128
diff -u -r1.128 Apache.xs
--- src/modules/perl/Apache.xs  6 Jul 2003 04:51:20 -0000       1.128
+++ src/modules/perl/Apache.xs  24 Jul 2003 14:38:33 -0000
@@ -1134,7 +1134,9 @@
         sv_setiv(sendh, 0);
      }
      else {
-       CV *cv = GvCV(gv_fetchpv("Apache::write_client", FALSE, SVt_PVCV));
+        /* should exist already */
+        CV *cv = GvCV(gv_fetchpv("Apache::write_client", GV_ADDWARN, SVt_PVCV));
+        if(!cv) croak("can't find Apache::write_client, are you using Safe.pm?");
         soft_timeout("mod_perl: Apache->print", r);
         PUSHMARK(mark);
  #ifdef PERL_OBJECT



__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

Re: [mp1] "Safe" segfaults with mp1

Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
[...]
> It's handy to have p5p people sitting next to you. Just asked this 
> question Tim Bunce, and he replied:
> 
>   "Safe is a failed experiment. It works only for several cases. 
> TIEHANDLE is
>   not one of them [print under mod_perl uses a tied STDOUT]. Do not use 
> it if
>   it doesn't work for you."
> 
> I'm supposed to ask Dan Sugalsky whether perl6 will have this 
> functionality designed from the ground up.

I just did that and Dan has replied:

   Of course! It's working already!

So if anybody has a few minutes to port mod_perl to perl6....

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: [mp1] "Safe" segfaults with mp1

Posted by Stas Bekman <st...@stason.org>.
Joel Palmius wrote:
> This works, separate file /tmp/test.pl:
> 
>   use Safe;
> 
>   my($compartment) = new Safe;
>   $compartment->permit(qw(:browse));
>   $compartment->reval("print \"gnu\n\";");
> 
>   if($@)
>   {
>     die $@;
>   }
> 
>   print "\n\n";
> 
> (Script prints "gnu")
> 
> This does not work, in perl-handler Handler.pm:
> 
>   [...]
> 
>   use Safe;
> 
>   sub handler
>   {
>     my $r = shift;
> 
>     return DECLINED unless $r->content_type() eq 'text/html';
> 
>     [...]
> 
>     print "Content-type: text/plain\n\n";
>  
>     my($compartment) = new Safe;
>     $compartment->permit(qw(:browse));
>     $compartment->reval("print \"gnu\n\";");
> 
>     if($@)
>     {
>       die $@;
>     }
> 
>     [...]
> 
> Request results in segfault:
> 
>   [Thu Jul 24 12:59:56 2003] [notice] child pid 3003 exit signal 
>   Segmentation fault (11)
> 
> If I comment out $compartment->reval(), then the process does not 
> segfault. 
> 
> Since Safe works outside mod_perl, I'm guessing there's something with the 
> mod_perl environment that messes things up. 
> 
> I have run the rest of the setup for several months now without noticing
> any other ill effects, so I don't think it is a bad installation of
> something. Setup is:
> 
>   Gentoo linux
>   perl 5.8.0
>   apache 1.3.27
>   mod_perl 1.27
> 
> Ideas anyone?

Joel, I have reproduced the segfault using your test script.

It's handy to have p5p people sitting next to you. Just asked this question 
Tim Bunce, and he replied:

   "Safe is a failed experiment. It works only for several cases. TIEHANDLE is
   not one of them [print under mod_perl uses a tied STDOUT]. Do not use it if
   it doesn't work for you."

I'm supposed to ask Dan Sugalsky whether perl6 will have this functionality 
designed from the ground up.

We could prevent the segfault in mod_perl, but you still won't be able to use 
Safe under it. So IMHO it's not worth the slowdown to do extra checks.

Should probably add it to the troubleshooting section.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com