From 14bb84c599016c51d53f7fd66259990c11e2246f Mon Sep 17 00:00:00 2001 From: Yugo Nagata Date: Tue, 14 Feb 2023 02:19:59 +0900 Subject: [PATCH] Fix to use qualified function names during maintenance Previously, functions names in pg_catalog schema that were used during view maintenance were not qualified. This is problematic because functions in other schema could be referenced unintentionally. Moreover, that could result in privilege escalation that if a nefarious user who can create a function, arbitrary functions could be executed under IMMV owner's privilege. CVE-2023-23554 --- createas.c | 12 ++++++------ matview.c | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/createas.c b/createas.c index 937ebc8..5205db9 100644 --- a/createas.c +++ b/createas.c @@ -343,9 +343,9 @@ rewriteQueryForIMMV(Query *query, List *colNames) if (rewritten->distinctClause || rewritten->hasAggs) { #if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 140000) - fn = makeFuncCall(list_make1(makeString("count")), NIL, COERCE_EXPLICIT_CALL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, COERCE_EXPLICIT_CALL, -1); #else - fn = makeFuncCall(list_make1(makeString("count")), NIL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, -1); #endif fn->agg_star = true; @@ -401,9 +401,9 @@ makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname, AttrNumber * if (strcmp(aggname, "count") != 0) { #if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 140000) - fn = makeFuncCall(list_make1(makeString("count")), NIL, COERCE_EXPLICIT_CALL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, COERCE_EXPLICIT_CALL, -1); #else - fn = makeFuncCall(list_make1(makeString("count")), NIL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, -1); #endif /* Make a Func with a dummy arg, and then override this by the original agg's args. */ @@ -437,9 +437,9 @@ makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname, AttrNumber * ReleaseSysCache(type); } #if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 140000) - fn = makeFuncCall(list_make1(makeString("sum")), NIL, COERCE_EXPLICIT_CALL, -1); + fn = makeFuncCall(SystemFuncName("sum"), NIL, COERCE_EXPLICIT_CALL, -1); #else - fn = makeFuncCall(list_make1(makeString("sum")), NIL, -1); + fn = makeFuncCall(SystemFuncName("sum"), NIL, -1); #endif /* Make a Func with dummy args, and then override this by the original agg's args. */ diff --git a/matview.c b/matview.c index 1c99976..313d366 100644 --- a/matview.c +++ b/matview.c @@ -1348,7 +1348,7 @@ get_prestate_rte(RangeTblEntry *rte, MV_TriggerTable *table, initStringInfo(&str); appendStringInfo(&str, "SELECT t.* FROM %s t" - " WHERE ivm_visible_in_prestate(t.tableoid, t.ctid ,%d::oid)", + " WHERE pg_catalog.ivm_visible_in_prestate(t.tableoid, t.ctid ,%d::pg_catalog.oid)", relname, matviewid); for (i = 0; i < list_length(table->old_tuplestores); i++) @@ -1492,9 +1492,9 @@ rewrite_query_for_distinct_and_aggregates(Query *query, ParseState *pstate) /* Add count(*) for counting distinct tuples in views */ #if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 140000) - fn = makeFuncCall(list_make1(makeString("count")), NIL, COERCE_EXPLICIT_CALL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, COERCE_EXPLICIT_CALL, -1); #else - fn = makeFuncCall(list_make1(makeString("count")), NIL, -1); + fn = makeFuncCall(SystemFuncName("count"), NIL, -1); #endif fn->agg_star = true; if (!query->groupClause && !query->hasAggs) @@ -1696,7 +1696,7 @@ apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *n /* avg */ else if (!strcmp(aggname, "avg")) append_set_clause_for_avg(resname, aggs_set_old, aggs_set_new, aggs_list_buf, - format_type_be(aggref->aggtype)); + format_type_be_qualified(aggref->aggtype)); /* min/max */ else if (!strcmp(aggname, "min") || !strcmp(aggname, "max")) @@ -2245,7 +2245,7 @@ apply_old_delta(const char *matviewname, const char *deltaname_old, initStringInfo(&querybuf); appendStringInfo(&querybuf, "DELETE FROM %s WHERE ctid IN (" - "SELECT tid FROM (SELECT row_number() over (partition by %s) AS \"__ivm_row_number__\"," + "SELECT tid FROM (SELECT pg_catalog.row_number() over (partition by %s) AS \"__ivm_row_number__\"," "mv.ctid AS tid," "diff.\"__ivm_count__\"" "FROM %s AS mv, %s AS diff " @@ -2344,7 +2344,7 @@ apply_new_delta(const char *matviewname, const char *deltaname_new, initStringInfo(&querybuf); appendStringInfo(&querybuf, "INSERT INTO %s (%s) SELECT %s FROM (" - "SELECT diff.*, generate_series(1, diff.\"__ivm_count__\") AS __ivm_generate_series__ " + "SELECT diff.*, pg_catalog.generate_series(1, diff.\"__ivm_count__\") AS __ivm_generate_series__ " "FROM %s AS diff) AS v", matviewname, target_list->data, target_list->data, deltaname_new); @@ -2743,7 +2743,7 @@ generate_equal(StringInfo querybuf, Oid opttype, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", - format_type_be(opttype)))); + format_type_be_qualified(opttype)))); generate_operator_clause(querybuf, leftop, opttype,