*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.163.2.4 2005/11/18 23:08:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.163.2.5 2010/06/30 18:11:43 heikki Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "catalog/catname.h"
+#include "catalog/pg_attrdef.h"
+#include "catalog/pg_constraint.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "commands/dbcommands.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_type.h"
+#include "parser/parsetree.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
fn->agg_star,
fn->agg_distinct,
false);
+
+ /*
+ * 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 = lfirst(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;
+ Index levelsup;
+
+ levelsup = var->varlevelsup;
+ while (levelsup-- > 0)
+ {
+ pstate = pstate->parentParseState;
+ Assert(pstate != NULL);
+ }
+ Assert(var->varno > 0 &&
+ (int) var->varno <= length(pstate->p_rtable));
+ rte = rt_fetch(var->varno, pstate->p_rtable);
+
+ if (rte->relid == get_system_catalog_relid(IndexRelationName))
+ {
+ if (var->varattno == Anum_pg_index_indexprs ||
+ var->varattno == Anum_pg_index_indpred)
+ allowed = true;
+ }
+ else if (rte->relid == get_system_catalog_relid(AttrDefaultRelationName))
+ {
+ if (var->varattno == Anum_pg_attrdef_adbin)
+ allowed = true;
+ }
+ else if (rte->relid == get_system_catalog_relid(ConstraintRelationName))
+ {
+ if (var->varattno == Anum_pg_constraint_conbin)
+ allowed = true;
+ }
+ else if (rte->relid == get_system_catalog_relid(TypeRelationName))
+ {
+ if (var->varattno == Anum_pg_type_typdefaultbin)
+ allowed = true;
+ }
+ }
+ if (!allowed)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("argument to pg_get_expr() must come from system catalogs")));
+ }
+ }
break;
}
case T_SubLink:
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.69 2003/09/25 06:58:02 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.69.2.1 2010/06/30 18:11:43 heikki Exp $
*
* NOTES
* This cruft is the server side of PQfn.
#include "mb/pg_wchar.h"
#include "tcop/fastpath.h"
#include "utils/acl.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
*/
SetQuerySnapshot();
+ /*
+ * Restrict access to pg_get_expr(). This reflects the hack in
+ * transformExpr() in parse_expr.c, see comments there on FuncCall for an
+ * explanation.
+ */
+ if ((fid == F_PG_GET_EXPR || fid == F_PG_GET_EXPR_EXT) && !superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("argument to pg_get_expr() must come from system catalogs")));
+
/*
* Prepare function call info block and insert arguments.
*/