summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Joslyn <robert.joslyn@redrectangle.org>2023-08-20 18:18:30 -0700
committerArmin Kuster <akuster808@gmail.com>2023-09-04 09:05:03 -0400
commitd96f8c485326e3bf4420d28aeab4c4fae8a48906 (patch)
tree2e22795c36713a3ada15802580467dd44e37553e
parent1ff41cb9c6c49373e7a5598e2e444af68428ca46 (diff)
downloadmeta-openembedded-d96f8c485326e3bf4420d28aeab4c4fae8a48906.tar.gz
postgresql: Update to 12.16
This is a minor release to address CVEs and other bug fixes without new features. Remove patches that are fixed in this release. Release notes are available at: https://www.postgresql.org/docs/release/12.10/ https://www.postgresql.org/docs/release/12.11/ https://www.postgresql.org/docs/release/12.12/ https://www.postgresql.org/docs/release/12.13/ https://www.postgresql.org/docs/release/12.14/ https://www.postgresql.org/docs/release/12.15/ https://www.postgresql.org/docs/release/12.16/ License-Update: Copyright year updated Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2022-1552.patch947
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch904
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2022-41862.patch48
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2023-2454.patch235
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2023-2455.patch118
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/remove_duplicate.patch38
-rw-r--r--meta-oe/recipes-dbs/postgresql/postgresql_12.16.bb11
-rw-r--r--meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb17
8 files changed, 11 insertions, 2307 deletions
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-1552.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2022-1552.patch
deleted file mode 100644
index 6f0d5ac06..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-1552.patch
+++ /dev/null
@@ -1,947 +0,0 @@
1From 31eefa1efc8eecb6ab91c8835d2952d44a3b1ae1 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 22 Sep 2022 11:20:41 +0530
4Subject: [PATCH] CVE-2022-1552
5
6Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=ab49ce7c3414ac19e4afb386d7843ce2d2fb8bda && https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=677a494789062ca88e0142a17bedd5415f6ab0aa]
7
8CVE: CVE-2022-1552
9Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
10---
11 contrib/amcheck/expected/check_btree.out | 23 ++++++
12 contrib/amcheck/sql/check_btree.sql | 21 +++++
13 contrib/amcheck/verify_nbtree.c | 27 +++++++
14 src/backend/access/brin/brin.c | 29 ++++++-
15 src/backend/catalog/index.c | 65 ++++++++++++----
16 src/backend/commands/cluster.c | 37 ++++++---
17 src/backend/commands/indexcmds.c | 98 ++++++++++++++++++++----
18 src/backend/commands/matview.c | 30 +++-----
19 src/backend/utils/init/miscinit.c | 24 +++---
20 src/test/regress/expected/privileges.out | 71 +++++++++++++++++
21 src/test/regress/sql/privileges.sql | 64 ++++++++++++++++
22 11 files changed, 422 insertions(+), 67 deletions(-)
23
24diff --git a/contrib/amcheck/expected/check_btree.out b/contrib/amcheck/expected/check_btree.out
25index 59a805d..0fd6ea0 100644
26--- a/contrib/amcheck/expected/check_btree.out
27+++ b/contrib/amcheck/expected/check_btree.out
28@@ -168,11 +168,34 @@ SELECT bt_index_check('toasty', true);
29
30 (1 row)
31
32+--
33+-- Check that index expressions and predicates are run as the table's owner
34+--
35+TRUNCATE bttest_a;
36+INSERT INTO bttest_a SELECT * FROM generate_series(1, 1000);
37+ALTER TABLE bttest_a OWNER TO regress_bttest_role;
38+-- A dummy index function checking current_user
39+CREATE FUNCTION ifun(int8) RETURNS int8 AS $$
40+BEGIN
41+ ASSERT current_user = 'regress_bttest_role',
42+ format('ifun(%s) called by %s', $1, current_user);
43+ RETURN $1;
44+END;
45+$$ LANGUAGE plpgsql IMMUTABLE;
46+CREATE INDEX bttest_a_expr_idx ON bttest_a ((ifun(id) + ifun(0)))
47+ WHERE ifun(id + 10) > ifun(10);
48+SELECT bt_index_check('bttest_a_expr_idx', true);
49+ bt_index_check
50+----------------
51+
52+(1 row)
53+
54 -- cleanup
55 DROP TABLE bttest_a;
56 DROP TABLE bttest_b;
57 DROP TABLE bttest_multi;
58 DROP TABLE delete_test_table;
59 DROP TABLE toast_bug;
60+DROP FUNCTION ifun(int8);
61 DROP OWNED BY regress_bttest_role; -- permissions
62 DROP ROLE regress_bttest_role;
63diff --git a/contrib/amcheck/sql/check_btree.sql b/contrib/amcheck/sql/check_btree.sql
64index 99acbc8..3248187 100644
65--- a/contrib/amcheck/sql/check_btree.sql
66+++ b/contrib/amcheck/sql/check_btree.sql
67@@ -110,11 +110,32 @@ INSERT INTO toast_bug SELECT repeat('a', 2200);
68 -- Should not get false positive report of corruption:
69 SELECT bt_index_check('toasty', true);
70
71+--
72+-- Check that index expressions and predicates are run as the table's owner
73+--
74+TRUNCATE bttest_a;
75+INSERT INTO bttest_a SELECT * FROM generate_series(1, 1000);
76+ALTER TABLE bttest_a OWNER TO regress_bttest_role;
77+-- A dummy index function checking current_user
78+CREATE FUNCTION ifun(int8) RETURNS int8 AS $$
79+BEGIN
80+ ASSERT current_user = 'regress_bttest_role',
81+ format('ifun(%s) called by %s', $1, current_user);
82+ RETURN $1;
83+END;
84+$$ LANGUAGE plpgsql IMMUTABLE;
85+
86+CREATE INDEX bttest_a_expr_idx ON bttest_a ((ifun(id) + ifun(0)))
87+ WHERE ifun(id + 10) > ifun(10);
88+
89+SELECT bt_index_check('bttest_a_expr_idx', true);
90+
91 -- cleanup
92 DROP TABLE bttest_a;
93 DROP TABLE bttest_b;
94 DROP TABLE bttest_multi;
95 DROP TABLE delete_test_table;
96 DROP TABLE toast_bug;
97+DROP FUNCTION ifun(int8);
98 DROP OWNED BY regress_bttest_role; -- permissions
99 DROP ROLE regress_bttest_role;
100diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
101index 700a02f..cb6475d 100644
102--- a/contrib/amcheck/verify_nbtree.c
103+++ b/contrib/amcheck/verify_nbtree.c
104@@ -228,6 +228,9 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
105 Relation indrel;
106 Relation heaprel;
107 LOCKMODE lockmode;
108+ Oid save_userid;
109+ int save_sec_context;
110+ int save_nestlevel;
111
112 if (parentcheck)
113 lockmode = ShareLock;
114@@ -244,9 +247,27 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
115 */
116 heapid = IndexGetRelation(indrelid, true);
117 if (OidIsValid(heapid))
118+ {
119 heaprel = table_open(heapid, lockmode);
120+
121+ /*
122+ * Switch to the table owner's userid, so that any index functions are
123+ * run as that user. Also lock down security-restricted operations
124+ * and arrange to make GUC variable changes local to this command.
125+ */
126+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
127+ SetUserIdAndSecContext(heaprel->rd_rel->relowner,
128+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
129+ save_nestlevel = NewGUCNestLevel();
130+ }
131 else
132+ {
133 heaprel = NULL;
134+ /* for "gcc -Og" https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78394 */
135+ save_userid = InvalidOid;
136+ save_sec_context = -1;
137+ save_nestlevel = -1;
138+ }
139
140 /*
141 * Open the target index relations separately (like relation_openrv(), but
142@@ -293,6 +314,12 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
143 heapallindexed, rootdescend);
144 }
145
146+ /* Roll back any GUC changes executed by index functions */
147+ AtEOXact_GUC(false, save_nestlevel);
148+
149+ /* Restore userid and security context */
150+ SetUserIdAndSecContext(save_userid, save_sec_context);
151+
152 /*
153 * Release locks early. That's ok here because nothing in the called
154 * routines will trigger shared cache invalidations to be sent, so we can
155diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
156index c7b403b..781cac2 100644
157--- a/src/backend/access/brin/brin.c
158+++ b/src/backend/access/brin/brin.c
159@@ -873,6 +873,9 @@ brin_summarize_range(PG_FUNCTION_ARGS)
160 Oid heapoid;
161 Relation indexRel;
162 Relation heapRel;
163+ Oid save_userid;
164+ int save_sec_context;
165+ int save_nestlevel;
166 double numSummarized = 0;
167
168 if (RecoveryInProgress())
169@@ -899,7 +902,22 @@ brin_summarize_range(PG_FUNCTION_ARGS)
170 */
171 heapoid = IndexGetRelation(indexoid, true);
172 if (OidIsValid(heapoid))
173+ {
174 heapRel = table_open(heapoid, ShareUpdateExclusiveLock);
175+
176+ /*
177+ * Autovacuum calls us. For its benefit, switch to the table owner's
178+ * userid, so that any index functions are run as that user. Also
179+ * lock down security-restricted operations and arrange to make GUC
180+ * variable changes local to this command. This is harmless, albeit
181+ * unnecessary, when called from SQL, because we fail shortly if the
182+ * user does not own the index.
183+ */
184+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
185+ SetUserIdAndSecContext(heapRel->rd_rel->relowner,
186+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
187+ save_nestlevel = NewGUCNestLevel();
188+ }
189 else
190 heapRel = NULL;
191
192@@ -914,7 +932,7 @@ brin_summarize_range(PG_FUNCTION_ARGS)
193 RelationGetRelationName(indexRel))));
194
195 /* User must own the index (comparable to privileges needed for VACUUM) */
196- if (!pg_class_ownercheck(indexoid, GetUserId()))
197+ if (heapRel != NULL && !pg_class_ownercheck(indexoid, save_userid))
198 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX,
199 RelationGetRelationName(indexRel));
200
201@@ -932,6 +950,12 @@ brin_summarize_range(PG_FUNCTION_ARGS)
202 /* OK, do it */
203 brinsummarize(indexRel, heapRel, heapBlk, true, &numSummarized, NULL);
204
205+ /* Roll back any GUC changes executed by index functions */
206+ AtEOXact_GUC(false, save_nestlevel);
207+
208+ /* Restore userid and security context */
209+ SetUserIdAndSecContext(save_userid, save_sec_context);
210+
211 relation_close(indexRel, ShareUpdateExclusiveLock);
212 relation_close(heapRel, ShareUpdateExclusiveLock);
213
214@@ -973,6 +997,9 @@ brin_desummarize_range(PG_FUNCTION_ARGS)
215 * passed indexoid isn't an index then IndexGetRelation() will fail.
216 * Rather than emitting a not-very-helpful error message, postpone
217 * complaining, expecting that the is-it-an-index test below will fail.
218+ *
219+ * Unlike brin_summarize_range(), autovacuum never calls this. Hence, we
220+ * don't switch userid.
221 */
222 heapoid = IndexGetRelation(indexoid, true);
223 if (OidIsValid(heapoid))
224diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
225index 3ece136..0333bfd 100644
226--- a/src/backend/catalog/index.c
227+++ b/src/backend/catalog/index.c
228@@ -1400,6 +1400,9 @@ index_concurrently_build(Oid heapRelationId,
229 Oid indexRelationId)
230 {
231 Relation heapRel;
232+ Oid save_userid;
233+ int save_sec_context;
234+ int save_nestlevel;
235 Relation indexRelation;
236 IndexInfo *indexInfo;
237
238@@ -1409,7 +1412,16 @@ index_concurrently_build(Oid heapRelationId,
239 /* Open and lock the parent heap relation */
240 heapRel = table_open(heapRelationId, ShareUpdateExclusiveLock);
241
242- /* And the target index relation */
243+ /*
244+ * Switch to the table owner's userid, so that any index functions are run
245+ * as that user. Also lock down security-restricted operations and
246+ * arrange to make GUC variable changes local to this command.
247+ */
248+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
249+ SetUserIdAndSecContext(heapRel->rd_rel->relowner,
250+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
251+ save_nestlevel = NewGUCNestLevel();
252+
253 indexRelation = index_open(indexRelationId, RowExclusiveLock);
254
255 /*
256@@ -1425,6 +1437,12 @@ index_concurrently_build(Oid heapRelationId,
257 /* Now build the index */
258 index_build(heapRel, indexRelation, indexInfo, false, true);
259
260+ /* Roll back any GUC changes executed by index functions */
261+ AtEOXact_GUC(false, save_nestlevel);
262+
263+ /* Restore userid and security context */
264+ SetUserIdAndSecContext(save_userid, save_sec_context);
265+
266 /* Close both the relations, but keep the locks */
267 table_close(heapRel, NoLock);
268 index_close(indexRelation, NoLock);
269@@ -3271,7 +3289,17 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
270
271 /* Open and lock the parent heap relation */
272 heapRelation = table_open(heapId, ShareUpdateExclusiveLock);
273- /* And the target index relation */
274+
275+ /*
276+ * Switch to the table owner's userid, so that any index functions are run
277+ * as that user. Also lock down security-restricted operations and
278+ * arrange to make GUC variable changes local to this command.
279+ */
280+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
281+ SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
282+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
283+ save_nestlevel = NewGUCNestLevel();
284+
285 indexRelation = index_open(indexId, RowExclusiveLock);
286
287 /*
288@@ -3284,16 +3312,6 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
289 /* mark build is concurrent just for consistency */
290 indexInfo->ii_Concurrent = true;
291
292- /*
293- * Switch to the table owner's userid, so that any index functions are run
294- * as that user. Also lock down security-restricted operations and
295- * arrange to make GUC variable changes local to this command.
296- */
297- GetUserIdAndSecContext(&save_userid, &save_sec_context);
298- SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
299- save_sec_context | SECURITY_RESTRICTED_OPERATION);
300- save_nestlevel = NewGUCNestLevel();
301-
302 /*
303 * Scan the index and gather up all the TIDs into a tuplesort object.
304 */
305@@ -3497,6 +3515,9 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
306 Relation iRel,
307 heapRelation;
308 Oid heapId;
309+ Oid save_userid;
310+ int save_sec_context;
311+ int save_nestlevel;
312 IndexInfo *indexInfo;
313 volatile bool skipped_constraint = false;
314 PGRUsage ru0;
315@@ -3527,6 +3548,16 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
316 */
317 iRel = index_open(indexId, AccessExclusiveLock);
318
319+ /*
320+ * Switch to the table owner's userid, so that any index functions are run
321+ * as that user. Also lock down security-restricted operations and
322+ * arrange to make GUC variable changes local to this command.
323+ */
324+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
325+ SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
326+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
327+ save_nestlevel = NewGUCNestLevel();
328+
329 if (progress)
330 pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID,
331 iRel->rd_rel->relam);
332@@ -3684,12 +3715,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
333 errdetail_internal("%s",
334 pg_rusage_show(&ru0))));
335
336- if (progress)
337- pgstat_progress_end_command();
338+ /* Roll back any GUC changes executed by index functions */
339+ AtEOXact_GUC(false, save_nestlevel);
340+
341+ /* Restore userid and security context */
342+ SetUserIdAndSecContext(save_userid, save_sec_context);
343
344 /* Close rels, but keep locks */
345 index_close(iRel, NoLock);
346 table_close(heapRelation, NoLock);
347+
348+ if (progress)
349+ pgstat_progress_end_command();
350 }
351
352 /*
353diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
354index bd6f408..74db03e 100644
355--- a/src/backend/commands/cluster.c
356+++ b/src/backend/commands/cluster.c
357@@ -266,6 +266,9 @@ void
358 cluster_rel(Oid tableOid, Oid indexOid, int options)
359 {
360 Relation OldHeap;
361+ Oid save_userid;
362+ int save_sec_context;
363+ int save_nestlevel;
364 bool verbose = ((options & CLUOPT_VERBOSE) != 0);
365 bool recheck = ((options & CLUOPT_RECHECK) != 0);
366
367@@ -295,6 +298,16 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
368 return;
369 }
370
371+ /*
372+ * Switch to the table owner's userid, so that any index functions are run
373+ * as that user. Also lock down security-restricted operations and
374+ * arrange to make GUC variable changes local to this command.
375+ */
376+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
377+ SetUserIdAndSecContext(OldHeap->rd_rel->relowner,
378+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
379+ save_nestlevel = NewGUCNestLevel();
380+
381 /*
382 * Since we may open a new transaction for each relation, we have to check
383 * that the relation still is what we think it is.
384@@ -309,11 +322,10 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
385 Form_pg_index indexForm;
386
387 /* Check that the user still owns the relation */
388- if (!pg_class_ownercheck(tableOid, GetUserId()))
389+ if (!pg_class_ownercheck(tableOid, save_userid))
390 {
391 relation_close(OldHeap, AccessExclusiveLock);
392- pgstat_progress_end_command();
393- return;
394+ goto out;
395 }
396
397 /*
398@@ -327,8 +339,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
399 if (RELATION_IS_OTHER_TEMP(OldHeap))
400 {
401 relation_close(OldHeap, AccessExclusiveLock);
402- pgstat_progress_end_command();
403- return;
404+ goto out;
405 }
406
407 if (OidIsValid(indexOid))
408@@ -339,8 +350,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
409 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid)))
410 {
411 relation_close(OldHeap, AccessExclusiveLock);
412- pgstat_progress_end_command();
413- return;
414+ goto out;
415 }
416
417 /*
418@@ -350,8 +360,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
419 if (!HeapTupleIsValid(tuple)) /* probably can't happen */
420 {
421 relation_close(OldHeap, AccessExclusiveLock);
422- pgstat_progress_end_command();
423- return;
424+ goto out;
425 }
426 indexForm = (Form_pg_index) GETSTRUCT(tuple);
427 if (!indexForm->indisclustered)
428@@ -413,8 +422,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
429 !RelationIsPopulated(OldHeap))
430 {
431 relation_close(OldHeap, AccessExclusiveLock);
432- pgstat_progress_end_command();
433- return;
434+ goto out;
435 }
436
437 /*
438@@ -430,6 +438,13 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
439
440 /* NB: rebuild_relation does table_close() on OldHeap */
441
442+out:
443+ /* Roll back any GUC changes executed by index functions */
444+ AtEOXact_GUC(false, save_nestlevel);
445+
446+ /* Restore userid and security context */
447+ SetUserIdAndSecContext(save_userid, save_sec_context);
448+
449 pgstat_progress_end_command();
450 }
451
452diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
453index be1cf8c..167b377 100644
454--- a/src/backend/commands/indexcmds.c
455+++ b/src/backend/commands/indexcmds.c
456@@ -470,21 +470,22 @@ DefineIndex(Oid relationId,
457 LOCKTAG heaplocktag;
458 LOCKMODE lockmode;
459 Snapshot snapshot;
460- int save_nestlevel = -1;
461+ Oid root_save_userid;
462+ int root_save_sec_context;
463+ int root_save_nestlevel;
464 int i;
465
466+ root_save_nestlevel = NewGUCNestLevel();
467+
468 /*
469 * Some callers need us to run with an empty default_tablespace; this is a
470 * necessary hack to be able to reproduce catalog state accurately when
471 * recreating indexes after table-rewriting ALTER TABLE.
472 */
473 if (stmt->reset_default_tblspc)
474- {
475- save_nestlevel = NewGUCNestLevel();
476 (void) set_config_option("default_tablespace", "",
477 PGC_USERSET, PGC_S_SESSION,
478 GUC_ACTION_SAVE, true, 0, false);
479- }
480
481 /*
482 * Force non-concurrent build on temporary relations, even if CONCURRENTLY
483@@ -563,6 +564,15 @@ DefineIndex(Oid relationId,
484 lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
485 rel = table_open(relationId, lockmode);
486
487+ /*
488+ * Switch to the table owner's userid, so that any index functions are run
489+ * as that user. Also lock down security-restricted operations. We
490+ * already arranged to make GUC variable changes local to this command.
491+ */
492+ GetUserIdAndSecContext(&root_save_userid, &root_save_sec_context);
493+ SetUserIdAndSecContext(rel->rd_rel->relowner,
494+ root_save_sec_context | SECURITY_RESTRICTED_OPERATION);
495+
496 namespaceId = RelationGetNamespace(rel);
497
498 /* Ensure that it makes sense to index this kind of relation */
499@@ -648,7 +658,7 @@ DefineIndex(Oid relationId,
500 {
501 AclResult aclresult;
502
503- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
504+ aclresult = pg_namespace_aclcheck(namespaceId, root_save_userid,
505 ACL_CREATE);
506 if (aclresult != ACLCHECK_OK)
507 aclcheck_error(aclresult, OBJECT_SCHEMA,
508@@ -680,7 +690,7 @@ DefineIndex(Oid relationId,
509 {
510 AclResult aclresult;
511
512- aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
513+ aclresult = pg_tablespace_aclcheck(tablespaceId, root_save_userid,
514 ACL_CREATE);
515 if (aclresult != ACLCHECK_OK)
516 aclcheck_error(aclresult, OBJECT_TABLESPACE,
517@@ -1066,15 +1076,17 @@ DefineIndex(Oid relationId,
518
519 ObjectAddressSet(address, RelationRelationId, indexRelationId);
520
521- /*
522- * Revert to original default_tablespace. Must do this before any return
523- * from this function, but after index_create, so this is a good time.
524- */
525- if (save_nestlevel >= 0)
526- AtEOXact_GUC(true, save_nestlevel);
527-
528 if (!OidIsValid(indexRelationId))
529 {
530+ /*
531+ * Roll back any GUC changes executed by index functions. Also revert
532+ * to original default_tablespace if we changed it above.
533+ */
534+ AtEOXact_GUC(false, root_save_nestlevel);
535+
536+ /* Restore userid and security context */
537+ SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
538+
539 table_close(rel, NoLock);
540
541 /* If this is the top-level index, we're done */
542@@ -1084,6 +1096,17 @@ DefineIndex(Oid relationId,
543 return address;
544 }
545
546+ /*
547+ * Roll back any GUC changes executed by index functions, and keep
548+ * subsequent changes local to this command. It's barely possible that
549+ * some index function changed a behavior-affecting GUC, e.g. xmloption,
550+ * that affects subsequent steps. This improves bug-compatibility with
551+ * older PostgreSQL versions. They did the AtEOXact_GUC() here for the
552+ * purpose of clearing the above default_tablespace change.
553+ */
554+ AtEOXact_GUC(false, root_save_nestlevel);
555+ root_save_nestlevel = NewGUCNestLevel();
556+
557 /* Add any requested comment */
558 if (stmt->idxcomment != NULL)
559 CreateComments(indexRelationId, RelationRelationId, 0,
560@@ -1130,6 +1153,9 @@ DefineIndex(Oid relationId,
561 {
562 Oid childRelid = part_oids[i];
563 Relation childrel;
564+ Oid child_save_userid;
565+ int child_save_sec_context;
566+ int child_save_nestlevel;
567 List *childidxs;
568 ListCell *cell;
569 AttrNumber *attmap;
570@@ -1138,6 +1164,12 @@ DefineIndex(Oid relationId,
571
572 childrel = table_open(childRelid, lockmode);
573
574+ GetUserIdAndSecContext(&child_save_userid,
575+ &child_save_sec_context);
576+ SetUserIdAndSecContext(childrel->rd_rel->relowner,
577+ child_save_sec_context | SECURITY_RESTRICTED_OPERATION);
578+ child_save_nestlevel = NewGUCNestLevel();
579+
580 /*
581 * Don't try to create indexes on foreign tables, though. Skip
582 * those if a regular index, or fail if trying to create a
583@@ -1153,6 +1185,9 @@ DefineIndex(Oid relationId,
584 errdetail("Table \"%s\" contains partitions that are foreign tables.",
585 RelationGetRelationName(rel))));
586
587+ AtEOXact_GUC(false, child_save_nestlevel);
588+ SetUserIdAndSecContext(child_save_userid,
589+ child_save_sec_context);
590 table_close(childrel, lockmode);
591 continue;
592 }
593@@ -1226,6 +1261,9 @@ DefineIndex(Oid relationId,
594 }
595
596 list_free(childidxs);
597+ AtEOXact_GUC(false, child_save_nestlevel);
598+ SetUserIdAndSecContext(child_save_userid,
599+ child_save_sec_context);
600 table_close(childrel, NoLock);
601
602 /*
603@@ -1280,12 +1318,21 @@ DefineIndex(Oid relationId,
604 if (found_whole_row)
605 elog(ERROR, "cannot convert whole-row table reference");
606
607+ /*
608+ * Recurse as the starting user ID. Callee will use that
609+ * for permission checks, then switch again.
610+ */
611+ Assert(GetUserId() == child_save_userid);
612+ SetUserIdAndSecContext(root_save_userid,
613+ root_save_sec_context);
614 DefineIndex(childRelid, childStmt,
615 InvalidOid, /* no predefined OID */
616 indexRelationId, /* this is our child */
617 createdConstraintId,
618 is_alter_table, check_rights, check_not_in_use,
619 skip_build, quiet);
620+ SetUserIdAndSecContext(child_save_userid,
621+ child_save_sec_context);
622 }
623
624 pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_DONE,
625@@ -1322,12 +1369,17 @@ DefineIndex(Oid relationId,
626 * Indexes on partitioned tables are not themselves built, so we're
627 * done here.
628 */
629+ AtEOXact_GUC(false, root_save_nestlevel);
630+ SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
631 table_close(rel, NoLock);
632 if (!OidIsValid(parentIndexId))
633 pgstat_progress_end_command();
634 return address;
635 }
636
637+ AtEOXact_GUC(false, root_save_nestlevel);
638+ SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
639+
640 if (!concurrent)
641 {
642 /* Close the heap and we're done, in the non-concurrent case */
643@@ -3040,6 +3092,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
644 Oid newIndexId;
645 Relation indexRel;
646 Relation heapRel;
647+ Oid save_userid;
648+ int save_sec_context;
649+ int save_nestlevel;
650 Relation newIndexRel;
651 LockRelId *lockrelid;
652
653@@ -3047,6 +3102,16 @@ ReindexRelationConcurrently(Oid relationOid, int options)
654 heapRel = table_open(indexRel->rd_index->indrelid,
655 ShareUpdateExclusiveLock);
656
657+ /*
658+ * Switch to the table owner's userid, so that any index functions are
659+ * run as that user. Also lock down security-restricted operations
660+ * and arrange to make GUC variable changes local to this command.
661+ */
662+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
663+ SetUserIdAndSecContext(heapRel->rd_rel->relowner,
664+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
665+ save_nestlevel = NewGUCNestLevel();
666+
667 /* This function shouldn't be called for temporary relations. */
668 if (indexRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
669 elog(ERROR, "cannot reindex a temporary table concurrently");
670@@ -3101,6 +3166,13 @@ ReindexRelationConcurrently(Oid relationOid, int options)
671
672 index_close(indexRel, NoLock);
673 index_close(newIndexRel, NoLock);
674+
675+ /* Roll back any GUC changes executed by index functions */
676+ AtEOXact_GUC(false, save_nestlevel);
677+
678+ /* Restore userid and security context */
679+ SetUserIdAndSecContext(save_userid, save_sec_context);
680+
681 table_close(heapRel, NoLock);
682 }
683
684diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
685index 80e9ec0..e485661 100644
686--- a/src/backend/commands/matview.c
687+++ b/src/backend/commands/matview.c
688@@ -167,6 +167,17 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
689 lockmode, 0,
690 RangeVarCallbackOwnsTable, NULL);
691 matviewRel = table_open(matviewOid, NoLock);
692+ relowner = matviewRel->rd_rel->relowner;
693+
694+ /*
695+ * Switch to the owner's userid, so that any functions are run as that
696+ * user. Also lock down security-restricted operations and arrange to
697+ * make GUC variable changes local to this command.
698+ */
699+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
700+ SetUserIdAndSecContext(relowner,
701+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
702+ save_nestlevel = NewGUCNestLevel();
703
704 /* Make sure it is a materialized view. */
705 if (matviewRel->rd_rel->relkind != RELKIND_MATVIEW)
706@@ -268,19 +279,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
707 */
708 SetMatViewPopulatedState(matviewRel, !stmt->skipData);
709
710- relowner = matviewRel->rd_rel->relowner;
711-
712- /*
713- * Switch to the owner's userid, so that any functions are run as that
714- * user. Also arrange to make GUC variable changes local to this command.
715- * Don't lock it down too tight to create a temporary table just yet. We
716- * will switch modes when we are about to execute user code.
717- */
718- GetUserIdAndSecContext(&save_userid, &save_sec_context);
719- SetUserIdAndSecContext(relowner,
720- save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
721- save_nestlevel = NewGUCNestLevel();
722-
723 /* Concurrent refresh builds new data in temp tablespace, and does diff. */
724 if (concurrent)
725 {
726@@ -303,12 +301,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
727 LockRelationOid(OIDNewHeap, AccessExclusiveLock);
728 dest = CreateTransientRelDestReceiver(OIDNewHeap);
729
730- /*
731- * Now lock down security-restricted operations.
732- */
733- SetUserIdAndSecContext(relowner,
734- save_sec_context | SECURITY_RESTRICTED_OPERATION);
735-
736 /* Generate the data, if wanted. */
737 if (!stmt->skipData)
738 processed = refresh_matview_datafill(dest, dataQuery, queryString);
739diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
740index de554e2..c9f858e 100644
741--- a/src/backend/utils/init/miscinit.c
742+++ b/src/backend/utils/init/miscinit.c
743@@ -455,15 +455,21 @@ GetAuthenticatedUserId(void)
744 * with guc.c's internal state, so SET ROLE has to be disallowed.
745 *
746 * SECURITY_RESTRICTED_OPERATION indicates that we are inside an operation
747- * that does not wish to trust called user-defined functions at all. This
748- * bit prevents not only SET ROLE, but various other changes of session state
749- * that normally is unprotected but might possibly be used to subvert the
750- * calling session later. An example is replacing an existing prepared
751- * statement with new code, which will then be executed with the outer
752- * session's permissions when the prepared statement is next used. Since
753- * these restrictions are fairly draconian, we apply them only in contexts
754- * where the called functions are really supposed to be side-effect-free
755- * anyway, such as VACUUM/ANALYZE/REINDEX.
756+ * that does not wish to trust called user-defined functions at all. The
757+ * policy is to use this before operations, e.g. autovacuum and REINDEX, that
758+ * enumerate relations of a database or schema and run functions associated
759+ * with each found relation. The relation owner is the new user ID. Set this
760+ * as soon as possible after locking the relation. Restore the old user ID as
761+ * late as possible before closing the relation; restoring it shortly after
762+ * close is also tolerable. If a command has both relation-enumerating and
763+ * non-enumerating modes, e.g. ANALYZE, both modes set this bit. This bit
764+ * prevents not only SET ROLE, but various other changes of session state that
765+ * normally is unprotected but might possibly be used to subvert the calling
766+ * session later. An example is replacing an existing prepared statement with
767+ * new code, which will then be executed with the outer session's permissions
768+ * when the prepared statement is next used. These restrictions are fairly
769+ * draconian, but the functions called in relation-enumerating operations are
770+ * really supposed to be side-effect-free anyway.
771 *
772 * SECURITY_NOFORCE_RLS indicates that we are inside an operation which should
773 * ignore the FORCE ROW LEVEL SECURITY per-table indication. This is used to
774diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
775index 186d2fb..0f0c1b3 100644
776--- a/src/test/regress/expected/privileges.out
777+++ b/src/test/regress/expected/privileges.out
778@@ -1336,6 +1336,61 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
779 -- security-restricted operations
780 \c -
781 CREATE ROLE regress_sro_user;
782+-- Check that index expressions and predicates are run as the table's owner
783+-- A dummy index function checking current_user
784+CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
785+BEGIN
786+ -- Below we set the table's owner to regress_sro_user
787+ ASSERT current_user = 'regress_sro_user',
788+ format('sro_ifun(%s) called by %s', $1, current_user);
789+ RETURN $1;
790+END;
791+$$ LANGUAGE plpgsql IMMUTABLE;
792+-- Create a table owned by regress_sro_user
793+CREATE TABLE sro_tab (a int);
794+ALTER TABLE sro_tab OWNER TO regress_sro_user;
795+INSERT INTO sro_tab VALUES (1), (2), (3);
796+-- Create an expression index with a predicate
797+CREATE INDEX sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
798+ WHERE sro_ifun(a + 10) > sro_ifun(10);
799+DROP INDEX sro_idx;
800+-- Do the same concurrently
801+CREATE INDEX CONCURRENTLY sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
802+ WHERE sro_ifun(a + 10) > sro_ifun(10);
803+-- REINDEX
804+REINDEX TABLE sro_tab;
805+REINDEX INDEX sro_idx;
806+REINDEX TABLE CONCURRENTLY sro_tab;
807+DROP INDEX sro_idx;
808+-- CLUSTER
809+CREATE INDEX sro_cluster_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)));
810+CLUSTER sro_tab USING sro_cluster_idx;
811+DROP INDEX sro_cluster_idx;
812+-- BRIN index
813+CREATE INDEX sro_brin ON sro_tab USING brin ((sro_ifun(a) + sro_ifun(0)));
814+SELECT brin_desummarize_range('sro_brin', 0);
815+ brin_desummarize_range
816+------------------------
817+
818+(1 row)
819+
820+SELECT brin_summarize_range('sro_brin', 0);
821+ brin_summarize_range
822+----------------------
823+ 1
824+(1 row)
825+
826+DROP TABLE sro_tab;
827+-- Check with a partitioned table
828+CREATE TABLE sro_ptab (a int) PARTITION BY RANGE (a);
829+ALTER TABLE sro_ptab OWNER TO regress_sro_user;
830+CREATE TABLE sro_part PARTITION OF sro_ptab FOR VALUES FROM (1) TO (10);
831+ALTER TABLE sro_part OWNER TO regress_sro_user;
832+INSERT INTO sro_ptab VALUES (1), (2), (3);
833+CREATE INDEX sro_pidx ON sro_ptab ((sro_ifun(a) + sro_ifun(0)))
834+ WHERE sro_ifun(a + 10) > sro_ifun(10);
835+REINDEX TABLE sro_ptab;
836+REINDEX INDEX CONCURRENTLY sro_pidx;
837 SET SESSION AUTHORIZATION regress_sro_user;
838 CREATE FUNCTION unwanted_grant() RETURNS void LANGUAGE sql AS
839 'GRANT regress_priv_group2 TO regress_sro_user';
840@@ -1373,6 +1428,22 @@ CONTEXT: SQL function "unwanted_grant" statement 1
841 SQL statement "SELECT unwanted_grant()"
842 PL/pgSQL function sro_trojan() line 1 at PERFORM
843 SQL function "mv_action" statement 1
844+-- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions()
845+SET SESSION AUTHORIZATION regress_sro_user;
846+CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int
847+ IMMUTABLE LANGUAGE plpgsql AS $$
848+BEGIN
849+ PERFORM unwanted_grant();
850+ RAISE WARNING 'owned';
851+ RETURN 1;
852+EXCEPTION WHEN OTHERS THEN
853+ RETURN 2;
854+END$$;
855+CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c;
856+CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0;
857+\c -
858+REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv;
859+REFRESH MATERIALIZED VIEW sro_index_mv;
860 DROP OWNED BY regress_sro_user;
861 DROP ROLE regress_sro_user;
862 -- Admin options
863diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
864index 34fbf0e..c0b88a6 100644
865--- a/src/test/regress/sql/privileges.sql
866+++ b/src/test/regress/sql/privileges.sql
867@@ -826,6 +826,53 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
868 \c -
869 CREATE ROLE regress_sro_user;
870
871+-- Check that index expressions and predicates are run as the table's owner
872+
873+-- A dummy index function checking current_user
874+CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
875+BEGIN
876+ -- Below we set the table's owner to regress_sro_user
877+ ASSERT current_user = 'regress_sro_user',
878+ format('sro_ifun(%s) called by %s', $1, current_user);
879+ RETURN $1;
880+END;
881+$$ LANGUAGE plpgsql IMMUTABLE;
882+-- Create a table owned by regress_sro_user
883+CREATE TABLE sro_tab (a int);
884+ALTER TABLE sro_tab OWNER TO regress_sro_user;
885+INSERT INTO sro_tab VALUES (1), (2), (3);
886+-- Create an expression index with a predicate
887+CREATE INDEX sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
888+ WHERE sro_ifun(a + 10) > sro_ifun(10);
889+DROP INDEX sro_idx;
890+-- Do the same concurrently
891+CREATE INDEX CONCURRENTLY sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
892+ WHERE sro_ifun(a + 10) > sro_ifun(10);
893+-- REINDEX
894+REINDEX TABLE sro_tab;
895+REINDEX INDEX sro_idx;
896+REINDEX TABLE CONCURRENTLY sro_tab;
897+DROP INDEX sro_idx;
898+-- CLUSTER
899+CREATE INDEX sro_cluster_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)));
900+CLUSTER sro_tab USING sro_cluster_idx;
901+DROP INDEX sro_cluster_idx;
902+-- BRIN index
903+CREATE INDEX sro_brin ON sro_tab USING brin ((sro_ifun(a) + sro_ifun(0)));
904+SELECT brin_desummarize_range('sro_brin', 0);
905+SELECT brin_summarize_range('sro_brin', 0);
906+DROP TABLE sro_tab;
907+-- Check with a partitioned table
908+CREATE TABLE sro_ptab (a int) PARTITION BY RANGE (a);
909+ALTER TABLE sro_ptab OWNER TO regress_sro_user;
910+CREATE TABLE sro_part PARTITION OF sro_ptab FOR VALUES FROM (1) TO (10);
911+ALTER TABLE sro_part OWNER TO regress_sro_user;
912+INSERT INTO sro_ptab VALUES (1), (2), (3);
913+CREATE INDEX sro_pidx ON sro_ptab ((sro_ifun(a) + sro_ifun(0)))
914+ WHERE sro_ifun(a + 10) > sro_ifun(10);
915+REINDEX TABLE sro_ptab;
916+REINDEX INDEX CONCURRENTLY sro_pidx;
917+
918 SET SESSION AUTHORIZATION regress_sro_user;
919 CREATE FUNCTION unwanted_grant() RETURNS void LANGUAGE sql AS
920 'GRANT regress_priv_group2 TO regress_sro_user';
921@@ -852,6 +899,23 @@ REFRESH MATERIALIZED VIEW sro_mv;
922 REFRESH MATERIALIZED VIEW sro_mv;
923 BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT;
924
925+-- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions()
926+SET SESSION AUTHORIZATION regress_sro_user;
927+CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int
928+ IMMUTABLE LANGUAGE plpgsql AS $$
929+BEGIN
930+ PERFORM unwanted_grant();
931+ RAISE WARNING 'owned';
932+ RETURN 1;
933+EXCEPTION WHEN OTHERS THEN
934+ RETURN 2;
935+END$$;
936+CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c;
937+CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0;
938+\c -
939+REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv;
940+REFRESH MATERIALIZED VIEW sro_index_mv;
941+
942 DROP OWNED BY regress_sro_user;
943 DROP ROLE regress_sro_user;
944
945--
9462.25.1
947
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch
deleted file mode 100644
index 6417d8a2b..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch
+++ /dev/null
@@ -1,904 +0,0 @@
1From 84375c1db25ef650902cf80712495fc514b0ff63 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 13 Oct 2022 10:35:32 +0530
4Subject: [PATCH] CVE-2022-2625
5
6Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=5579726bd60a6e7afb04a3548bced348cd5ffd89]
7CVE: CVE-2022-2625
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 doc/src/sgml/extend.sgml | 11 --
11 src/backend/catalog/pg_collation.c | 49 ++++--
12 src/backend/catalog/pg_depend.c | 74 ++++++++-
13 src/backend/catalog/pg_operator.c | 2 +-
14 src/backend/catalog/pg_type.c | 7 +-
15 src/backend/commands/createas.c | 18 ++-
16 src/backend/commands/foreigncmds.c | 19 ++-
17 src/backend/commands/schemacmds.c | 25 ++-
18 src/backend/commands/sequence.c | 8 +
19 src/backend/commands/statscmds.c | 4 +
20 src/backend/commands/view.c | 16 +-
21 src/backend/parser/parse_utilcmd.c | 10 ++
22 src/include/catalog/dependency.h | 2 +
23 src/test/modules/test_extensions/Makefile | 5 +-
24 .../expected/test_extensions.out | 153 ++++++++++++++++++
25 .../test_extensions/sql/test_extensions.sql | 110 +++++++++++++
26 .../test_ext_cine--1.0--1.1.sql | 26 +++
27 .../test_extensions/test_ext_cine--1.0.sql | 25 +++
28 .../test_extensions/test_ext_cine.control | 3 +
29 .../test_extensions/test_ext_cor--1.0.sql | 20 +++
30 .../test_extensions/test_ext_cor.control | 3 +
31 21 files changed, 540 insertions(+), 50 deletions(-)
32 create mode 100644 src/test/modules/test_extensions/test_ext_cine--1.0--1.1.sql
33 create mode 100644 src/test/modules/test_extensions/test_ext_cine--1.0.sql
34 create mode 100644 src/test/modules/test_extensions/test_ext_cine.control
35 create mode 100644 src/test/modules/test_extensions/test_ext_cor--1.0.sql
36 create mode 100644 src/test/modules/test_extensions/test_ext_cor.control
37
38diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml
39index 53f2638..bcc7a80 100644
40--- a/doc/src/sgml/extend.sgml
41+++ b/doc/src/sgml/extend.sgml
42@@ -1109,17 +1109,6 @@ SELECT * FROM pg_extension_update_paths('<replaceable>extension_name</replaceabl
43 <varname>search_path</varname>. However, no mechanism currently exists
44 to require that.
45 </para>
46-
47- <para>
48- Do <emphasis>not</emphasis> use <command>CREATE OR REPLACE
49- FUNCTION</command>, except in an update script that must change the
50- definition of a function that is known to be an extension member
51- already. (Likewise for other <literal>OR REPLACE</literal> options.)
52- Using <literal>OR REPLACE</literal> unnecessarily not only has a risk
53- of accidentally overwriting someone else's function, but it creates a
54- security hazard since the overwritten function would still be owned by
55- its original owner, who could modify it.
56- </para>
57 </sect3>
58 </sect2>
59
60diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
61index dd99d53..ba4c3ef 100644
62--- a/src/backend/catalog/pg_collation.c
63+++ b/src/backend/catalog/pg_collation.c
64@@ -78,15 +78,25 @@ CollationCreate(const char *collname, Oid collnamespace,
65 * friendlier error message. The unique index provides a backstop against
66 * race conditions.
67 */
68- if (SearchSysCacheExists3(COLLNAMEENCNSP,
69- PointerGetDatum(collname),
70- Int32GetDatum(collencoding),
71- ObjectIdGetDatum(collnamespace)))
72+ oid = GetSysCacheOid3(COLLNAMEENCNSP,
73+ Anum_pg_collation_oid,
74+ PointerGetDatum(collname),
75+ Int32GetDatum(collencoding),
76+ ObjectIdGetDatum(collnamespace));
77+ if (OidIsValid(oid))
78 {
79 if (quiet)
80 return InvalidOid;
81 else if (if_not_exists)
82 {
83+ /*
84+ * If we are in an extension script, insist that the pre-existing
85+ * object be a member of the extension, to avoid security risks.
86+ */
87+ ObjectAddressSet(myself, CollationRelationId, oid);
88+ checkMembershipInCurrentExtension(&myself);
89+
90+ /* OK to skip */
91 ereport(NOTICE,
92 (errcode(ERRCODE_DUPLICATE_OBJECT),
93 collencoding == -1
94@@ -116,16 +126,19 @@ CollationCreate(const char *collname, Oid collnamespace,
95 * so we take a ShareRowExclusiveLock earlier, to protect against
96 * concurrent changes fooling this check.
97 */
98- if ((collencoding == -1 &&
99- SearchSysCacheExists3(COLLNAMEENCNSP,
100- PointerGetDatum(collname),
101- Int32GetDatum(GetDatabaseEncoding()),
102- ObjectIdGetDatum(collnamespace))) ||
103- (collencoding != -1 &&
104- SearchSysCacheExists3(COLLNAMEENCNSP,
105- PointerGetDatum(collname),
106- Int32GetDatum(-1),
107- ObjectIdGetDatum(collnamespace))))
108+ if (collencoding == -1)
109+ oid = GetSysCacheOid3(COLLNAMEENCNSP,
110+ Anum_pg_collation_oid,
111+ PointerGetDatum(collname),
112+ Int32GetDatum(GetDatabaseEncoding()),
113+ ObjectIdGetDatum(collnamespace));
114+ else
115+ oid = GetSysCacheOid3(COLLNAMEENCNSP,
116+ Anum_pg_collation_oid,
117+ PointerGetDatum(collname),
118+ Int32GetDatum(-1),
119+ ObjectIdGetDatum(collnamespace));
120+ if (OidIsValid(oid))
121 {
122 if (quiet)
123 {
124@@ -134,6 +147,14 @@ CollationCreate(const char *collname, Oid collnamespace,
125 }
126 else if (if_not_exists)
127 {
128+ /*
129+ * If we are in an extension script, insist that the pre-existing
130+ * object be a member of the extension, to avoid security risks.
131+ */
132+ ObjectAddressSet(myself, CollationRelationId, oid);
133+ checkMembershipInCurrentExtension(&myself);
134+
135+ /* OK to skip */
136 table_close(rel, NoLock);
137 ereport(NOTICE,
138 (errcode(ERRCODE_DUPLICATE_OBJECT),
139diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
140index 9ffadbb..71c7cef 100644
141--- a/src/backend/catalog/pg_depend.c
142+++ b/src/backend/catalog/pg_depend.c
143@@ -124,15 +124,23 @@ recordMultipleDependencies(const ObjectAddress *depender,
144
145 /*
146 * If we are executing a CREATE EXTENSION operation, mark the given object
147- * as being a member of the extension. Otherwise, do nothing.
148+ * as being a member of the extension, or check that it already is one.
149+ * Otherwise, do nothing.
150 *
151 * This must be called during creation of any user-definable object type
152 * that could be a member of an extension.
153 *
154- * If isReplace is true, the object already existed (or might have already
155- * existed), so we must check for a pre-existing extension membership entry.
156- * Passing false is a guarantee that the object is newly created, and so
157- * could not already be a member of any extension.
158+ * isReplace must be true if the object already existed, and false if it is
159+ * newly created. In the former case we insist that it already be a member
160+ * of the current extension. In the latter case we can skip checking whether
161+ * it is already a member of any extension.
162+ *
163+ * Note: isReplace = true is typically used when updating a object in
164+ * CREATE OR REPLACE and similar commands. We used to allow the target
165+ * object to not already be an extension member, instead silently absorbing
166+ * it into the current extension. However, this was both error-prone
167+ * (extensions might accidentally overwrite free-standing objects) and
168+ * a security hazard (since the object would retain its previous ownership).
169 */
170 void
171 recordDependencyOnCurrentExtension(const ObjectAddress *object,
172@@ -150,6 +158,12 @@ recordDependencyOnCurrentExtension(const ObjectAddress *object,
173 {
174 Oid oldext;
175
176+ /*
177+ * Side note: these catalog lookups are safe only because the
178+ * object is a pre-existing one. In the not-isReplace case, the
179+ * caller has most likely not yet done a CommandCounterIncrement
180+ * that would make the new object visible.
181+ */
182 oldext = getExtensionOfObject(object->classId, object->objectId);
183 if (OidIsValid(oldext))
184 {
185@@ -163,6 +177,13 @@ recordDependencyOnCurrentExtension(const ObjectAddress *object,
186 getObjectDescription(object),
187 get_extension_name(oldext))));
188 }
189+ /* It's a free-standing object, so reject */
190+ ereport(ERROR,
191+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
192+ errmsg("%s is not a member of extension \"%s\"",
193+ getObjectDescription(object),
194+ get_extension_name(CurrentExtensionObject)),
195+ errdetail("An extension is not allowed to replace an object that it does not own.")));
196 }
197
198 /* OK, record it as a member of CurrentExtensionObject */
199@@ -174,6 +195,49 @@ recordDependencyOnCurrentExtension(const ObjectAddress *object,
200 }
201 }
202
203+/*
204+ * If we are executing a CREATE EXTENSION operation, check that the given
205+ * object is a member of the extension, and throw an error if it isn't.
206+ * Otherwise, do nothing.
207+ *
208+ * This must be called whenever a CREATE IF NOT EXISTS operation (for an
209+ * object type that can be an extension member) has found that an object of
210+ * the desired name already exists. It is insecure for an extension to use
211+ * IF NOT EXISTS except when the conflicting object is already an extension
212+ * member; otherwise a hostile user could substitute an object with arbitrary
213+ * properties.
214+ */
215+void
216+checkMembershipInCurrentExtension(const ObjectAddress *object)
217+{
218+ /*
219+ * This is actually the same condition tested in
220+ * recordDependencyOnCurrentExtension; but we want to issue a
221+ * differently-worded error, and anyway it would be pretty confusing to
222+ * call recordDependencyOnCurrentExtension in these circumstances.
223+ */
224+
225+ /* Only whole objects can be extension members */
226+ Assert(object->objectSubId == 0);
227+
228+ if (creating_extension)
229+ {
230+ Oid oldext;
231+
232+ oldext = getExtensionOfObject(object->classId, object->objectId);
233+ /* If already a member of this extension, OK */
234+ if (oldext == CurrentExtensionObject)
235+ return;
236+ /* Else complain */
237+ ereport(ERROR,
238+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
239+ errmsg("%s is not a member of extension \"%s\"",
240+ getObjectDescription(object),
241+ get_extension_name(CurrentExtensionObject)),
242+ errdetail("An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.")));
243+ }
244+}
245+
246 /*
247 * deleteDependencyRecordsFor -- delete all records with given depender
248 * classId/objectId. Returns the number of records deleted.
249diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
250index bcaa26c..84784e6 100644
251--- a/src/backend/catalog/pg_operator.c
252+++ b/src/backend/catalog/pg_operator.c
253@@ -867,7 +867,7 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
254 oper->oprowner);
255
256 /* Dependency on extension */
257- recordDependencyOnCurrentExtension(&myself, true);
258+ recordDependencyOnCurrentExtension(&myself, isUpdate);
259
260 return myself;
261 }
262diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
263index 2a51501..3ff017f 100644
264--- a/src/backend/catalog/pg_type.c
265+++ b/src/backend/catalog/pg_type.c
266@@ -528,10 +528,9 @@ TypeCreate(Oid newTypeOid,
267 * If rebuild is true, we remove existing dependencies and rebuild them
268 * from scratch. This is needed for ALTER TYPE, and also when replacing
269 * a shell type. We don't remove an existing extension dependency, though.
270- * (That means an extension can't absorb a shell type created in another
271- * extension, nor ALTER a type created by another extension. Also, if it
272- * replaces a free-standing shell type or ALTERs a free-standing type,
273- * that type will become a member of the extension.)
274+ * That means an extension can't absorb a shell type that is free-standing
275+ * or belongs to another extension, nor ALTER a type that is free-standing or
276+ * belongs to another extension.
277 */
278 void
279 GenerateTypeDependencies(Oid typeObjectId,
280diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
281index 4c1d909..a68d945 100644
282--- a/src/backend/commands/createas.c
283+++ b/src/backend/commands/createas.c
284@@ -243,15 +243,27 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
285 if (stmt->if_not_exists)
286 {
287 Oid nspid;
288+ Oid oldrelid;
289
290- nspid = RangeVarGetCreationNamespace(stmt->into->rel);
291+ nspid = RangeVarGetCreationNamespace(into->rel);
292
293- if (get_relname_relid(stmt->into->rel->relname, nspid))
294+ oldrelid = get_relname_relid(into->rel->relname, nspid);
295+ if (OidIsValid(oldrelid))
296 {
297+ /*
298+ * The relation exists and IF NOT EXISTS has been specified.
299+ *
300+ * If we are in an extension script, insist that the pre-existing
301+ * object be a member of the extension, to avoid security risks.
302+ */
303+ ObjectAddressSet(address, RelationRelationId, oldrelid);
304+ checkMembershipInCurrentExtension(&address);
305+
306+ /* OK to skip */
307 ereport(NOTICE,
308 (errcode(ERRCODE_DUPLICATE_TABLE),
309 errmsg("relation \"%s\" already exists, skipping",
310- stmt->into->rel->relname)));
311+ into->rel->relname)));
312 return InvalidObjectAddress;
313 }
314 }
315diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
316index d7bc6e3..bc583c6 100644
317--- a/src/backend/commands/foreigncmds.c
318+++ b/src/backend/commands/foreigncmds.c
319@@ -887,13 +887,22 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
320 ownerId = GetUserId();
321
322 /*
323- * Check that there is no other foreign server by this name. Do nothing if
324- * IF NOT EXISTS was enforced.
325+ * Check that there is no other foreign server by this name. If there is
326+ * one, do nothing if IF NOT EXISTS was specified.
327 */
328- if (GetForeignServerByName(stmt->servername, true) != NULL)
329+ srvId = get_foreign_server_oid(stmt->servername, true);
330+ if (OidIsValid(srvId))
331 {
332 if (stmt->if_not_exists)
333 {
334+ /*
335+ * If we are in an extension script, insist that the pre-existing
336+ * object be a member of the extension, to avoid security risks.
337+ */
338+ ObjectAddressSet(myself, ForeignServerRelationId, srvId);
339+ checkMembershipInCurrentExtension(&myself);
340+
341+ /* OK to skip */
342 ereport(NOTICE,
343 (errcode(ERRCODE_DUPLICATE_OBJECT),
344 errmsg("server \"%s\" already exists, skipping",
345@@ -1182,6 +1191,10 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
346 {
347 if (stmt->if_not_exists)
348 {
349+ /*
350+ * Since user mappings aren't members of extensions (see comments
351+ * below), no need for checkMembershipInCurrentExtension here.
352+ */
353 ereport(NOTICE,
354 (errcode(ERRCODE_DUPLICATE_OBJECT),
355 errmsg("user mapping for \"%s\" already exists for server \"%s\", skipping",
356diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
357index 6cf94a3..6bc4edc 100644
358--- a/src/backend/commands/schemacmds.c
359+++ b/src/backend/commands/schemacmds.c
360@@ -113,14 +113,25 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
361 * the permissions checks, but since CREATE TABLE IF NOT EXISTS makes its
362 * creation-permission check first, we do likewise.
363 */
364- if (stmt->if_not_exists &&
365- SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(schemaName)))
366+ if (stmt->if_not_exists)
367 {
368- ereport(NOTICE,
369- (errcode(ERRCODE_DUPLICATE_SCHEMA),
370- errmsg("schema \"%s\" already exists, skipping",
371- schemaName)));
372- return InvalidOid;
373+ namespaceId = get_namespace_oid(schemaName, true);
374+ if (OidIsValid(namespaceId))
375+ {
376+ /*
377+ * If we are in an extension script, insist that the pre-existing
378+ * object be a member of the extension, to avoid security risks.
379+ */
380+ ObjectAddressSet(address, NamespaceRelationId, namespaceId);
381+ checkMembershipInCurrentExtension(&address);
382+
383+ /* OK to skip */
384+ ereport(NOTICE,
385+ (errcode(ERRCODE_DUPLICATE_SCHEMA),
386+ errmsg("schema \"%s\" already exists, skipping",
387+ schemaName)));
388+ return InvalidOid;
389+ }
390 }
391
392 /*
393diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
394index 0960b33..0577184 100644
395--- a/src/backend/commands/sequence.c
396+++ b/src/backend/commands/sequence.c
397@@ -149,6 +149,14 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
398 RangeVarGetAndCheckCreationNamespace(seq->sequence, NoLock, &seqoid);
399 if (OidIsValid(seqoid))
400 {
401+ /*
402+ * If we are in an extension script, insist that the pre-existing
403+ * object be a member of the extension, to avoid security risks.
404+ */
405+ ObjectAddressSet(address, RelationRelationId, seqoid);
406+ checkMembershipInCurrentExtension(&address);
407+
408+ /* OK to skip */
409 ereport(NOTICE,
410 (errcode(ERRCODE_DUPLICATE_TABLE),
411 errmsg("relation \"%s\" already exists, skipping",
412diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
413index 5678d31..409cf28 100644
414--- a/src/backend/commands/statscmds.c
415+++ b/src/backend/commands/statscmds.c
416@@ -173,6 +173,10 @@ CreateStatistics(CreateStatsStmt *stmt)
417 {
418 if (stmt->if_not_exists)
419 {
420+ /*
421+ * Since stats objects aren't members of extensions (see comments
422+ * below), no need for checkMembershipInCurrentExtension here.
423+ */
424 ereport(NOTICE,
425 (errcode(ERRCODE_DUPLICATE_OBJECT),
426 errmsg("statistics object \"%s\" already exists, skipping",
427diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
428index 87ed453..dd7cc97 100644
429--- a/src/backend/commands/view.c
430+++ b/src/backend/commands/view.c
431@@ -205,7 +205,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
432 CommandCounterIncrement();
433
434 /*
435- * Finally update the view options.
436+ * Update the view's options.
437 *
438 * The new options list replaces the existing options list, even if
439 * it's empty.
440@@ -218,8 +218,22 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
441 /* EventTriggerAlterTableStart called by ProcessUtilitySlow */
442 AlterTableInternal(viewOid, atcmds, true);
443
444+ /*
445+ * There is very little to do here to update the view's dependencies.
446+ * Most view-level dependency relationships, such as those on the
447+ * owner, schema, and associated composite type, aren't changing.
448+ * Because we don't allow changing type or collation of an existing
449+ * view column, those dependencies of the existing columns don't
450+ * change either, while the AT_AddColumnToView machinery took care of
451+ * adding such dependencies for new view columns. The dependencies of
452+ * the view's query could have changed arbitrarily, but that was dealt
453+ * with inside StoreViewQuery. What remains is only to check that
454+ * view replacement is allowed when we're creating an extension.
455+ */
456 ObjectAddressSet(address, RelationRelationId, viewOid);
457
458+ recordDependencyOnCurrentExtension(&address, true);
459+
460 /*
461 * Seems okay, so return the OID of the pre-existing view.
462 */
463diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
464index 44aa38a..8f4d940 100644
465--- a/src/backend/parser/parse_utilcmd.c
466+++ b/src/backend/parser/parse_utilcmd.c
467@@ -206,6 +206,16 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
468 */
469 if (stmt->if_not_exists && OidIsValid(existing_relid))
470 {
471+ /*
472+ * If we are in an extension script, insist that the pre-existing
473+ * object be a member of the extension, to avoid security risks.
474+ */
475+ ObjectAddress address;
476+
477+ ObjectAddressSet(address, RelationRelationId, existing_relid);
478+ checkMembershipInCurrentExtension(&address);
479+
480+ /* OK to skip */
481 ereport(NOTICE,
482 (errcode(ERRCODE_DUPLICATE_TABLE),
483 errmsg("relation \"%s\" already exists, skipping",
484diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
485index 8b1e3aa..27c7509 100644
486--- a/src/include/catalog/dependency.h
487+++ b/src/include/catalog/dependency.h
488@@ -201,6 +201,8 @@ extern void recordMultipleDependencies(const ObjectAddress *depender,
489 extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
490 bool isReplace);
491
492+extern void checkMembershipInCurrentExtension(const ObjectAddress *object);
493+
494 extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
495 bool skipExtensionDeps);
496
497diff --git a/src/test/modules/test_extensions/Makefile b/src/test/modules/test_extensions/Makefile
498index d18108e..7428f15 100644
499--- a/src/test/modules/test_extensions/Makefile
500+++ b/src/test/modules/test_extensions/Makefile
501@@ -4,10 +4,13 @@ MODULE = test_extensions
502 PGFILEDESC = "test_extensions - regression testing for EXTENSION support"
503
504 EXTENSION = test_ext1 test_ext2 test_ext3 test_ext4 test_ext5 test_ext6 \
505- test_ext7 test_ext8 test_ext_cyclic1 test_ext_cyclic2
506+ test_ext7 test_ext8 test_ext_cine test_ext_cor \
507+ test_ext_cyclic1 test_ext_cyclic2
508 DATA = test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \
509 test_ext4--1.0.sql test_ext5--1.0.sql test_ext6--1.0.sql \
510 test_ext7--1.0.sql test_ext7--1.0--2.0.sql test_ext8--1.0.sql \
511+ test_ext_cine--1.0.sql test_ext_cine--1.0--1.1.sql \
512+ test_ext_cor--1.0.sql \
513 test_ext_cyclic1--1.0.sql test_ext_cyclic2--1.0.sql
514
515 REGRESS = test_extensions test_extdepend
516diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
517index b5cbdfc..1e91640 100644
518--- a/src/test/modules/test_extensions/expected/test_extensions.out
519+++ b/src/test/modules/test_extensions/expected/test_extensions.out
520@@ -154,3 +154,156 @@ DROP TABLE test_ext4_tab;
521 DROP FUNCTION create_extension_with_temp_schema();
522 RESET client_min_messages;
523 \unset SHOW_CONTEXT
524+-- It's generally bad style to use CREATE OR REPLACE unnecessarily.
525+-- Test what happens if an extension does it anyway.
526+-- Replacing a shell type or operator is sort of like CREATE OR REPLACE;
527+-- check that too.
528+CREATE FUNCTION ext_cor_func() RETURNS text
529+ AS $$ SELECT 'ext_cor_func: original'::text $$ LANGUAGE sql;
530+CREATE EXTENSION test_ext_cor; -- fail
531+ERROR: function ext_cor_func() is not a member of extension "test_ext_cor"
532+DETAIL: An extension is not allowed to replace an object that it does not own.
533+SELECT ext_cor_func();
534+ ext_cor_func
535+------------------------
536+ ext_cor_func: original
537+(1 row)
538+
539+DROP FUNCTION ext_cor_func();
540+CREATE VIEW ext_cor_view AS
541+ SELECT 'ext_cor_view: original'::text AS col;
542+CREATE EXTENSION test_ext_cor; -- fail
543+ERROR: view ext_cor_view is not a member of extension "test_ext_cor"
544+DETAIL: An extension is not allowed to replace an object that it does not own.
545+SELECT ext_cor_func();
546+ERROR: function ext_cor_func() does not exist
547+LINE 1: SELECT ext_cor_func();
548+ ^
549+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
550+SELECT * FROM ext_cor_view;
551+ col
552+------------------------
553+ ext_cor_view: original
554+(1 row)
555+
556+DROP VIEW ext_cor_view;
557+CREATE TYPE test_ext_type;
558+CREATE EXTENSION test_ext_cor; -- fail
559+ERROR: type test_ext_type is not a member of extension "test_ext_cor"
560+DETAIL: An extension is not allowed to replace an object that it does not own.
561+DROP TYPE test_ext_type;
562+-- this makes a shell "point <<@@ polygon" operator too
563+CREATE OPERATOR @@>> ( PROCEDURE = poly_contain_pt,
564+ LEFTARG = polygon, RIGHTARG = point,
565+ COMMUTATOR = <<@@ );
566+CREATE EXTENSION test_ext_cor; -- fail
567+ERROR: operator <<@@(point,polygon) is not a member of extension "test_ext_cor"
568+DETAIL: An extension is not allowed to replace an object that it does not own.
569+DROP OPERATOR <<@@ (point, polygon);
570+CREATE EXTENSION test_ext_cor; -- now it should work
571+SELECT ext_cor_func();
572+ ext_cor_func
573+------------------------------
574+ ext_cor_func: from extension
575+(1 row)
576+
577+SELECT * FROM ext_cor_view;
578+ col
579+------------------------------
580+ ext_cor_view: from extension
581+(1 row)
582+
583+SELECT 'x'::test_ext_type;
584+ test_ext_type
585+---------------
586+ x
587+(1 row)
588+
589+SELECT point(0,0) <<@@ polygon(circle(point(0,0),1));
590+ ?column?
591+----------
592+ t
593+(1 row)
594+
595+\dx+ test_ext_cor
596+Objects in extension "test_ext_cor"
597+ Object description
598+------------------------------
599+ function ext_cor_func()
600+ operator <<@@(point,polygon)
601+ type test_ext_type
602+ view ext_cor_view
603+(4 rows)
604+
605+--
606+-- CREATE IF NOT EXISTS is an entirely unsound thing for an extension
607+-- to be doing, but let's at least plug the major security hole in it.
608+--
609+CREATE COLLATION ext_cine_coll
610+ ( LC_COLLATE = "C", LC_CTYPE = "C" );
611+CREATE EXTENSION test_ext_cine; -- fail
612+ERROR: collation ext_cine_coll is not a member of extension "test_ext_cine"
613+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
614+DROP COLLATION ext_cine_coll;
615+CREATE MATERIALIZED VIEW ext_cine_mv AS SELECT 11 AS f1;
616+CREATE EXTENSION test_ext_cine; -- fail
617+ERROR: materialized view ext_cine_mv is not a member of extension "test_ext_cine"
618+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
619+DROP MATERIALIZED VIEW ext_cine_mv;
620+CREATE FOREIGN DATA WRAPPER dummy;
621+CREATE SERVER ext_cine_srv FOREIGN DATA WRAPPER dummy;
622+CREATE EXTENSION test_ext_cine; -- fail
623+ERROR: server ext_cine_srv is not a member of extension "test_ext_cine"
624+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
625+DROP SERVER ext_cine_srv;
626+CREATE SCHEMA ext_cine_schema;
627+CREATE EXTENSION test_ext_cine; -- fail
628+ERROR: schema ext_cine_schema is not a member of extension "test_ext_cine"
629+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
630+DROP SCHEMA ext_cine_schema;
631+CREATE SEQUENCE ext_cine_seq;
632+CREATE EXTENSION test_ext_cine; -- fail
633+ERROR: sequence ext_cine_seq is not a member of extension "test_ext_cine"
634+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
635+DROP SEQUENCE ext_cine_seq;
636+CREATE TABLE ext_cine_tab1 (x int);
637+CREATE EXTENSION test_ext_cine; -- fail
638+ERROR: table ext_cine_tab1 is not a member of extension "test_ext_cine"
639+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
640+DROP TABLE ext_cine_tab1;
641+CREATE TABLE ext_cine_tab2 AS SELECT 42 AS y;
642+CREATE EXTENSION test_ext_cine; -- fail
643+ERROR: table ext_cine_tab2 is not a member of extension "test_ext_cine"
644+DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.
645+DROP TABLE ext_cine_tab2;
646+CREATE EXTENSION test_ext_cine;
647+\dx+ test_ext_cine
648+Objects in extension "test_ext_cine"
649+ Object description
650+-----------------------------------
651+ collation ext_cine_coll
652+ foreign-data wrapper ext_cine_fdw
653+ materialized view ext_cine_mv
654+ schema ext_cine_schema
655+ sequence ext_cine_seq
656+ server ext_cine_srv
657+ table ext_cine_tab1
658+ table ext_cine_tab2
659+(8 rows)
660+
661+ALTER EXTENSION test_ext_cine UPDATE TO '1.1';
662+\dx+ test_ext_cine
663+Objects in extension "test_ext_cine"
664+ Object description
665+-----------------------------------
666+ collation ext_cine_coll
667+ foreign-data wrapper ext_cine_fdw
668+ materialized view ext_cine_mv
669+ schema ext_cine_schema
670+ sequence ext_cine_seq
671+ server ext_cine_srv
672+ table ext_cine_tab1
673+ table ext_cine_tab2
674+ table ext_cine_tab3
675+(9 rows)
676+
677diff --git a/src/test/modules/test_extensions/sql/test_extensions.sql b/src/test/modules/test_extensions/sql/test_extensions.sql
678index f505466..b3d4579 100644
679--- a/src/test/modules/test_extensions/sql/test_extensions.sql
680+++ b/src/test/modules/test_extensions/sql/test_extensions.sql
681@@ -93,3 +93,113 @@ DROP TABLE test_ext4_tab;
682 DROP FUNCTION create_extension_with_temp_schema();
683 RESET client_min_messages;
684 \unset SHOW_CONTEXT
685+
686+-- It's generally bad style to use CREATE OR REPLACE unnecessarily.
687+-- Test what happens if an extension does it anyway.
688+-- Replacing a shell type or operator is sort of like CREATE OR REPLACE;
689+-- check that too.
690+
691+CREATE FUNCTION ext_cor_func() RETURNS text
692+ AS $$ SELECT 'ext_cor_func: original'::text $$ LANGUAGE sql;
693+
694+CREATE EXTENSION test_ext_cor; -- fail
695+
696+SELECT ext_cor_func();
697+
698+DROP FUNCTION ext_cor_func();
699+
700+CREATE VIEW ext_cor_view AS
701+ SELECT 'ext_cor_view: original'::text AS col;
702+
703+CREATE EXTENSION test_ext_cor; -- fail
704+
705+SELECT ext_cor_func();
706+
707+SELECT * FROM ext_cor_view;
708+
709+DROP VIEW ext_cor_view;
710+
711+CREATE TYPE test_ext_type;
712+
713+CREATE EXTENSION test_ext_cor; -- fail
714+
715+DROP TYPE test_ext_type;
716+
717+-- this makes a shell "point <<@@ polygon" operator too
718+CREATE OPERATOR @@>> ( PROCEDURE = poly_contain_pt,
719+ LEFTARG = polygon, RIGHTARG = point,
720+ COMMUTATOR = <<@@ );
721+
722+CREATE EXTENSION test_ext_cor; -- fail
723+
724+DROP OPERATOR <<@@ (point, polygon);
725+
726+CREATE EXTENSION test_ext_cor; -- now it should work
727+
728+SELECT ext_cor_func();
729+
730+SELECT * FROM ext_cor_view;
731+
732+SELECT 'x'::test_ext_type;
733+
734+SELECT point(0,0) <<@@ polygon(circle(point(0,0),1));
735+
736+\dx+ test_ext_cor
737+
738+--
739+-- CREATE IF NOT EXISTS is an entirely unsound thing for an extension
740+-- to be doing, but let's at least plug the major security hole in it.
741+--
742+
743+CREATE COLLATION ext_cine_coll
744+ ( LC_COLLATE = "C", LC_CTYPE = "C" );
745+
746+CREATE EXTENSION test_ext_cine; -- fail
747+
748+DROP COLLATION ext_cine_coll;
749+
750+CREATE MATERIALIZED VIEW ext_cine_mv AS SELECT 11 AS f1;
751+
752+CREATE EXTENSION test_ext_cine; -- fail
753+
754+DROP MATERIALIZED VIEW ext_cine_mv;
755+
756+CREATE FOREIGN DATA WRAPPER dummy;
757+
758+CREATE SERVER ext_cine_srv FOREIGN DATA WRAPPER dummy;
759+
760+CREATE EXTENSION test_ext_cine; -- fail
761+
762+DROP SERVER ext_cine_srv;
763+
764+CREATE SCHEMA ext_cine_schema;
765+
766+CREATE EXTENSION test_ext_cine; -- fail
767+
768+DROP SCHEMA ext_cine_schema;
769+
770+CREATE SEQUENCE ext_cine_seq;
771+
772+CREATE EXTENSION test_ext_cine; -- fail
773+
774+DROP SEQUENCE ext_cine_seq;
775+
776+CREATE TABLE ext_cine_tab1 (x int);
777+
778+CREATE EXTENSION test_ext_cine; -- fail
779+
780+DROP TABLE ext_cine_tab1;
781+
782+CREATE TABLE ext_cine_tab2 AS SELECT 42 AS y;
783+
784+CREATE EXTENSION test_ext_cine; -- fail
785+
786+DROP TABLE ext_cine_tab2;
787+
788+CREATE EXTENSION test_ext_cine;
789+
790+\dx+ test_ext_cine
791+
792+ALTER EXTENSION test_ext_cine UPDATE TO '1.1';
793+
794+\dx+ test_ext_cine
795diff --git a/src/test/modules/test_extensions/test_ext_cine--1.0--1.1.sql b/src/test/modules/test_extensions/test_ext_cine--1.0--1.1.sql
796new file mode 100644
797index 0000000..6dadfd2
798--- /dev/null
799+++ b/src/test/modules/test_extensions/test_ext_cine--1.0--1.1.sql
800@@ -0,0 +1,26 @@
801+/* src/test/modules/test_extensions/test_ext_cine--1.0--1.1.sql */
802+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
803+\echo Use "ALTER EXTENSION test_ext_cine UPDATE TO '1.1'" to load this file. \quit
804+
805+--
806+-- These are the same commands as in the 1.0 script; we expect them
807+-- to do nothing.
808+--
809+
810+CREATE COLLATION IF NOT EXISTS ext_cine_coll
811+ ( LC_COLLATE = "POSIX", LC_CTYPE = "POSIX" );
812+
813+CREATE MATERIALIZED VIEW IF NOT EXISTS ext_cine_mv AS SELECT 42 AS f1;
814+
815+CREATE SERVER IF NOT EXISTS ext_cine_srv FOREIGN DATA WRAPPER ext_cine_fdw;
816+
817+CREATE SCHEMA IF NOT EXISTS ext_cine_schema;
818+
819+CREATE SEQUENCE IF NOT EXISTS ext_cine_seq;
820+
821+CREATE TABLE IF NOT EXISTS ext_cine_tab1 (x int);
822+
823+CREATE TABLE IF NOT EXISTS ext_cine_tab2 AS SELECT 42 AS y;
824+
825+-- just to verify the script ran
826+CREATE TABLE ext_cine_tab3 (z int);
827diff --git a/src/test/modules/test_extensions/test_ext_cine--1.0.sql b/src/test/modules/test_extensions/test_ext_cine--1.0.sql
828new file mode 100644
829index 0000000..01408ff
830--- /dev/null
831+++ b/src/test/modules/test_extensions/test_ext_cine--1.0.sql
832@@ -0,0 +1,25 @@
833+/* src/test/modules/test_extensions/test_ext_cine--1.0.sql */
834+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
835+\echo Use "CREATE EXTENSION test_ext_cine" to load this file. \quit
836+
837+--
838+-- CREATE IF NOT EXISTS is an entirely unsound thing for an extension
839+-- to be doing, but let's at least plug the major security hole in it.
840+--
841+
842+CREATE COLLATION IF NOT EXISTS ext_cine_coll
843+ ( LC_COLLATE = "POSIX", LC_CTYPE = "POSIX" );
844+
845+CREATE MATERIALIZED VIEW IF NOT EXISTS ext_cine_mv AS SELECT 42 AS f1;
846+
847+CREATE FOREIGN DATA WRAPPER ext_cine_fdw;
848+
849+CREATE SERVER IF NOT EXISTS ext_cine_srv FOREIGN DATA WRAPPER ext_cine_fdw;
850+
851+CREATE SCHEMA IF NOT EXISTS ext_cine_schema;
852+
853+CREATE SEQUENCE IF NOT EXISTS ext_cine_seq;
854+
855+CREATE TABLE IF NOT EXISTS ext_cine_tab1 (x int);
856+
857+CREATE TABLE IF NOT EXISTS ext_cine_tab2 AS SELECT 42 AS y;
858diff --git a/src/test/modules/test_extensions/test_ext_cine.control b/src/test/modules/test_extensions/test_ext_cine.control
859new file mode 100644
860index 0000000..ced713b
861--- /dev/null
862+++ b/src/test/modules/test_extensions/test_ext_cine.control
863@@ -0,0 +1,3 @@
864+comment = 'Test extension using CREATE IF NOT EXISTS'
865+default_version = '1.0'
866+relocatable = true
867diff --git a/src/test/modules/test_extensions/test_ext_cor--1.0.sql b/src/test/modules/test_extensions/test_ext_cor--1.0.sql
868new file mode 100644
869index 0000000..2e8d89c
870--- /dev/null
871+++ b/src/test/modules/test_extensions/test_ext_cor--1.0.sql
872@@ -0,0 +1,20 @@
873+/* src/test/modules/test_extensions/test_ext_cor--1.0.sql */
874+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
875+\echo Use "CREATE EXTENSION test_ext_cor" to load this file. \quit
876+
877+-- It's generally bad style to use CREATE OR REPLACE unnecessarily.
878+-- Test what happens if an extension does it anyway.
879+
880+CREATE OR REPLACE FUNCTION ext_cor_func() RETURNS text
881+ AS $$ SELECT 'ext_cor_func: from extension'::text $$ LANGUAGE sql;
882+
883+CREATE OR REPLACE VIEW ext_cor_view AS
884+ SELECT 'ext_cor_view: from extension'::text AS col;
885+
886+-- These are for testing replacement of a shell type/operator, which works
887+-- enough like an implicit OR REPLACE to be important to check.
888+
889+CREATE TYPE test_ext_type AS ENUM('x', 'y');
890+
891+CREATE OPERATOR <<@@ ( PROCEDURE = pt_contained_poly,
892+ LEFTARG = point, RIGHTARG = polygon );
893diff --git a/src/test/modules/test_extensions/test_ext_cor.control b/src/test/modules/test_extensions/test_ext_cor.control
894new file mode 100644
895index 0000000..0e972e5
896--- /dev/null
897+++ b/src/test/modules/test_extensions/test_ext_cor.control
898@@ -0,0 +1,3 @@
899+comment = 'Test extension using CREATE OR REPLACE'
900+default_version = '1.0'
901+relocatable = true
902--
9032.25.1
904
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-41862.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2022-41862.patch
deleted file mode 100644
index f4093f4ba..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-41862.patch
+++ /dev/null
@@ -1,48 +0,0 @@
1From 3f7342671341a7a137f2d8b06ab3461cdb0e1d88 Mon Sep 17 00:00:00 2001
2From: Michael Paquier <michael@paquier.xyz>
3Date: Mon, 6 Feb 2023 11:20:31 +0900
4Subject: [PATCH] Properly NULL-terminate GSS receive buffer on error packet
5 reception
6
7pqsecure_open_gss() includes a code path handling error messages with
8v2-style protocol messages coming from the server. The client-side
9buffer holding the error message does not force a NULL-termination, with
10the data of the server getting copied to the errorMessage of the
11connection. Hence, it would be possible for a server to send an
12unterminated string and copy arbitrary bytes in the buffer receiving the
13error message in the client, opening the door to a crash or even data
14exposure.
15
16As at this stage of the authentication process the exchange has not been
17completed yet, this could be abused by an attacker without Kerberos
18credentials. Clients that have a valid kerberos cache are vulnerable as
19libpq opportunistically requests for it except if gssencmode is
20disabled.
21
22Author: Jacob Champion
23Backpatch-through: 12
24Security: CVE-2022-41862
25
26CVE: CVE-2022-41862
27Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=3f7342671341a7a137f2d8b06ab3461cdb0e1d88]
28Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
29---
30 src/interfaces/libpq/fe-secure-gssapi.c | 2 ++
31 1 file changed, 2 insertions(+)
32
33diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c
34index 7b5e383..aef201b 100644
35--- a/src/interfaces/libpq/fe-secure-gssapi.c
36+++ b/src/interfaces/libpq/fe-secure-gssapi.c
37@@ -578,6 +578,8 @@ pqsecure_open_gss(PGconn *conn)
38
39 PqGSSRecvLength += ret;
40
41+ Assert(PqGSSRecvLength < PQ_GSS_RECV_BUFFER_SIZE);
42+ PqGSSRecvBuffer[PqGSSRecvLength] = '\0';
43 printfPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
44
45 return PGRES_POLLING_FAILED;
46--
472.25.1
48
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2454.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2454.patch
deleted file mode 100644
index eb0aff80d..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2454.patch
+++ /dev/null
@@ -1,235 +0,0 @@
1From 23cb8eaeb97df350273cb8902e55842a955339c8 Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Mon, 8 May 2023 06:14:07 -0700
4Subject: [PATCH] Replace last PushOverrideSearchPath() call with
5 set_config_option().
6
7The two methods don't cooperate, so set_config_option("search_path",
8...) has been ineffective under non-empty overrideStack. This defect
9enabled an attacker having database-level CREATE privilege to execute
10arbitrary code as the bootstrap superuser. While that particular attack
11requires v13+ for the trusted extension attribute, other attacks are
12feasible in all supported versions.
13
14Standardize on the combination of NewGUCNestLevel() and
15set_config_option("search_path", ...). It is newer than
16PushOverrideSearchPath(), more-prevalent, and has no known
17disadvantages. The "override" mechanism remains for now, for
18compatibility with out-of-tree code. Users should update such code,
19which likely suffers from the same sort of vulnerability closed here.
20Back-patch to v11 (all supported versions).
21
22Alexander Lakhin. Reported by Alexander Lakhin.
23
24Security: CVE-2023-2454
25
26Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=23cb8eaeb97df350273cb8902e55842a955339c8]
27CVE: CVE-2023-2454
28Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
29---
30 src/backend/catalog/namespace.c | 4 +++
31 src/backend/commands/schemacmds.c | 37 ++++++++++++++------
32 src/test/regress/expected/namespace.out | 45 +++++++++++++++++++++++++
33 src/test/regress/sql/namespace.sql | 24 +++++++++++++
34 4 files changed, 100 insertions(+), 10 deletions(-)
35
36diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
37index 48a7058..74a0536 100644
38--- a/src/backend/catalog/namespace.c
39+++ b/src/backend/catalog/namespace.c
40@@ -3456,6 +3456,10 @@ OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
41 /*
42 * PushOverrideSearchPath - temporarily override the search path
43 *
44+ * Do not use this function; almost any usage introduces a security
45+ * vulnerability. It exists for the benefit of legacy code running in
46+ * non-security-sensitive environments.
47+ *
48 * We allow nested overrides, hence the push/pop terminology. The GUC
49 * search_path variable is ignored while an override is active.
50 *
51diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
52index 6bc4edc..27b1241 100644
53--- a/src/backend/commands/schemacmds.c
54+++ b/src/backend/commands/schemacmds.c
55@@ -29,6 +29,7 @@
56 #include "commands/schemacmds.h"
57 #include "miscadmin.h"
58 #include "parser/parse_utilcmd.h"
59+#include "parser/scansup.h"
60 #include "tcop/utility.h"
61 #include "utils/acl.h"
62 #include "utils/builtins.h"
63@@ -53,14 +54,16 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
64 {
65 const char *schemaName = stmt->schemaname;
66 Oid namespaceId;
67- OverrideSearchPath *overridePath;
68 List *parsetree_list;
69 ListCell *parsetree_item;
70 Oid owner_uid;
71 Oid saved_uid;
72 int save_sec_context;
73+ int save_nestlevel;
74+ char *nsp = namespace_search_path;
75 AclResult aclresult;
76 ObjectAddress address;
77+ StringInfoData pathbuf;
78
79 GetUserIdAndSecContext(&saved_uid, &save_sec_context);
80
81@@ -153,14 +156,26 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
82 CommandCounterIncrement();
83
84 /*
85- * Temporarily make the new namespace be the front of the search path, as
86- * well as the default creation target namespace. This will be undone at
87- * the end of this routine, or upon error.
88+ * Prepend the new schema to the current search path.
89+ *
90+ * We use the equivalent of a function SET option to allow the setting to
91+ * persist for exactly the duration of the schema creation. guc.c also
92+ * takes care of undoing the setting on error.
93 */
94- overridePath = GetOverrideSearchPath(CurrentMemoryContext);
95- overridePath->schemas = lcons_oid(namespaceId, overridePath->schemas);
96- /* XXX should we clear overridePath->useTemp? */
97- PushOverrideSearchPath(overridePath);
98+ save_nestlevel = NewGUCNestLevel();
99+
100+ initStringInfo(&pathbuf);
101+ appendStringInfoString(&pathbuf, quote_identifier(schemaName));
102+
103+ while (scanner_isspace(*nsp))
104+ nsp++;
105+
106+ if (*nsp != '\0')
107+ appendStringInfo(&pathbuf, ", %s", nsp);
108+
109+ (void) set_config_option("search_path", pathbuf.data,
110+ PGC_USERSET, PGC_S_SESSION,
111+ GUC_ACTION_SAVE, true, 0, false);
112
113 /*
114 * Report the new schema to possibly interested event triggers. Note we
115@@ -213,8 +228,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
116 CommandCounterIncrement();
117 }
118
119- /* Reset search path to normal state */
120- PopOverrideSearchPath();
121+ /*
122+ * Restore the GUC variable search_path we set above.
123+ */
124+ AtEOXact_GUC(true, save_nestlevel);
125
126 /* Reset current user and security context */
127 SetUserIdAndSecContext(saved_uid, save_sec_context);
128diff --git a/src/test/regress/expected/namespace.out b/src/test/regress/expected/namespace.out
129index 2564d1b..a62fd8d 100644
130--- a/src/test/regress/expected/namespace.out
131+++ b/src/test/regress/expected/namespace.out
132@@ -1,6 +1,14 @@
133 --
134 -- Regression tests for schemas (namespaces)
135 --
136+-- set the whitespace-only search_path to test that the
137+-- GUC list syntax is preserved during a schema creation
138+SELECT pg_catalog.set_config('search_path', ' ', false);
139+ set_config
140+------------
141+
142+(1 row)
143+
144 CREATE SCHEMA test_ns_schema_1
145 CREATE UNIQUE INDEX abc_a_idx ON abc (a)
146 CREATE VIEW abc_view AS
147@@ -9,6 +17,43 @@ CREATE SCHEMA test_ns_schema_1
148 a serial,
149 b int UNIQUE
150 );
151+-- verify that the correct search_path restored on abort
152+SET search_path to public;
153+BEGIN;
154+SET search_path to public, test_ns_schema_1;
155+CREATE SCHEMA test_ns_schema_2
156+ CREATE VIEW abc_view AS SELECT c FROM abc;
157+ERROR: column "c" does not exist
158+LINE 2: CREATE VIEW abc_view AS SELECT c FROM abc;
159+ ^
160+COMMIT;
161+SHOW search_path;
162+ search_path
163+-------------
164+ public
165+(1 row)
166+
167+-- verify that the correct search_path preserved
168+-- after creating the schema and on commit
169+BEGIN;
170+SET search_path to public, test_ns_schema_1;
171+CREATE SCHEMA test_ns_schema_2
172+ CREATE VIEW abc_view AS SELECT a FROM abc;
173+SHOW search_path;
174+ search_path
175+--------------------------
176+ public, test_ns_schema_1
177+(1 row)
178+
179+COMMIT;
180+SHOW search_path;
181+ search_path
182+--------------------------
183+ public, test_ns_schema_1
184+(1 row)
185+
186+DROP SCHEMA test_ns_schema_2 CASCADE;
187+NOTICE: drop cascades to view test_ns_schema_2.abc_view
188 -- verify that the objects were created
189 SELECT COUNT(*) FROM pg_class WHERE relnamespace =
190 (SELECT oid FROM pg_namespace WHERE nspname = 'test_ns_schema_1');
191diff --git a/src/test/regress/sql/namespace.sql b/src/test/regress/sql/namespace.sql
192index 6b12c96..3474f5e 100644
193--- a/src/test/regress/sql/namespace.sql
194+++ b/src/test/regress/sql/namespace.sql
195@@ -2,6 +2,10 @@
196 -- Regression tests for schemas (namespaces)
197 --
198
199+-- set the whitespace-only search_path to test that the
200+-- GUC list syntax is preserved during a schema creation
201+SELECT pg_catalog.set_config('search_path', ' ', false);
202+
203 CREATE SCHEMA test_ns_schema_1
204 CREATE UNIQUE INDEX abc_a_idx ON abc (a)
205
206@@ -13,6 +17,26 @@ CREATE SCHEMA test_ns_schema_1
207 b int UNIQUE
208 );
209
210+-- verify that the correct search_path restored on abort
211+SET search_path to public;
212+BEGIN;
213+SET search_path to public, test_ns_schema_1;
214+CREATE SCHEMA test_ns_schema_2
215+ CREATE VIEW abc_view AS SELECT c FROM abc;
216+COMMIT;
217+SHOW search_path;
218+
219+-- verify that the correct search_path preserved
220+-- after creating the schema and on commit
221+BEGIN;
222+SET search_path to public, test_ns_schema_1;
223+CREATE SCHEMA test_ns_schema_2
224+ CREATE VIEW abc_view AS SELECT a FROM abc;
225+SHOW search_path;
226+COMMIT;
227+SHOW search_path;
228+DROP SCHEMA test_ns_schema_2 CASCADE;
229+
230 -- verify that the objects were created
231 SELECT COUNT(*) FROM pg_class WHERE relnamespace =
232 (SELECT oid FROM pg_namespace WHERE nspname = 'test_ns_schema_1');
233--
2342.25.1
235
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2455.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2455.patch
deleted file mode 100644
index b0bf2dbf2..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/CVE-2023-2455.patch
+++ /dev/null
@@ -1,118 +0,0 @@
1From 473626cf00babd829eb15c36b51dfb358d32bc95 Mon Sep 17 00:00:00 2001
2From: Tom Lane <tgl@sss.pgh.pa.us>
3Date: Mon, 8 May 2023 10:12:45 -0400
4Subject: [PATCH] Handle RLS dependencies in inlined set-returning functions
5 properly.
6
7If an SRF in the FROM clause references a table having row-level
8security policies, and we inline that SRF into the calling query,
9we neglected to mark the plan as potentially dependent on which
10role is executing it. This could lead to later executions in the
11same session returning or hiding rows that should have been hidden
12or returned instead.
13
14Our thanks to Wolfgang Walther for reporting this problem.
15
16Stephen Frost and Tom Lane
17
18Security: CVE-2023-2455
19
20Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=473626cf00babd829eb15c36b51dfb358d32bc95]
21CVE: CVE-2023-2455
22Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
23---
24 src/backend/optimizer/util/clauses.c | 7 ++++++
25 src/test/regress/expected/rowsecurity.out | 27 +++++++++++++++++++++++
26 src/test/regress/sql/rowsecurity.sql | 20 +++++++++++++++++
27 3 files changed, 54 insertions(+)
28
29diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
30index 946e232..b8e469f 100644
31--- a/src/backend/optimizer/util/clauses.c
32+++ b/src/backend/optimizer/util/clauses.c
33@@ -5142,6 +5142,13 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
34 */
35 record_plan_function_dependency(root, func_oid);
36
37+ /*
38+ * We must also notice if the inserted query adds a dependency on the
39+ * calling role due to RLS quals.
40+ */
41+ if (querytree->hasRowSecurity)
42+ root->glob->dependsOnRole = true;
43+
44 return querytree;
45
46 /* Here if func is not inlinable: release temp memory and return NULL */
47diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
48index 5116e23..26eecd0 100644
49--- a/src/test/regress/expected/rowsecurity.out
50+++ b/src/test/regress/expected/rowsecurity.out
51@@ -4001,6 +4001,33 @@ SELECT * FROM rls_tbl;
52
53 DROP TABLE rls_tbl;
54 RESET SESSION AUTHORIZATION;
55+-- CVE-2023-2455: inlining an SRF may introduce an RLS dependency
56+create table rls_t (c text);
57+insert into rls_t values ('invisible to bob');
58+alter table rls_t enable row level security;
59+grant select on rls_t to regress_rls_alice, regress_rls_bob;
60+create policy p1 on rls_t for select to regress_rls_alice using (true);
61+create policy p2 on rls_t for select to regress_rls_bob using (false);
62+create function rls_f () returns setof rls_t
63+ stable language sql
64+ as $$ select * from rls_t $$;
65+prepare q as select current_user, * from rls_f();
66+set role regress_rls_alice;
67+execute q;
68+ current_user | c
69+-------------------+------------------
70+ regress_rls_alice | invisible to bob
71+(1 row)
72+
73+set role regress_rls_bob;
74+execute q;
75+ current_user | c
76+--------------+---
77+(0 rows)
78+
79+RESET ROLE;
80+DROP FUNCTION rls_f();
81+DROP TABLE rls_t;
82 --
83 -- Clean up objects
84 --
85diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
86index 178eeb0..83d99e3 100644
87--- a/src/test/regress/sql/rowsecurity.sql
88+++ b/src/test/regress/sql/rowsecurity.sql
89@@ -1839,6 +1839,26 @@ SELECT * FROM rls_tbl;
90 DROP TABLE rls_tbl;
91 RESET SESSION AUTHORIZATION;
92
93+-- CVE-2023-2455: inlining an SRF may introduce an RLS dependency
94+create table rls_t (c text);
95+insert into rls_t values ('invisible to bob');
96+alter table rls_t enable row level security;
97+grant select on rls_t to regress_rls_alice, regress_rls_bob;
98+create policy p1 on rls_t for select to regress_rls_alice using (true);
99+create policy p2 on rls_t for select to regress_rls_bob using (false);
100+create function rls_f () returns setof rls_t
101+ stable language sql
102+ as $$ select * from rls_t $$;
103+prepare q as select current_user, * from rls_f();
104+set role regress_rls_alice;
105+execute q;
106+set role regress_rls_bob;
107+execute q;
108+
109+RESET ROLE;
110+DROP FUNCTION rls_f();
111+DROP TABLE rls_t;
112+
113 --
114 -- Clean up objects
115 --
116--
1172.25.1
118
diff --git a/meta-oe/recipes-dbs/postgresql/files/remove_duplicate.patch b/meta-oe/recipes-dbs/postgresql/files/remove_duplicate.patch
deleted file mode 100644
index 92a3dcc71..000000000
--- a/meta-oe/recipes-dbs/postgresql/files/remove_duplicate.patch
+++ /dev/null
@@ -1,38 +0,0 @@
1Remove duplicate code for riscv
2
3Upstream-Status: Pending
4Signed-off-by: Khem Raj <raj.khem@gmail.com>
5
6--- a/src/include/storage/s_lock.h
7+++ b/src/include/storage/s_lock.h
8@@ -341,30 +341,6 @@ tas(volatile slock_t *lock)
9 #endif /* HAVE_GCC__SYNC_INT32_TAS */
10 #endif /* __arm__ || __arm || __aarch64__ || __aarch64 || __riscv */
11
12-
13-/*
14- * RISC-V likewise uses __sync_lock_test_and_set(int *, int) if available.
15- */
16-#if defined(__riscv)
17-#ifdef HAVE_GCC__SYNC_INT32_TAS
18-#define HAS_TEST_AND_SET
19-
20-#define TAS(lock) tas(lock)
21-
22-typedef int slock_t;
23-
24-static __inline__ int
25-tas(volatile slock_t *lock)
26-{
27- return __sync_lock_test_and_set(lock, 1);
28-}
29-
30-#define S_UNLOCK(lock) __sync_lock_release(lock)
31-
32-#endif /* HAVE_GCC__SYNC_INT32_TAS */
33-#endif /* __riscv */
34-
35-
36 /* S/390 and S/390x Linux (32- and 64-bit zSeries) */
37 #if defined(__s390__) || defined(__s390x__)
38 #define HAS_TEST_AND_SET
diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_12.16.bb b/meta-oe/recipes-dbs/postgresql/postgresql_12.16.bb
new file mode 100644
index 000000000..134826220
--- /dev/null
+++ b/meta-oe/recipes-dbs/postgresql/postgresql_12.16.bb
@@ -0,0 +1,11 @@
1require postgresql.inc
2
3LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=c31f662bb2bfb3b4187fe9a53e0ffe7c"
4
5SRC_URI += "\
6 file://not-check-libperl.patch \
7 file://0001-Add-support-for-RISC-V.patch \
8 file://0001-Improve-reproducibility.patch \
9"
10
11SRC_URI[sha256sum] = "c5f1fff7a0f93e1ec3746417b0594290ece617b4995ed95b8d527af0ba0e38f3"
diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb b/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb
deleted file mode 100644
index a32701cd8..000000000
--- a/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb
+++ /dev/null
@@ -1,17 +0,0 @@
1require postgresql.inc
2
3LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=255f15687738db8068fbe9b938c90217"
4
5SRC_URI += "\
6 file://not-check-libperl.patch \
7 file://0001-Add-support-for-RISC-V.patch \
8 file://0001-Improve-reproducibility.patch \
9 file://remove_duplicate.patch \
10 file://CVE-2022-1552.patch \
11 file://CVE-2022-2625.patch \
12 file://CVE-2022-41862.patch \
13 file://CVE-2023-2454.patch \
14 file://CVE-2023-2455.patch \
15"
16
17SRC_URI[sha256sum] = "89fda2de33ed04a98548e43f3ee5f15b882be17505d631fe0dd1a540a2b56dce"