1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

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
This commit is contained in:
Tom Lane
2010-09-30 17:18:51 -04:00
parent 1f0eb5de9e
commit 50595b5fce
12 changed files with 921 additions and 397 deletions

View File

@@ -214,14 +214,36 @@ $$ LANGUAGE pltcl;
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 <application>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.
</para>
<para>
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 <quote>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 <literal>SECURITY
DEFINER</> functions, use of <command>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 <literal>SECURITY DEFINER</>. You must of
course take care that such functions can't be used to do anything
unintended.
</para>
<para>
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.
</para>
<para>
To help protect PL/Tcl functions from unintentionally interfering
with each other, a global
@@ -231,7 +253,9 @@ $$ LANGUAGE pltcl;
<literal>GD</> be used
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.
multiple functions. (Note that the <literal>GD</> arrays are only
global within a particular interpreter, so they do not bypass the
security restrictions mentioned above.)
</para>
<para>
@@ -691,8 +715,8 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
exists, the module <literal>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 <xref linkend="pltcl-global">.)
</para>
<para>
While the <literal>unknown</> module could actually contain any