1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-29 10:41:53 +03:00

Improved version of patch to protect pg_get_expr() against misuse:

look through join alias Vars to avoid breaking join queries, and
move the test to someplace where it will catch more possible ways
of calling a function.  We still ought to throw away the whole thing
in favor of a data-type-based solution, but that's not feasible in
the back branches.

Completion of back-port of my patch of yesterday.
This commit is contained in:
Tom Lane
2010-07-30 17:56:59 +00:00
parent b08fd11508
commit 6b8494a3ad
4 changed files with 124 additions and 90 deletions

View File

@ -8,16 +8,13 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.241.2.5 2010/06/30 18:10:37 heikki Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.241.2.6 2010/07/30 17:56:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
@ -33,7 +30,6 @@
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/xml.h"
@ -1103,7 +1099,6 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
{
List *targs;
ListCell *args;
Node *result;
/* Transform the list of arguments ... */
targs = NIL;
@ -1114,7 +1109,7 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
}
/* ... and hand off to ParseFuncOrColumn */
result = ParseFuncOrColumn(pstate,
return ParseFuncOrColumn(pstate,
fn->funcname,
targs,
fn->agg_star,
@ -1123,86 +1118,6 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
fn->over,
false,
fn->location);
/*
* pg_get_expr() is a system function that exposes the expression
* deparsing functionality in ruleutils.c to users. Very handy, but
* it was later realized that the functions in ruleutils.c don't check
* the input rigorously, assuming it to come from system catalogs and
* to therefore be valid. That makes it easy for a user to crash the
* backend by passing a maliciously crafted string representation of
* an expression to pg_get_expr().
*
* There's a lot of code in ruleutils.c, so it's not feasible to add
* water-proof input checking after the fact. Even if we did it once,
* it would need to be taken into account in any future patches too.
*
* Instead, we restrict pg_rule_expr() to only allow input from system
* catalogs instead. This is a hack, but it's the most robust and easiest
* to backpatch way of plugging the vulnerability.
*
* This is transparent to the typical usage pattern of
* "pg_get_expr(systemcolumn, ...)", but will break
* "pg_get_expr('foo', ...)", even if 'foo' is a valid expression fetched
* earlier from a system catalog. Hopefully there's isn't many clients
* doing that out there.
*/
if (result && IsA(result, FuncExpr) && !superuser())
{
FuncExpr *fe = (FuncExpr *) result;
if (fe->funcid == F_PG_GET_EXPR || fe->funcid == F_PG_GET_EXPR_EXT)
{
Expr *arg = linitial(fe->args);
bool allowed = false;
/*
* Check that the argument came directly from one of the
* allowed system catalog columns
*/
if (IsA(arg, Var))
{
Var *var = (Var *) arg;
RangeTblEntry *rte;
rte = GetRTEByRangeTablePosn(pstate,
var->varno, var->varlevelsup);
switch(rte->relid)
{
case IndexRelationId:
if (var->varattno == Anum_pg_index_indexprs ||
var->varattno == Anum_pg_index_indpred)
allowed = true;
break;
case AttrDefaultRelationId:
if (var->varattno == Anum_pg_attrdef_adbin)
allowed = true;
break;
case ProcedureRelationId:
if (var->varattno == Anum_pg_proc_proargdefaults)
allowed = true;
break;
case ConstraintRelationId:
if (var->varattno == Anum_pg_constraint_conbin)
allowed = true;
break;
case TypeRelationId:
if (var->varattno == Anum_pg_type_typdefaultbin)
allowed = true;
break;
}
}
if (!allowed)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("argument to pg_get_expr() must come from system catalogs")));
}
}
return result;
}
static Node *