summaryrefslogtreecommitdiffstats
path: root/src/backend/catalog
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog')
-rw-r--r--src/backend/catalog/Makefile3
-rw-r--r--src/backend/catalog/dependency.c13
-rw-r--r--src/backend/catalog/fix-CVE-2024-4317.sql117
-rw-r--r--src/backend/catalog/heap.c3
-rw-r--r--src/backend/catalog/pg_proc.c7
-rw-r--r--src/backend/catalog/system_views.sql11
6 files changed, 142 insertions, 12 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 89a0221..7304e2b 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -130,13 +130,14 @@ install-data: bki-stamp installdirs
$(INSTALL_DATA) $(srcdir)/system_views.sql '$(DESTDIR)$(datadir)/system_views.sql'
$(INSTALL_DATA) $(srcdir)/information_schema.sql '$(DESTDIR)$(datadir)/information_schema.sql'
$(INSTALL_DATA) $(srcdir)/sql_features.txt '$(DESTDIR)$(datadir)/sql_features.txt'
+ $(INSTALL_DATA) $(srcdir)/fix-CVE-2024-4317.sql '$(DESTDIR)$(datadir)/fix-CVE-2024-4317.sql'
installdirs:
$(MKDIR_P) '$(DESTDIR)$(datadir)'
.PHONY: uninstall-data
uninstall-data:
- rm -f $(addprefix '$(DESTDIR)$(datadir)'/, postgres.bki system_constraints.sql system_functions.sql system_views.sql information_schema.sql sql_features.txt)
+ rm -f $(addprefix '$(DESTDIR)$(datadir)'/, postgres.bki system_constraints.sql system_functions.sql system_views.sql information_schema.sql sql_features.txt fix-CVE-2024-4317.sql)
# postgres.bki, system_constraints.sql, and the generated headers are
# in the distribution tarball, so they are not cleaned here.
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 85e2a90..3cca107 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -75,6 +75,7 @@
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "funcapi.h"
+#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteRemove.h"
@@ -517,6 +518,12 @@ findDependentObjects(const ObjectAddress *object,
return;
/*
+ * since this function recurses, it could be driven to stack overflow,
+ * because of the deep dependency tree, not only due to dependency loops.
+ */
+ check_stack_depth();
+
+ /*
* It's also possible that the target object has already been completely
* processed and put into targetObjects. If so, again we just add the
* specified objflags to its entry and return.
@@ -2378,7 +2385,11 @@ process_function_rte_ref(RangeTblEntry *rte, AttrNumber attnum,
{
TupleDesc tupdesc;
- tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr, true);
+ /* If it has a coldeflist, it certainly returns RECORD */
+ if (rtfunc->funccolnames != NIL)
+ tupdesc = NULL; /* no need to work hard */
+ else
+ tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr, true);
if (tupdesc && tupdesc->tdtypeid != RECORDOID)
{
/*
diff --git a/src/backend/catalog/fix-CVE-2024-4317.sql b/src/backend/catalog/fix-CVE-2024-4317.sql
new file mode 100644
index 0000000..b24eba9
--- /dev/null
+++ b/src/backend/catalog/fix-CVE-2024-4317.sql
@@ -0,0 +1,117 @@
+/*
+ * fix-CVE-2024-4317.sql
+ *
+ * Copyright (c) 2024, PostgreSQL Global Development Group
+ *
+ * src/backend/catalog/fix-CVE-2024-4317.sql
+ *
+ * This file should be run in every database in the cluster to address
+ * CVE-2024-4317.
+ */
+
+SET search_path = pg_catalog;
+
+CREATE OR REPLACE VIEW pg_stats_ext WITH (security_barrier) AS
+ SELECT cn.nspname AS schemaname,
+ c.relname AS tablename,
+ sn.nspname AS statistics_schemaname,
+ s.stxname AS statistics_name,
+ pg_get_userbyid(s.stxowner) AS statistics_owner,
+ ( SELECT array_agg(a.attname ORDER BY a.attnum)
+ FROM unnest(s.stxkeys) k
+ JOIN pg_attribute a
+ ON (a.attrelid = s.stxrelid AND a.attnum = k)
+ ) AS attnames,
+ pg_get_statisticsobjdef_expressions(s.oid) as exprs,
+ s.stxkind AS kinds,
+ sd.stxdinherit AS inherited,
+ sd.stxdndistinct AS n_distinct,
+ sd.stxddependencies AS dependencies,
+ m.most_common_vals,
+ m.most_common_val_nulls,
+ m.most_common_freqs,
+ m.most_common_base_freqs
+ FROM pg_statistic_ext s JOIN pg_class c ON (c.oid = s.stxrelid)
+ JOIN pg_statistic_ext_data sd ON (s.oid = sd.stxoid)
+ LEFT JOIN pg_namespace cn ON (cn.oid = c.relnamespace)
+ LEFT JOIN pg_namespace sn ON (sn.oid = s.stxnamespace)
+ LEFT JOIN LATERAL
+ ( SELECT array_agg(values) AS most_common_vals,
+ array_agg(nulls) AS most_common_val_nulls,
+ array_agg(frequency) AS most_common_freqs,
+ array_agg(base_frequency) AS most_common_base_freqs
+ FROM pg_mcv_list_items(sd.stxdmcv)
+ ) m ON sd.stxdmcv IS NOT NULL
+ WHERE pg_has_role(c.relowner, 'USAGE')
+ AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
+
+CREATE OR REPLACE VIEW pg_stats_ext_exprs WITH (security_barrier) AS
+ SELECT cn.nspname AS schemaname,
+ c.relname AS tablename,
+ sn.nspname AS statistics_schemaname,
+ s.stxname AS statistics_name,
+ pg_get_userbyid(s.stxowner) AS statistics_owner,
+ stat.expr,
+ sd.stxdinherit AS inherited,
+ (stat.a).stanullfrac AS null_frac,
+ (stat.a).stawidth AS avg_width,
+ (stat.a).stadistinct AS n_distinct,
+ (CASE
+ WHEN (stat.a).stakind1 = 1 THEN (stat.a).stavalues1
+ WHEN (stat.a).stakind2 = 1 THEN (stat.a).stavalues2
+ WHEN (stat.a).stakind3 = 1 THEN (stat.a).stavalues3
+ WHEN (stat.a).stakind4 = 1 THEN (stat.a).stavalues4
+ WHEN (stat.a).stakind5 = 1 THEN (stat.a).stavalues5
+ END) AS most_common_vals,
+ (CASE
+ WHEN (stat.a).stakind1 = 1 THEN (stat.a).stanumbers1
+ WHEN (stat.a).stakind2 = 1 THEN (stat.a).stanumbers2
+ WHEN (stat.a).stakind3 = 1 THEN (stat.a).stanumbers3
+ WHEN (stat.a).stakind4 = 1 THEN (stat.a).stanumbers4
+ WHEN (stat.a).stakind5 = 1 THEN (stat.a).stanumbers5
+ END) AS most_common_freqs,
+ (CASE
+ WHEN (stat.a).stakind1 = 2 THEN (stat.a).stavalues1
+ WHEN (stat.a).stakind2 = 2 THEN (stat.a).stavalues2
+ WHEN (stat.a).stakind3 = 2 THEN (stat.a).stavalues3
+ WHEN (stat.a).stakind4 = 2 THEN (stat.a).stavalues4
+ WHEN (stat.a).stakind5 = 2 THEN (stat.a).stavalues5
+ END) AS histogram_bounds,
+ (CASE
+ WHEN (stat.a).stakind1 = 3 THEN (stat.a).stanumbers1[1]
+ WHEN (stat.a).stakind2 = 3 THEN (stat.a).stanumbers2[1]
+ WHEN (stat.a).stakind3 = 3 THEN (stat.a).stanumbers3[1]
+ WHEN (stat.a).stakind4 = 3 THEN (stat.a).stanumbers4[1]
+ WHEN (stat.a).stakind5 = 3 THEN (stat.a).stanumbers5[1]
+ END) correlation,
+ (CASE
+ WHEN (stat.a).stakind1 = 4 THEN (stat.a).stavalues1
+ WHEN (stat.a).stakind2 = 4 THEN (stat.a).stavalues2
+ WHEN (stat.a).stakind3 = 4 THEN (stat.a).stavalues3
+ WHEN (stat.a).stakind4 = 4 THEN (stat.a).stavalues4
+ WHEN (stat.a).stakind5 = 4 THEN (stat.a).stavalues5
+ END) AS most_common_elems,
+ (CASE
+ WHEN (stat.a).stakind1 = 4 THEN (stat.a).stanumbers1
+ WHEN (stat.a).stakind2 = 4 THEN (stat.a).stanumbers2
+ WHEN (stat.a).stakind3 = 4 THEN (stat.a).stanumbers3
+ WHEN (stat.a).stakind4 = 4 THEN (stat.a).stanumbers4
+ WHEN (stat.a).stakind5 = 4 THEN (stat.a).stanumbers5
+ END) AS most_common_elem_freqs,
+ (CASE
+ WHEN (stat.a).stakind1 = 5 THEN (stat.a).stanumbers1
+ WHEN (stat.a).stakind2 = 5 THEN (stat.a).stanumbers2
+ WHEN (stat.a).stakind3 = 5 THEN (stat.a).stanumbers3
+ WHEN (stat.a).stakind4 = 5 THEN (stat.a).stanumbers4
+ WHEN (stat.a).stakind5 = 5 THEN (stat.a).stanumbers5
+ END) AS elem_count_histogram
+ FROM pg_statistic_ext s JOIN pg_class c ON (c.oid = s.stxrelid)
+ LEFT JOIN pg_statistic_ext_data sd ON (s.oid = sd.stxoid)
+ LEFT JOIN pg_namespace cn ON (cn.oid = c.relnamespace)
+ LEFT JOIN pg_namespace sn ON (sn.oid = s.stxnamespace)
+ JOIN LATERAL (
+ SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr,
+ unnest(sd.stxdexpr)::pg_statistic AS a
+ ) stat ON (stat.expr IS NOT NULL)
+ WHERE pg_has_role(c.relowner, 'USAGE')
+ AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bd6b9c4..9197909 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -552,6 +552,9 @@ CheckAttributeType(const char *attname,
char att_typtype = get_typtype(atttypid);
Oid att_typelem;
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
if (att_typtype == TYPTYPE_PSEUDO)
{
/*
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 7514015..5fd8a38 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -972,9 +972,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
(void) get_func_result_type(funcoid, &rettype, &rettupdesc);
- (void) check_sql_fn_retval(querytree_list,
- rettype, rettupdesc,
- false, NULL);
+ (void) check_sql_fn_retval_ext(querytree_list,
+ rettype, rettupdesc,
+ proc->prokind,
+ false, NULL);
}
error_context_stack = sqlerrcontext.previous;
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 76e4177..ffa8632 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -284,12 +284,7 @@ CREATE VIEW pg_stats_ext WITH (security_barrier) AS
array_agg(base_frequency) AS most_common_base_freqs
FROM pg_mcv_list_items(sd.stxdmcv)
) m ON sd.stxdmcv IS NOT NULL
- WHERE NOT EXISTS
- ( SELECT 1
- FROM unnest(stxkeys) k
- JOIN pg_attribute a
- ON (a.attrelid = s.stxrelid AND a.attnum = k)
- WHERE NOT has_column_privilege(c.oid, a.attnum, 'select') )
+ WHERE pg_has_role(c.relowner, 'USAGE')
AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
CREATE VIEW pg_stats_ext_exprs WITH (security_barrier) AS
@@ -359,7 +354,9 @@ CREATE VIEW pg_stats_ext_exprs WITH (security_barrier) AS
JOIN LATERAL (
SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr,
unnest(sd.stxdexpr)::pg_statistic AS a
- ) stat ON (stat.expr IS NOT NULL);
+ ) stat ON (stat.expr IS NOT NULL)
+ WHERE pg_has_role(c.relowner, 'USAGE')
+ AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
-- unprivileged users may read pg_statistic_ext but not pg_statistic_ext_data
REVOKE ALL ON pg_statistic_ext_data FROM public;