Perl / perl5

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

Safe.PM broken with packages, dies silently #2056

Closed p5pRT closed 20 years ago

p5pRT commented 24 years ago

Migrated from rt.perl.org#3335 (status was 'resolved')

Searchable as RT3335$

p5pRT commented 24 years ago

From scrytch@uswest.net

Created by chuck@abulafia.localdomain

I am trying to use Safe.pm with Template.pm\, with the following​:

$s = new Safe("BigHouse"); $s->deny_only(qw(​:dangerous)); $s->reval('use Template; my $tmpl = new Template;');

Works perfectly outside a safe. Inside it\, I get the error in my log​: [Tue Jun 6 22​:59​:39 2000] [error] [client 127.0.0.1] FastCGI​: server "/opt/apache/htdocs/naga/dtest.fcgi" stderr​: Can't locate object method "new" via package "Template" at (eval 11) line 1.

I tried instantiating a template from outside the safe\, sharing it with the safe\, then calling the ->process() method on it. Works if I use it outside the safe\, not in\, can't find the method.

The test case I tried has even more mysterious breakage Created a file Foo.pm\, with the following content​:

package Foo;

sub new {   my $class = shift;   return bless { message => "hello world\n" }\, $class; }

sub hi {   my $self = shift;   print $self->{message}; } 1;

Then testsafe.pl with this content

#!/usr/bin/perl -w use Safe; use Foo;

my $greeting = new Foo; $greeting->hi;

my $s = new Safe; $s->deny_only(qw(​:base_thread)); # deny pretty near nothing $s->reval(q{ print "-- in a safe --\n";   use Foo;   my $f = new Foo;   print "Is anybody out there?\n";   $f->hi;}); print "-- out of a safe --\n";

I get the following output​: hello world -- in a safe -- -- out of a safe --

If I put the constructor in an eval\, it does print the "Is anybody out there?" line\, but not hello world. $@​ and $! are not set after the eval.

Two problems here\, really... failing to find package members\, and dying completely silently.

Perl Info ``` This perlbug was built using Perl 5.00502 - $Date: 1999/01/17 09:53:34 $ It is being executed now by Perl 5.006 - Mon May 8 16:41:53 MDT 2000. Site configuration information for perl 5.006: Configured by chuck at Mon May 8 16:41:53 MDT 2000. Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: Platform: osname=freebsd, osvers=4.0-stable, archname=i386-freebsd uname='freebsd abulafia 4.0-stable freebsd 4.0-stable #2: wed may 3 23:08:22 mdt 2000 chuck@abulafia:usrsrcsyscompileabulafia i386 ' config_args='-de' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef Compiler: cc='cc', optimize='-O', gccversion=2.95.2 19991024 (release) cppflags='-fno-strict-aliasing -I/usr/local/include' ccflags ='-fno-strict-aliasing -I/usr/local/include' stdchar='char', d_stdstdio=undef, usevfork=true intsize=4, longsize=4, ptrsize=4, doublesize=8 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags ='-Wl,-E -L/usr/local/lib' libpth=/usr/lib /usr/local/lib libs=-lgdbm -lm -lc -lcrypt libc=, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-DPIC -fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl 5.006: /usr/local/lib/perl5/5.6.0/i386-freebsd /usr/local/lib/perl5/5.6.0 /usr/local/lib/perl5/site_perl/5.6.0/i386-freebsd /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl . Environment for perl 5.006: HOME=/home/chuck LANG (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/chuck/bin:/usr/libexec:/usr/local/libexec:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/games:/usr/java/bin:/usr/local/bin:/usr/X11R6/bin:/opt/apache/bin:/opt/apache_1.3.12/bin:/opt/dev-apache/bin:/opt/mason/bin:/opt/python/bin:/opt/roxen/bin:/usr/X11R6/bin PERL_BADLANG (unset) SHELL=/usr/local/bin/bash ```
p5pRT commented 24 years ago

From [Unknown Contact. See original ticket]

This is a bug report for perl from chuck@​abulafia.localdomain\, generated with the help of perlbug 1.26 running under perl 5.006.

----------------------------------------------------------------- [Please enter your report here]

I am trying to use Safe.pm with Template.pm\, with the following​:

$s = new Safe("BigHouse"); $s->deny_only(qw(​:dangerous)); $s->reval('use Template; my $tmpl = new Template;');

Works perfectly outside a safe. Inside it\, I get the error in my log​: [Tue Jun 6 22​:59​:39 2000] [error] [client 127.0.0.1] FastCGI​: server "/opt/apache/htdocs/naga/dtest.fcgi" stderr​: Can't locate object method "new" via package "Template" at (eval 11) line 1.

I tried instantiating a template from outside the safe\, sharing it with the safe\, then calling the ->process() method on it. Works if I use it outside the safe\, not in\, can't find the method.

The test case I tried has even more mysterious breakage Created a file Foo.pm\, with the following content​:

package Foo;

sub new { my $class = shift; return bless { message => "hello world\n" }\, $class; }

sub hi { my $self = shift; print $self->{message}; } 1;

Then testsafe.pl with this content

#!/usr/bin/perl -w use Safe; use Foo;

my $greeting = new Foo; $greeting->hi;

my $s = new Safe; $s->deny_only(qw(​:base_thread)); # deny pretty near nothing $s->reval(q{ print "-- in a safe --\n"; use Foo; my $f = new Foo; print "Is anybody out there?\n"; $f->hi;}); print "-- out of a safe --\n";

I get the following output​: hello world -- in a safe -- -- out of a safe --

If I put the constructor in an eval\, it does print the "Is anybody out there?" line\, but not hello world. $@​ and $! are not set after the eval.

Two problems here\, really... failing to find package members\, and dying completely silently.

[Please do not change anything below this line] -----------------------------------------------------------------

--- This perlbug was built using Perl 5.00502 - $Date​: 1999/01/17 09​:53​:34 $ It is being executed now by Perl 5.006 - Mon May 8 16​:41​:53 MDT 2000.

Site configuration information for perl 5.006​:

Configured by chuck at Mon May 8 16​:41​:53 MDT 2000.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration​: Platform​: osname=freebsd\, osvers=4.0-stable\, archname=i386-freebsd uname='freebsd abulafia 4.0-stable freebsd 4.0-stable #2​: wed may 3 23​:08​:22 mdt 2000 chuck@​abulafia​:usrsrcsyscompileabulafia i386 ' config_args='-de' hint=recommended\, useposix=true\, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef Compiler​: cc='cc'\, optimize='-O'\, gccversion=2.95.2 19991024 (release) cppflags='-fno-strict-aliasing -I/usr/local/include' ccflags ='-fno-strict-aliasing -I/usr/local/include' stdchar='char'\, d_stdstdio=undef\, usevfork=true intsize=4\, longsize=4\, ptrsize=4\, doublesize=8 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, usemymalloc=n\, prototype=define Linker and Libraries​: ld='cc'\, ldflags ='-Wl\,-E -L/usr/local/lib' libpth=/usr/lib /usr/local/lib libs=-lgdbm -lm -lc -lcrypt libc=\, so=so\, useshrplib=false\, libperl=libperl.a Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags='-DPIC -fpic'\, lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:

--- @​INC for perl 5.006​: /usr/local/lib/perl5/5.6.0/i386-freebsd /usr/local/lib/perl5/5.6.0 /usr/local/lib/perl5/site_perl/5.6.0/i386-freebsd /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl .

--- Environment for perl 5.006​: HOME=/home/chuck LANG (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/chuck/bin​:/usr/libexec​:/usr/local/libexec​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/usr/local/sbin​:/usr/games​:/usr/java/bin​:/usr/local/bin​:/usr/X11R6/bin​:/opt/apache/bin​:/opt/apache_1.3.12/bin​:/opt/dev-apache/bin​:/opt/mason/bin​:/opt/python/bin​:/opt/roxen/bin​:/usr/X11R6/bin PERL_BADLANG (unset) SHELL=/usr/local/bin/bash

p5pRT commented 24 years ago

From [Unknown Contact. See original ticket]

This is a bug report for perl from chuck@​abulafia.localdomain\, generated with the help of perlbug 1.26 running under perl 5.006.

----------------------------------------------------------------- [Please enter your report here]

I am trying to use Safe.pm with Template.pm\, with the following​:

$s = new Safe("BigHouse"); $s->deny_only(qw(​:dangerous)); $s->reval('use Template; my $tmpl = new Template;');

Works perfectly outside a safe. Inside it\, I get the error in my log​: [Tue Jun 6 22​:59​:39 2000] [error] [client 127.0.0.1] FastCGI​: server "/opt/apache/htdocs/naga/dtest.fcgi" stderr​: Can't locate object method "new" via package "Template" at (eval 11) line 1.

I tried instantiating a template from outside the safe\, sharing it with the safe\, then calling the ->process() method on it. Works if I use it outside the safe\, not in\, can't find the method.

The test case I tried has even more mysterious breakage Created a file Foo.pm\, with the following content​:

package Foo;

sub new { my $class = shift; return bless { message => "hello world\n" }\, $class; }

sub hi { my $self = shift; print $self->{message}; } 1;

Then testsafe.pl with this content

#!/usr/bin/perl -w use Safe; use Foo;

my $greeting = new Foo; $greeting->hi;

my $s = new Safe; $s->deny_only(qw(​:base_thread)); # deny pretty near nothing $s->reval(q{ print "-- in a safe --\n"; use Foo; my $f = new Foo; print "Is anybody out there?\n"; $f->hi;}); print "-- out of a safe --\n";

I get the following output​: hello world -- in a safe -- -- out of a safe --

If I put the constructor in an eval\, it does print the "Is anybody out there?" line\, but not hello world. $@​ and $! are not set after the eval.

Two problems here\, really... failing to find package members\, and dying completely silently.

[Please do not change anything below this line] -----------------------------------------------------------------

--- This perlbug was built using Perl 5.00502 - $Date​: 1999/01/17 09​:53​:34 $ It is being executed now by Perl 5.006 - Mon May 8 16​:41​:53 MDT 2000.

Site configuration information for perl 5.006​:

Configured by chuck at Mon May 8 16​:41​:53 MDT 2000.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration​: Platform​: osname=freebsd\, osvers=4.0-stable\, archname=i386-freebsd uname='freebsd abulafia 4.0-stable freebsd 4.0-stable #2​: wed may 3 23​:08​:22 mdt 2000 chuck@​abulafia​:usrsrcsyscompileabulafia i386 ' config_args='-de' hint=recommended\, useposix=true\, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef Compiler​: cc='cc'\, optimize='-O'\, gccversion=2.95.2 19991024 (release) cppflags='-fno-strict-aliasing -I/usr/local/include' ccflags ='-fno-strict-aliasing -I/usr/local/include' stdchar='char'\, d_stdstdio=undef\, usevfork=true intsize=4\, longsize=4\, ptrsize=4\, doublesize=8 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, usemymalloc=n\, prototype=define Linker and Libraries​: ld='cc'\, ldflags ='-Wl\,-E -L/usr/local/lib' libpth=/usr/lib /usr/local/lib libs=-lgdbm -lm -lc -lcrypt libc=\, so=so\, useshrplib=false\, libperl=libperl.a Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags='-DPIC -fpic'\, lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:

--- @​INC for perl 5.006​: /usr/local/lib/perl5/5.6.0/i386-freebsd /usr/local/lib/perl5/5.6.0 /usr/local/lib/perl5/site_perl/5.6.0/i386-freebsd /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl .

--- Environment for perl 5.006​: HOME=/home/chuck LANG (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/chuck/bin​:/usr/libexec​:/usr/local/libexec​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/usr/local/sbin​:/usr/games​:/usr/java/bin​:/usr/local/bin​:/usr/X11R6/bin​:/opt/apache/bin​:/opt/apache_1.3.12/bin​:/opt/dev-apache/bin​:/opt/mason/bin​:/opt/python/bin​:/opt/roxen/bin​:/usr/X11R6/bin PERL_BADLANG (unset) SHELL=/usr/local/bin/bash

p5pRT commented 23 years ago

From @gsar

On Wed\, 07 Jun 2000 15​:10​:53 +0200\, Richard Foley^W^WChuck Adams wrote​:

#!/usr/bin/perl -w use Safe; use Foo;

my $greeting = new Foo; $greeting->hi;

my $s = new Safe; $s->deny_only(qw(​:base_thread)); # deny pretty near nothing $s->reval(q{ print "-- in a safe --\n"; use Foo; my $f = new Foo; print "Is anybody out there?\n"; $f->hi;}); print "-- out of a safe --\n";

I get the following output​: hello world -- in a safe -- -- out of a safe --

If I put the constructor in an eval\, it does print the "Is anybody out there?" line\, b ut not hello world. $@​ and $! are not set after the eval.

Two problems here\, really... failing to find package members\, and dying completely sil ently.

This patch is meant to fix one of those problems. If you can modify your test into a form suitable for t/lib/safe*.t\, that would be wonderful. Thanks.

Sarathy gsar@​ActiveState.com

Inline Patch ```diff -----------------------------------8<----------------------------------- Change 6285 by gsar@auger on 2000/06/30 02:05:28 localize %INC in a Safe compartment so that use/require work (many other magic globals probably need similar treatment) Affected files ... ... //depot/perl/ext/Opcode/Opcode.xs#24 edit Differences ... ==== //depot/perl/ext/Opcode/Opcode.xs#24 (text) ==== Index: perl/ext/Opcode/Opcode.xs --- perl/ext/Opcode/Opcode.xs.~1~ Thu Jun 29 19:05:33 2000 +++ perl/ext/Opcode/Opcode.xs Thu Jun 29 19:05:33 2000 @@ -250,7 +250,7 @@ save_aptr(&PL_endav); PL_endav = (AV*)sv_2mortal((SV*)newAV()); /* ignore END blocks for now */ - save_hptr(&PL_defstash); /* save current default stack */ + save_hptr(&PL_defstash); /* save current default stash */ /* the assignment to global defstash changes our sense of 'main' */ PL_defstash = gv_stashpv(Package, GV_ADDWARN); /* should exist already */ save_hptr(&PL_curstash); @@ -263,6 +263,10 @@ sv_free((SV*)GvHV(gv)); GvHV(gv) = (HV*)SvREFCNT_inc(PL_defstash); + /* %INC must be clean for use/require in compartment */ + save_hash(PL_incgv); + GvHV(PL_incgv) = (HV*)SvREFCNT_inc(GvHV(gv_HVadd(gv_fetchpv("INC",TRUE,SVt_PVHV)))); + PUSHMARK(SP); perl_call_sv(codesv, GIMME|G_EVAL|G_KEEPERR); /* use callers context */ SPAGAIN; /* for the PUTBACK added by xsubpp */ End of Patch. ```
p5pRT commented 23 years ago

From [Unknown Contact. See original ticket]

I'm one of those folks that use modules inside of Safe​:: partitions. While Sarathy's patch to "localize" %INC is one necessary part of using modules inside of Safe partitions\, it isn't quite enough...

As the following snippet of code shows​:

#! perl use Safe; $s = new Safe 'FOO'; $s->permit('​:all'); $s->reval('@​c = caller; print qq(called from module "$c[0]"\n);');

(you'll get 'called from module "FOO"' with an unmodified Opcode.XS for Perl versions back to ~5.002)

Code running inside of a Safe partition that checks 'caller' will get the partition name. No problem\, except that there are modules out there that use 'caller' to do their exporting\, and they will fail horribly.

The solution is a small patch to Opcode.xs that changes the HvNAME of partition's stash to "main". You still reference it from the outside via $FOO​::whatever\, but code inside the partition sees a package name of "main​::" and the tricky exporting logic works correctly.

The second problem addressed by the patch below is that filetests on _ fail inside a Safe partition. But first a program to demonstrate the problem​:

#! perl use Safe; $s = new Safe 'FOO'; $s->permit('​:all'); $script = \<\<'TESTSCRIPT'; opendir(D\,'.') || die('horribly'); while (defined($d = readdir(D))) {   $d =~ s/\.dir$// if $^O eq 'VMS';   next if !(-d $d);   print "directory $d is ".((-d $d && -w _) ? '' : 'not ')."writable\n"; } closedir(D); TESTSCRIPT print "--------------- not in Safe​:: ----------------\n"; eval($script); print "--------------- in Safe​:: ----------------\n"; $s->reval($script); print "--------------- done ----------------\n";

This code checks for subdirectories and whether they are writable; Prior to the patch\, you should see that all of the subdirectories tested in the Safe partition are considered "not writable"\, even if they are.

The reason is that when compiling code in the Safe partition _ is looked up in the partition stash...then the gv for _ is compared to PL_defgv and found to be different\, bypassing the "use the results of the last stat" logic.

Again the fix is in Opcode.xs\, by creating an entry for _ in the partition stash and pointing it to the "real\, true main​::_". Or at least to PL_defgv.

There's a bunch of global symbols that need to be either set (because they're no longer global inside the partition) or localized around calls to the code inside the partition\, but that can be handled in Perl code\, and doesn't really affect module loading.

Patch for Opcode for Perl >= 5.005.59

1) make routines in Safe​:: partitions think they are in main​:: 2) connect the _ in the partition to the global _

Inline Patch ```diff --- ext/Opcode/Opcode.xs-orig Wed Jul 26 07:00:15 2000 +++ ext/Opcode/Opcode.xs Wed Jul 26 06:59:39 2000 @@ -253,6 +253,12 @@ save_hptr(&PL_defstash); /* save current default stack */ /* the assignment to global defstash changes our sense of 'main' */ PL_defstash = gv_stashpv(Package, GV_ADDWARN); /* should exist already */ + if (strNE(HvNAME(PL_defstash),"main")) { + Safefree(HvNAME(PL_defstash)); + HvNAME(PL_defstash) = savepv("main"); /* make it think it's in main:: */ + hv_store(PL_defstash,"_",1,(SV *)PL_defgv,0); /* connect _ to global */ + SvREFCNT_inc((SV *)PL_defgv); /* want to keep _ around! */ + } save_hptr(&PL_curstash); PL_curstash = PL_defstash; ```