File tree 7 files changed +175
-2
lines changed
7 files changed +175
-2
lines changed Original file line number Diff line number Diff line change @@ -1093,6 +1093,19 @@ $$ LANGUAGE plperl;
1093
1093
be permitted to use this language.
1094
1094
</para>
1095
1095
1096
+ <warning>
1097
+ <para>
1098
+ Trusted PL/Perl relies on the Perl <literal>Opcode</literal> module to
1099
+ preserve security.
1100
+ Perl
1101
+ <ulink url="https://perldoc.perl.org/Opcode#WARNING">documents</ulink>
1102
+ that the module is not effective for the trusted PL/Perl use case. If
1103
+ your security needs are incompatible with the uncertainty in that warning,
1104
+ consider executing <literal>REVOKE USAGE ON LANGUAGE plperl FROM
1105
+ PUBLIC</literal>.
1106
+ </para>
1107
+ </warning>
1108
+
1096
1109
<para>
1097
1110
Here is an example of a function that will not work because file
1098
1111
system operations are not allowed for security reasons:
Original file line number Diff line number Diff line change @@ -60,10 +60,10 @@ ifeq ($(PORTNAME), cygwin)
60
60
SHLIB_LINK += -Wl,--export-all-symbols
61
61
endif
62
62
63
- REGRESS_OPTS = --dbname=$(PL_TESTDB )
63
+ REGRESS_OPTS = --dbname=$(PL_TESTDB ) --dlpath= $( top_builddir ) /src/test/regress
64
64
REGRESS = plperl_setup plperl plperl_lc plperl_trigger plperl_shared \
65
65
plperl_elog plperl_util plperl_init plperlu plperl_array \
66
- plperl_call plperl_transaction
66
+ plperl_call plperl_transaction plperl_env
67
67
# if Perl can support two interpreters in one backend,
68
68
# test plperl-and-plperlu cases
69
69
ifneq ($(PERL ) ,)
Original file line number Diff line number Diff line change
1
+ --
2
+ -- Test the environment setting
3
+ --
4
+ -- directory path and dlsuffix are passed to us in environment variables
5
+ \getenv libdir PG_LIBDIR
6
+ \getenv dlsuffix PG_DLSUFFIX
7
+ \set regresslib :libdir '/regress' :dlsuffix
8
+ CREATE FUNCTION get_environ()
9
+ RETURNS text[]
10
+ AS :'regresslib', 'get_environ'
11
+ LANGUAGE C STRICT;
12
+ -- fetch the process environment
13
+ CREATE FUNCTION process_env () RETURNS text[]
14
+ LANGUAGE plpgsql AS
15
+ $$
16
+
17
+ declare
18
+ res text[];
19
+ tmp text[];
20
+ f record;
21
+ begin
22
+ for f in select unnest(get_environ()) as t loop
23
+ tmp := regexp_split_to_array(f.t, '=');
24
+ if array_length(tmp, 1) = 2 then
25
+ res := res || tmp;
26
+ end if;
27
+ end loop;
28
+ return res;
29
+ end
30
+
31
+ $$;
32
+ -- plperl should not be able to affect the process environment
33
+ DO
34
+ $$
35
+ $ENV{TEST_PLPERL_ENV_FOO} = "shouldfail";
36
+ untie %ENV;
37
+ $ENV{TEST_PLPERL_ENV_FOO} = "testval";
38
+ my $penv = spi_exec_query("select unnest(process_env()) as pe");
39
+ my %received;
40
+ for (my $f = 0; $f < $penv->{processed}; $f += 2)
41
+ {
42
+ my $k = $penv->{rows}[$f]->{pe};
43
+ my $v = $penv->{rows}[$f+1]->{pe};
44
+ $received{$k} = $v;
45
+ }
46
+ unless (exists $received{TEST_PLPERL_ENV_FOO})
47
+ {
48
+ elog(NOTICE, "environ unaffected")
49
+ }
50
+
51
+ $$ LANGUAGE plperl;
52
+ WARNING: attempted alteration of $ENV{TEST_PLPERL_ENV_FOO} at line 12.
53
+ NOTICE: environ unaffected
Original file line number Diff line number Diff line change @@ -94,7 +94,9 @@ tests += {
94
94
' plperl_array' ,
95
95
' plperl_call' ,
96
96
' plperl_transaction' ,
97
+ ' plperl_env' ,
97
98
],
99
+ ' regress_args' : [' --dlpath' , meson .build_root() / ' src/test/regress' ],
98
100
},
99
101
}
100
102
Original file line number Diff line number Diff line change @@ -30,3 +30,27 @@ package PostgreSQL::InServer::safe; ## no critic (RequireFilenameMatchesPackage)
30
30
require Carp::Heavy;
31
31
require warnings;
32
32
require feature if $] >= 5.010000;
33
+
34
+ # <<< protect next line from perltidy so perlcritic annotation works
35
+ package PostgreSQL::InServer::WarnEnv ; # # no critic (RequireFilenameMatchesPackage)
36
+ # >>>
37
+
38
+ use strict;
39
+ use warnings;
40
+ use Tie::Hash;
41
+ our @ISA = qw( Tie::StdHash) ;
42
+
43
+ sub STORE { warn " attempted alteration of \$ ENV{$_ [1]}" ; }
44
+ sub DELETE { warn " attempted deletion of \$ ENV{$_ [1]}" ; }
45
+ sub CLEAR { warn " attempted clearance of ENV hash" ; }
46
+
47
+ # Remove magic property of %ENV. Changes to this will now not be reflected in
48
+ # the process environment.
49
+ *main::ENV = {%ENV };
50
+
51
+ # Block %ENV changes from trusted PL/Perl, and warn. We changed %ENV to just a
52
+ # normal hash, yet the application may be expecting the usual Perl %ENV
53
+ # magic. Blocking and warning avoids silent application breakage. The user can
54
+ # untie or otherwise disable this, e.g. if the lost mutation is unimportant
55
+ # and modifying the code to stop that mutation would be onerous.
56
+ tie %main::ENV , ' PostgreSQL::InServer::WarnEnv' , %ENV or die $! ;
Original file line number Diff line number Diff line change
1
+ --
2
+ -- Test the environment setting
3
+ --
4
+
5
+ -- directory path and dlsuffix are passed to us in environment variables
6
+ \getenv libdir PG_LIBDIR
7
+ \getenv dlsuffix PG_DLSUFFIX
8
+
9
+ \set regresslib :libdir ' /regress' :dlsuffix
10
+
11
+ CREATE FUNCTION get_environ ()
12
+ RETURNS text []
13
+ AS :' regresslib' , ' get_environ'
14
+ LANGUAGE C STRICT;
15
+
16
+ -- fetch the process environment
17
+
18
+ CREATE FUNCTION process_env () RETURNS text []
19
+ LANGUAGE plpgsql AS
20
+ $$
21
+
22
+ declare
23
+ res text [];
24
+ tmp text [];
25
+ f record;
26
+ begin
27
+ for f in select unnest(get_environ()) as t loop
28
+ tmp := regexp_split_to_array(f .t , ' =' );
29
+ if array_length(tmp, 1 ) = 2 then
30
+ res := res || tmp;
31
+ end if;
32
+ end loop;
33
+ return res;
34
+ end
35
+
36
+ $$;
37
+
38
+ -- plperl should not be able to affect the process environment
39
+
40
+ DO
41
+ $$
42
+ $ENV{TEST_PLPERL_ENV_FOO} = " shouldfail" ;
43
+ untie %ENV;
44
+ $ENV{TEST_PLPERL_ENV_FOO} = " testval" ;
45
+ my $penv = spi_exec_query(" select unnest(process_env()) as pe" );
46
+ my %received;
47
+ for (my $f = 0 ; $f < $penv- > {processed}; $f + = 2 )
48
+ {
49
+ my $k = $penv- > {rows}[$f]- > {pe};
50
+ my $v = $penv- > {rows}[$f+ 1 ]- > {pe};
51
+ $received{$k} = $v;
52
+ }
53
+ unless (exists $received{TEST_PLPERL_ENV_FOO})
54
+ {
55
+ elog(NOTICE, " environ unaffected" )
56
+ }
57
+
58
+ $$ LANGUAGE plperl;
Original file line number Diff line number Diff line change @@ -645,6 +645,29 @@ make_tuple_indirect(PG_FUNCTION_ARGS)
645
645
PG_RETURN_POINTER (newtup -> t_data );
646
646
}
647
647
648
+ PG_FUNCTION_INFO_V1 (get_environ );
649
+
650
+ Datum
651
+ get_environ (PG_FUNCTION_ARGS )
652
+ {
653
+ extern char * * environ ;
654
+ int nvals = 0 ;
655
+ ArrayType * result ;
656
+ Datum * env ;
657
+
658
+ for (char * * s = environ ; * s ; s ++ )
659
+ nvals ++ ;
660
+
661
+ env = palloc (nvals * sizeof (Datum ));
662
+
663
+ for (int i = 0 ; i < nvals ; i ++ )
664
+ env [i ] = CStringGetTextDatum (environ [i ]);
665
+
666
+ result = construct_array_builtin (env , nvals , TEXTOID );
667
+
668
+ PG_RETURN_POINTER (result );
669
+ }
670
+
648
671
PG_FUNCTION_INFO_V1 (regress_setenv );
649
672
650
673
Datum
You can’t perform that action at this time.
0 commit comments