diff --git a/CVE-2018-16850.patch b/CVE-2018-16850.patch new file mode 100644 index 0000000000000000000000000000000000000000..cdbf59fc80332e35d5020cf395962c24d8a9c36f --- /dev/null +++ b/CVE-2018-16850.patch @@ -0,0 +1,44 @@ +From 21a134a26100b377191735ad49f996eac03047de Mon Sep 17 00:00:00 2001 +From: guiyao +Date: Thu, 17 Dec 2020 09:34:13 -0500 +Subject: [PATCH] backport to fix CVE-2018-16850 + +--- + src/backend/utils/adt/ruleutils.c | 10 ++++++---- + 1 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c +index 4c9a49c..0eea491 100644 +--- a/src/backend/utils/adt/ruleutils.c ++++ b/src/backend/utils/adt/ruleutils.c +@@ -952,22 +952,24 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) + value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable, + tgrel->rd_att, &isnull); + if (!isnull) +- tgoldtable = NameStr(*((NameData *) DatumGetPointer(value))); ++ tgoldtable = NameStr(*DatumGetName(value)); + else + tgoldtable = NULL; + value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable, + tgrel->rd_att, &isnull); + if (!isnull) +- tgnewtable = NameStr(*((NameData *) DatumGetPointer(value))); ++ tgnewtable = NameStr(*DatumGetName(value)); + else + tgnewtable = NULL; + if (tgoldtable != NULL || tgnewtable != NULL) + { + appendStringInfoString(&buf, "REFERENCING "); + if (tgoldtable != NULL) +- appendStringInfo(&buf, "OLD TABLE AS %s ", tgoldtable); ++ appendStringInfo(&buf, "OLD TABLE AS %s ", ++ quote_identifier(tgoldtable)); + if (tgnewtable != NULL) +- appendStringInfo(&buf, "NEW TABLE AS %s ", tgnewtable); ++ appendStringInfo(&buf, "NEW TABLE AS %s ", ++ quote_identifier(tgnewtable)); + } + + if (TRIGGER_FOR_ROW(trigrec->tgtype)) +-- +1.8.3.1 diff --git a/CVE-2019-10208.patch b/CVE-2019-10208.patch new file mode 100644 index 0000000000000000000000000000000000000000..d16ae170e88f08cad18ad3409e46a598f0d5c64f --- /dev/null +++ b/CVE-2019-10208.patch @@ -0,0 +1,224 @@ +From 2062007cbf7008de383c8f2f4a9ad466ea243acf Mon Sep 17 00:00:00 2001 +From: Noah Misch +Date: Mon, 5 Aug 2019 07:48:41 -0700 +Subject: [PATCH] Require the schema qualification in pg_temp.type_name(arg). + +Commit aa27977fe21a7dfa4da4376ad66ae37cb8f0d0b5 introduced this +restriction for pg_temp.function_name(arg); do likewise for types +created in temporary schemas. Programs that this breaks should add +"pg_temp." schema qualification or switch to arg::type_name syntax. +Back-patch to 9.4 (all supported versions). + +Reviewed by Tom Lane. Reported by Tom Lane. + +Security: CVE-2019-10208 +--- + src/backend/catalog/namespace.c | 15 ++++++++++++++- + src/backend/parser/parse_func.c | 7 ++++++- + src/backend/parser/parse_type.c | 24 +++++++++++++++++++++--- + src/backend/utils/adt/ruleutils.c | 8 ++++++++ + src/include/catalog/namespace.h | 1 + + src/include/parser/parse_type.h | 3 +++ + src/test/regress/expected/temp.out | 15 +++++++++++++++ + src/test/regress/sql/temp.sql | 12 ++++++++++++ + 8 files changed, 79 insertions(+), 5 deletions(-) + +diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c +index 5a737c8ab3..6b75ce10da 100644 +--- a/src/backend/catalog/namespace.c ++++ b/src/backend/catalog/namespace.c +@@ -739,13 +739,23 @@ RelationIsVisible(Oid relid) + + /* + * TypenameGetTypid ++ * Wrapper for binary compatibility. ++ */ ++Oid ++TypenameGetTypid(const char *typname) ++{ ++ return TypenameGetTypidExtended(typname, true); ++} ++ ++/* ++ * TypenameGetTypidExtended + * Try to resolve an unqualified datatype name. + * Returns OID if type found in search path, else InvalidOid. + * + * This is essentially the same as RelnameGetRelid. + */ + Oid +-TypenameGetTypid(const char *typname) ++TypenameGetTypidExtended(const char *typname, bool temp_ok) + { + Oid typid; + ListCell *l; +@@ -756,6 +766,9 @@ TypenameGetTypid(const char *typname) + { + Oid namespaceId = lfirst_oid(l); + ++ if (!temp_ok && namespaceId == myTempNamespace) ++ continue; /* do not look in temp namespace */ ++ + typid = GetSysCacheOid2(TYPENAMENSP, + PointerGetDatum(typname), + ObjectIdGetDatum(namespaceId)); +diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c +index 25ae4e5949..571d3d1b62 100644 +--- a/src/backend/parser/parse_func.c ++++ b/src/backend/parser/parse_func.c +@@ -1769,7 +1769,12 @@ FuncNameAsType(List *funcname) + Oid result; + Type typtup; + +- typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, false); ++ /* ++ * temp_ok=false protects the ++ * contract for writing SECURITY DEFINER functions safely. ++ */ ++ typtup = LookupTypeNameExtended(NULL, makeTypeNameFromNameList(funcname), ++ NULL, false, false); + if (typtup == NULL) + return InvalidOid; + +diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c +index d0b3fbeb57..1171381487 100644 +--- a/src/backend/parser/parse_type.c ++++ b/src/backend/parser/parse_type.c +@@ -33,6 +33,18 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, + + /* + * LookupTypeName ++ * Wrapper for typical case. ++ */ ++Type ++LookupTypeName(ParseState *pstate, const TypeName *typeName, ++ int32 *typmod_p, bool missing_ok) ++{ ++ return LookupTypeNameExtended(pstate, ++ typeName, typmod_p, true, missing_ok); ++} ++ ++/* ++ * LookupTypeNameExtended + * Given a TypeName object, lookup the pg_type syscache entry of the type. + * Returns NULL if no such type can be found. If the type is found, + * the typmod value represented in the TypeName struct is computed and +@@ -51,11 +63,17 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, + * found but is a shell, and there is typmod decoration, an error will be + * thrown --- this is intentional. + * ++ * If temp_ok is false, ignore types in the temporary namespace. Pass false ++ * when the caller will decide, using goodness of fit criteria, whether the ++ * typeName is actually a type or something else. If typeName always denotes ++ * a type (or denotes nothing), pass true. ++ * + * pstate is only used for error location info, and may be NULL. + */ + Type +-LookupTypeName(ParseState *pstate, const TypeName *typeName, +- int32 *typmod_p, bool missing_ok) ++LookupTypeNameExtended(ParseState *pstate, ++ const TypeName *typeName, int32 *typmod_p, ++ bool temp_ok, bool missing_ok) + { + Oid typoid; + HeapTuple tup; +@@ -172,7 +190,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, + else + { + /* Unqualified type name, so search the search path */ +- typoid = TypenameGetTypid(typname); ++ typoid = TypenameGetTypidExtended(typname, temp_ok); + } + + /* If an array reference, return the array type instead */ +diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c +index 3d1a701775..01789291bb 100644 +--- a/src/backend/utils/adt/ruleutils.c ++++ b/src/backend/utils/adt/ruleutils.c +@@ -9273,6 +9273,14 @@ get_coercion_expr(Node *arg, deparse_context *context, + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } ++ ++ /* ++ * Never emit resulttype(arg) functional notation. A pg_proc entry could ++ * take precedence, and a resulttype in pg_temp would require schema ++ * qualification that format_type_with_typemod() would usually omit. We've ++ * standardized on arg::resulttype, but CAST(arg AS resulttype) notation ++ * would work fine. ++ */ + appendStringInfo(buf, "::%s", + format_type_with_typemod(resulttype, resulttypmod)); + } +diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h +index f2ee935623..59c5ea5be2 100644 +--- a/src/include/catalog/namespace.h ++++ b/src/include/catalog/namespace.h +@@ -66,6 +66,7 @@ extern Oid RelnameGetRelid(const char *relname); + extern bool RelationIsVisible(Oid relid); + + extern Oid TypenameGetTypid(const char *typname); ++extern Oid TypenameGetTypidExtended(const char *typname, bool temp_ok); + extern bool TypeIsVisible(Oid typid); + + extern FuncCandidateList FuncnameGetCandidates(List *names, +diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h +index 7b843d0b9d..ac1bf1009e 100644 +--- a/src/include/parser/parse_type.h ++++ b/src/include/parser/parse_type.h +@@ -21,6 +21,9 @@ typedef HeapTuple Type; + + extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName, + int32 *typmod_p, bool missing_ok); ++extern Type LookupTypeNameExtended(ParseState *pstate, ++ const TypeName *typeName, int32 *typmod_p, ++ bool temp_ok, bool missing_ok); + extern Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, + bool missing_ok); + extern Type typenameType(ParseState *pstate, const TypeName *typeName, +diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out +index 7046deb0c8..aad562791e 100644 +--- a/src/test/regress/expected/temp.out ++++ b/src/test/regress/expected/temp.out +@@ -199,3 +199,18 @@ select pg_temp.whoami(); + (1 row) + + drop table public.whereami; ++-- types in temp schema ++set search_path = pg_temp, public; ++create domain pg_temp.nonempty as text check (value <> ''); ++-- function-syntax invocation of types matches rules for functions ++select nonempty(''); ++ERROR: function nonempty(unknown) does not exist ++LINE 1: select nonempty(''); ++ ^ ++HINT: No function matches the given name and argument types. You might need to add explicit type casts. ++select pg_temp.nonempty(''); ++ERROR: value for domain nonempty violates check constraint "nonempty_check" ++-- other syntax matches rules for tables ++select ''::nonempty; ++ERROR: value for domain nonempty violates check constraint "nonempty_check" ++reset search_path; +diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql +index d69a243fe7..c14c11444c 100644 +--- a/src/test/regress/sql/temp.sql ++++ b/src/test/regress/sql/temp.sql +@@ -151,3 +151,15 @@ select pg_temp.whoami(); + select pg_temp.whoami(); + + drop table public.whereami; ++ ++-- types in temp schema ++set search_path = pg_temp, public; ++create domain pg_temp.nonempty as text check (value <> ''); ++-- function-syntax invocation of types matches rules for functions ++select nonempty(''); ++select pg_temp.nonempty(''); ++-- other syntax matches rules for tables ++select ''::nonempty; ++ ++reset search_path; ++ +-- +2.11.0 diff --git a/postgresql.spec b/postgresql.spec index 76d52a26f31ed6d8e27ed80d413dee8293f935f1..a62065604608c7b78b4040ef42a550520ea761b5 100644 --- a/postgresql.spec +++ b/postgresql.spec @@ -4,7 +4,7 @@ Name: postgresql Version: 10.5 -Release: 6 +Release: 7 Summary: PostgreSQL client programs License: PostgreSQL Url: http://www.postgresql.org/ @@ -27,6 +27,8 @@ Patch0003: 0003-postgresql-man.patch Patch6000: 6000-CVE-2019-10164-1.patch Patch6001: 6001-CVE-2019-10164-2.patch +Patch6002: CVE-2019-10208.patch +Patch6003: CVE-2018-16850.patch BuildRequires: gcc perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk perl(ExtUtils::Embed) BuildRequires: perl-devel perl-generators readline-devel zlib-devel systemd systemd-devel @@ -188,6 +190,8 @@ PostgreSQL database management system, including regression tests and benchmarks %patch6000 -p1 %patch6001 -p1 +%patch6002 -p1 +%patch6003 -p1 cp -p %{SOURCE1} . tar xfj %{SOURCE3} @@ -565,5 +569,11 @@ make -C postgresql-setup-8.2 check %attr(-,postgres,postgres) %{_libdir}/pgsql/test %changelog +* Tue Dec 24 2019 fengbing - 10.5-7 +- Type:cves +- ID:CVE-2019-10208 CVE-2018-16850 +- SUG:restart +- DESC: fix CVE-2019-10208 CVE-2018-16850 + * Fri Nov 15 2019 yanzhihua - 10.5-6 - Package init