From b68319c25bb40dd0245cf176273c741fdba064ec Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 30 Sep 2010 17:23:01 -0400 Subject: Use a separate interpreter for each calling SQL userid in plperl and pltcl. There are numerous methods by which a Perl or Tcl function can subvert the behavior of another such function executed later; for example, by redefining standard functions or operators called by the target function. If the target function is SECURITY DEFINER, or is called by such a function, this means that any ordinary SQL user with Perl or Tcl language usage rights can do essentially anything with the privileges of the target function's owner. To close this security hole, create a separate Perl or Tcl interpreter for each SQL userid under which plperl or pltcl functions are executed within a session. However, all plperlu or pltclu functions run within a session still share a single interpreter, since they all execute at the trust level of a database superuser anyway. Note: this change results in a functionality loss when libperl has been built without the "multiplicity" option: it's no longer possible to call plperl functions under different userids in one session, since such a libperl can't support multiple interpreters in one process. However, such a libperl already failed to support concurrent use of plperl and plperlu, so it's likely that few people use such versions with Postgres. Security: CVE-2010-3433 --- doc/src/sgml/installation.sgml | 8 ++++-- doc/src/sgml/plperl.sgml | 57 +++++++++++++++++++++++++++++++----------- doc/src/sgml/pltcl.sgml | 48 ++++++++++++++++++++++++++--------- doc/src/sgml/release-7.4.sgml | 37 +++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 29 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 06324513bf7..de49593776b 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -145,8 +145,12 @@ su - postgres libperl library must be a shared library also on most platforms. This appears to be the default in recent Perl versions, but it was not in earlier versions, and in - general it is the choice of whomever installed Perl at your - site. + any case it is the choice of whomever installed Perl at your site. + If you intend to make more than incidental use of + PL/Perl, you should ensure that the + Perl installation was built with the + usemultiplicity option enabled (perl -V + will show whether this is the case). diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index aa3838698d8..c6516c2b122 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -261,21 +261,31 @@ CREATE FUNCTION badfunc() RETURNS integer AS ' - - For security reasons, to stop a leak of privileged operations from - PL/PerlU to PL/Perl, these two languages - have to run in separate instances of the Perl interpreter. If your - Perl installation has been appropriately compiled, this is not a problem. - However, not all installations are compiled with the requisite flags. - If PostgreSQL detects that this is the case then it will - not start a second interpreter, but instead create an error. In - consequence, in such an installation, you cannot use both - PL/PerlU and PL/Perl in the same backend - process. The remedy for this is to obtain a Perl installation created - with the appropriate flags, namely either usemultiplicity or - both usethreads and useithreads. - For more details,see the perlembed manual page. - + + While PL/Perl functions run in a separate Perl + interpreter for each SQL role, all PL/PerlU functions + executed in a given session run in a single Perl interpreter (which is + not any of the ones used for PL/Perl functions). + This allows PL/PerlU functions to share data freely, + but no communication can occur between PL/Perl and + PL/PerlU functions. + + + + + + Perl cannot support multiple interpreters within one process unless + it was built with the appropriate flags, namely either + usemultiplicity or useithreads. + (usemultiplicity is preferred unless you actually need + to use threads. For more details, see the + perlembed man page.) + If PL/Perl is used with a copy of Perl that was not built + this way, then it is only possible to have one Perl interpreter per + session, and so any one session can only execute either + PL/PerlU functions, or PL/Perl functions + that are all called by the same SQL role. + @@ -313,6 +323,23 @@ CREATE FUNCTION badfunc() RETURNS integer AS ' + + + For security reasons, PL/Perl executes functions called by any one SQL role + in a separate Perl interpreter for that role. This prevents accidental or + malicious interference by one user with the behavior of another user's + PL/Perl functions. Each such interpreter has its own value of the + %_SHARED variable and other global state. Thus, two + PL/Perl functions will share the same value of %_SHARED + if and only if they are executed by the same SQL role. In an application + wherein a single session executes code under multiple SQL roles (via + SECURITY DEFINER functions, use of SET ROLE, etc) + you may need to take explicit steps to ensure that PL/Perl functions can + share data via %_SHARED. To do that, make sure that + functions that should communicate are owned by the same user, and mark + them SECURITY DEFINER. You must of course take care that + such functions can't be used to do anything unintended. + diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml index d72e275ae77..f02e203e903 100644 --- a/doc/src/sgml/pltcl.sgml +++ b/doc/src/sgml/pltcl.sgml @@ -199,14 +199,36 @@ CREATE FUNCTION overpaid(employee) RETURNS boolean AS ' Sometimes it is useful to have some global data that is held between two calls to a function or is shared between different functions. - This is easily done since - all PL/Tcl functions executed in one session share the same - safe Tcl interpreter. So, any global Tcl variable is accessible to - all PL/Tcl function calls and will persist for the duration of the - SQL session. (Note that PL/TclU functions likewise share - global data, but they are in a different Tcl interpreter and cannot - communicate with PL/Tcl functions.) + This is easily done in PL/Tcl, but there are some restrictions that + must be understood. + + + For security reasons, PL/Tcl executes functions called by any one SQL + role in a separate Tcl interpreter for that role. This prevents + accidental or malicious interference by one user with the behavior of + another user's PL/Tcl functions. Each such interpreter will have its own + values for any global Tcl variables. Thus, two PL/Tcl + functions will share the same global variables if and only if they are + executed by the same SQL role. In an application wherein a single + session executes code under multiple SQL roles (via SECURITY + DEFINER functions, use of SET ROLE, etc) you may need to + take explicit steps to ensure that PL/Tcl functions can share data. To + do that, make sure that functions that should communicate are owned by + the same user, and mark them SECURITY DEFINER. You must of + course take care that such functions can't be used to do anything + unintended. + + + + All PL/TclU functions used in a session execute in the same Tcl + interpreter, which of course is distinct from the interpreter(s) + used for PL/Tcl functions. So global data is automatically shared + between PL/TclU functions. This is not considered a security risk + because all PL/TclU functions execute at the same trust level, + namely that of a database superuser. + + To help protect PL/Tcl functions from unintentionally interfering with each other, a global @@ -214,9 +236,11 @@ CREATE FUNCTION overpaid(employee) RETURNS boolean AS ' command. The global name of this variable is the function's internal name, and the local name is GD. It is recommended that GD be used - for private data of a function. Use regular Tcl global variables - only for values that you specifically intend to be shared among multiple - functions. + for persistent private data of a function. Use regular Tcl global + variables only for values that you specifically intend to be shared among + multiple functions. (Note that the GD arrays are only + global within a particular interpreter, so they do not bypass the + security restrictions mentioned above.) @@ -648,8 +672,8 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab exists, the module unknown is fetched from the table and loaded into the Tcl interpreter immediately before the first execution of a PL/Tcl function in a database session. (This - happens separately for PL/Tcl and PL/TclU, if both are used, - because separate interpreters are used for the two languages.) + happens separately for each Tcl interpreter, if more than one is + used in a session; see .) While the unknown module could actually contain any diff --git a/doc/src/sgml/release-7.4.sgml b/doc/src/sgml/release-7.4.sgml index 2c52be70064..226275bf320 100644 --- a/doc/src/sgml/release-7.4.sgml +++ b/doc/src/sgml/release-7.4.sgml @@ -37,6 +37,43 @@ + + + Use a separate interpreter for each calling SQL userid in PL/Perl and + PL/Tcl (Tom Lane) + + + + This change prevents security problems that can be caused by subverting + Perl or Tcl code that will be executed later in the same session under + another SQL user identity (for example, within a SECURITY + DEFINER function). Most scripting languages offer numerous ways that + that might be done, such as redefining standard functions or operators + called by the target function. Without this change, any SQL user with + Perl or Tcl language usage rights can do essentially anything with the + SQL privileges of the target function's owner. + + + + The cost of this change is that intentional communication among Perl + and Tcl functions becomes more difficult. To provide an escape hatch, + PL/PerlU and PL/TclU functions continue to use only one interpreter + per session. This is not considered a security issue since all such + functions execute at the trust level of a database superuser already. + + + + It is likely that third-party procedural languages that claim to offer + trusted execution have similar security issues. We advise contacting + the authors of any PL you are depending on for security-critical + purposes. + + + + Our thanks to Tim Bunce for pointing out this issue (CVE-2010-3433). + + + Prevent possible crashes in pg_get_expr() by disallowing -- cgit v1.2.3