summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2022-10-17 09:48:50 +0530
committerArmin Kuster <akuster808@gmail.com>2022-12-11 16:01:15 -0500
commit7952135f650b4a754e2255f5aa03973a32344123 (patch)
treef8a3fc216daf661b7ef579e06c1280bada079fb7
parent1e9bf08cca883bbec7e6b9ffbe1fae9632dea412 (diff)
downloadmeta-openembedded-7952135f650b4a754e2255f5aa03973a32344123.tar.gz
postgresql: Fix CVE-2022-2625
Upstream-Status: Backport from https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=5579726bd60a6e7afb04a3548bced348cd5ffd89 Description: CVE-2022-2625 postgresql: Extension scripts replace objects not belonging to the extension. Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch904
-rw-r--r--meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb1
2 files changed, 905 insertions, 0 deletions
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch
new file mode 100644
index 0000000000..6417d8a2b7
--- /dev/null
+++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2022-2625.patch
@@ -0,0 +1,904 @@
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/postgresql_12.9.bb b/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb
index 1344d4eb00..860e821b20 100644
--- a/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb
+++ b/meta-oe/recipes-dbs/postgresql/postgresql_12.9.bb
@@ -8,6 +8,7 @@ SRC_URI += "\
8 file://0001-Improve-reproducibility.patch \ 8 file://0001-Improve-reproducibility.patch \
9 file://remove_duplicate.patch \ 9 file://remove_duplicate.patch \
10 file://CVE-2022-1552.patch \ 10 file://CVE-2022-1552.patch \
11 file://CVE-2022-2625.patch \
11" 12"
12 13
13SRC_URI[sha256sum] = "89fda2de33ed04a98548e43f3ee5f15b882be17505d631fe0dd1a540a2b56dce" 14SRC_URI[sha256sum] = "89fda2de33ed04a98548e43f3ee5f15b882be17505d631fe0dd1a540a2b56dce"