From af92d7f3090c44beac63bf1855ecf1cb87a07454 Mon Sep 17 00:00:00 2001 From: s17723959267 Date: Thu, 10 Sep 2020 14:52:22 +0800 Subject: [PATCH 01/10] l --- 0009-CVE-2020-14349-1.patch | 96 +++ 0010-CVE-2020-14349-2.patch | 54 ++ 0011-CVE-2020-14350.patch | 1199 +++++++++++++++++++++++++++++++++++ 3 files changed, 1349 insertions(+) create mode 100644 0009-CVE-2020-14349-1.patch create mode 100644 0010-CVE-2020-14349-2.patch create mode 100644 0011-CVE-2020-14350.patch diff --git a/0009-CVE-2020-14349-1.patch b/0009-CVE-2020-14349-1.patch new file mode 100644 index 0000000..42ef138 --- /dev/null +++ b/0009-CVE-2020-14349-1.patch @@ -0,0 +1,96 @@ +From 11da97024abbe76b8c81e3f2375b2a62e9717c67 Mon Sep 17 00:00:00 2001 +From: Noah Misch +Date: Mon, 10 Aug 2020 09:22:54 -0700 +Subject: [PATCH] Empty search_path in logical replication apply worker and + walsender. + +This is like CVE-2018-1058 commit +582edc369cdbd348d68441fc50fa26a84afd0c1a. Today, a malicious user of a +publisher or subscriber database can invoke arbitrary SQL functions +under an identity running replication, often a superuser. This fix may +cause "does not exist" or "no schema has been selected to create in" +errors in a replication process. After upgrading, consider watching +server logs for these errors. Objects accruing schema qualification in +the wake of the earlier commit are unlikely to need further correction. +Back-patch to v10, which introduced logical replication. + +Security: CVE-2020-14349 +reason: fix CVE-2020-14349 +https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=11da97024abbe76b8c81e3f2375b2a62e9717c67 + +Signed-off-by: Noah Misch +--- + .../libpqwalreceiver/libpqwalreceiver.c | 17 +++++++++++++++++ + src/backend/replication/logical/worker.c | 6 ++++++ + src/test/subscription/t/001_rep_changes.pl | 4 ++++ + 3 files changed, 27 insertions(+) + +diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +index 37b481c..564e6d3 100644 +--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c ++++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +@@ -23,6 +23,7 @@ + #include "pqexpbuffer.h" + #include "access/xlog.h" + #include "catalog/pg_type.h" ++#include "fe_utils/connect.h" + #include "funcapi.h" + #include "mb/pg_wchar.h" + #include "miscadmin.h" +@@ -210,6 +211,22 @@ libpqrcv_connect(const char *conninfo, bool logical, const char *appname, + return NULL; + } + ++ if (logical) ++ { ++ PGresult *res; ++ ++ res = libpqrcv_PQexec(conn->streamConn, ++ ALWAYS_SECURE_SEARCH_PATH_SQL); ++ if (PQresultStatus(res) != PGRES_TUPLES_OK) ++ { ++ PQclear(res); ++ ereport(ERROR, ++ (errmsg("could not clear search path: %s", ++ pchomp(PQerrorMessage(conn->streamConn))))); ++ } ++ PQclear(res); ++ } ++ + conn->logical = logical; + + return conn; +diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c +index bd60094..07b765a 100644 +--- a/src/backend/replication/logical/worker.c ++++ b/src/backend/replication/logical/worker.c +@@ -1548,6 +1548,12 @@ ApplyWorkerMain(Datum main_arg) + BackgroundWorkerInitializeConnectionByOid(MyLogicalRepWorker->dbid, + MyLogicalRepWorker->userid); + ++ /* ++ * Set always-secure search path, so malicious users can't redirect user ++ * code (e.g. pg_index.indexprs). ++ */ ++ SetConfigOption("search_path", "", PGC_SUSET, PGC_S_OVERRIDE); ++ + /* Load the subscription into persistent memory context. */ + ApplyContext = AllocSetContextCreate(TopMemoryContext, + "ApplyContext", +diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl +index 0136c79..cda275b 100644 +--- a/src/test/subscription/t/001_rep_changes.pl ++++ b/src/test/subscription/t/001_rep_changes.pl +@@ -16,6 +16,10 @@ $node_subscriber->init(allows_streaming => 'logical'); + $node_subscriber->start; + + # Create some preexisting content on publisher ++$node_publisher->safe_psql( ++ 'postgres', ++ "CREATE FUNCTION public.pg_get_replica_identity_index(int) ++ RETURNS regclass LANGUAGE sql AS 'SELECT 1/0'"); # shall not call + $node_publisher->safe_psql('postgres', + "CREATE TABLE tab_notrep AS SELECT generate_series(1,10) AS a"); + $node_publisher->safe_psql('postgres', +-- +2.23.0 \ No newline at end of file diff --git a/0010-CVE-2020-14349-2.patch b/0010-CVE-2020-14349-2.patch new file mode 100644 index 0000000..0b88b57 --- /dev/null +++ b/0010-CVE-2020-14349-2.patch @@ -0,0 +1,54 @@ +From cec57b1a0fbcd3833086ba686897c5883e0a2afc Mon Sep 17 00:00:00 2001 +From: Noah Misch +Date: Mon, 10 Aug 2020 09:22:54 -0700 +Subject: [PATCH] Document clashes between logical replication and untrusted +users. + +Back-patch to v10, which introduced logical replication. + +Security: CVE-2020-14349 +reason: fix CVE-2020-14349 +https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=cec57b1a0fbcd3833086ba686897c5883e0a2afc + +Signed-off-by: Noah Misch +--- + doc/src/sgml/logical-replication.sgml | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml +index 41770a4..f5086b2 100644 +--- a/doc/src/sgml/logical-replication.sgml ++++ b/doc/src/sgml/logical-replication.sgml +@@ -490,11 +490,27 @@ + + Security + ++ ++ A user able to modify the schema of subscriber-side tables can execute ++ arbitrary code as a superuser. Limit ownership ++ and TRIGGER privilege on such tables to roles that ++ superusers trust. Moreover, if untrusted users can create tables, use only ++ publications that list tables explicitly. That is to say, create a ++ subscription FOR ALL TABLES only when superusers trust ++ every user permitted to create a non-temp table on the publisher or the ++ subscriber. ++ ++ + + The role used for the replication connection must have +- the REPLICATION attribute (or be a superuser). Access for the role must be +- configured in pg_hba.conf and it must have the +- LOGIN attribute. ++ the REPLICATION attribute (or be a superuser). If the ++ role lacks SUPERUSER and BYPASSRLS, ++ publisher row security policies can execute. If the role does not trust ++ all table owners, include options=-crow_security=off in ++ the connection string; if a table owner then adds a row security policy, ++ that setting will cause replication to halt rather than execute the policy. ++ Access for the role must be configured in pg_hba.conf ++ and it must have the LOGIN attribute. + + + +-- +2.23.0 \ No newline at end of file diff --git a/0011-CVE-2020-14350.patch b/0011-CVE-2020-14350.patch new file mode 100644 index 0000000..6140806 --- /dev/null +++ b/0011-CVE-2020-14350.patch @@ -0,0 +1,1199 @@ +From f43931e9bc3431026092b8d21f5b50b9b4896384 Mon Sep 17 00:00:00 2001 +From: Tom Lane +Date: Mon, 10 Aug 2020 10:44:42 -0400 +Subject: [PATCH] Make contrib modules' installation scripts more secure. + +Hostile objects located within the installation-time search_path could +capture references in an extension's installation or upgrade script. +If the extension is being installed with superuser privileges, this +opens the door to privilege escalation. While such hazards have existed +all along, their urgency increases with the v13 "trusted extensions" +feature, because that lets a non-superuser control the installation path +for a superuser-privileged script. Therefore, make a number of changes +to make such situations more secure: + +* Tweak the construction of the installation-time search_path to ensure +that references to objects in pg_catalog can't be subverted; and +explicitly add pg_temp to the end of the path to prevent attacks using +temporary objects. + +* Disable check_function_bodies within installation/upgrade scripts, +so that any security gaps in SQL-language or PL-language function bodies +cannot create a risk of unwanted installation-time code execution. + +* Adjust lookup of type input/receive functions and join estimator +functions to complain if there are multiple candidate functions. This +prevents capture of references to functions whose signature is not the +first one checked; and it's arguably more user-friendly anyway. + +* Modify various contrib upgrade scripts to ensure that catalog +modification queries are executed with secure search paths. (These +are in-place modifications with no extension version changes, since +it is the update process itself that is at issue, not the end result.) + +Extensions that depend on other extensions cannot be made fully secure +by these methods alone; therefore, revert the "trusted" marking that +commit eb67623c9 applied to earthdistance and hstore_plperl, pending +some better solution to that set of issues. + +Also add documentation around these issues, to help extension authors +write secure installation scripts. + +Patch by me, following an observation by Andres Freund; thanks +to Noah Misch for review. + +Security: CVE-2020-14350 +reason: fix CVE-2020-14349 +https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=7eeb1d9861b0a3f453f8b31c7648396cdd7f1e59 + +Signed-off-by: Tom Lane +--- + contrib/btree_gist/btree_gist--1.1--1.2.sql | 56 +++-- + contrib/citext/citext--1.1--1.2.sql | 26 ++- + contrib/citext/citext--1.2--1.3.sql | 18 +- + contrib/cube/cube--1.1--1.2.sql | 25 +- + contrib/earthdistance/earthdistance--1.1.sql | 2 +- + contrib/hstore/hstore--1.1--1.2.sql | 9 +- + contrib/hstore/hstore--1.3--1.4.sql | 35 ++- + contrib/intagg/intagg--1.0--1.1.sql | 14 +- + contrib/intarray/intarray--1.1--1.2.sql | 27 ++- + contrib/ltree/ltree--1.0--1.1.sql | 37 ++- + contrib/pg_trgm/pg_trgm--1.2--1.3.sql | 25 +- + contrib/seg/seg--1.0--1.1.sql | 23 +- + doc/src/sgml/earthdistance.sgml | 27 ++- + doc/src/sgml/extend.sgml | 228 ++++++++++++++++--- + doc/src/sgml/hstore.sgml | 9 + + doc/src/sgml/ltree.sgml | 9 + + doc/src/sgml/ref/create_extension.sgml | 34 ++- + src/backend/commands/extension.c | 21 +- + src/backend/commands/operatorcmds.c | 26 ++- + src/backend/commands/typecmds.c | 92 +- + 20 files changed, 533 insertions(+), 127 deletions(-) + +diff --git a/contrib/btree_gist/btree_gist--1.1--1.2.sql b/contrib/btree_gist/btree_gist--1.1--1.2.sql +index 8487f9b..d5a8c6c 100644 +--- a/contrib/btree_gist/btree_gist--1.1--1.2.sql ++++ b/contrib/btree_gist/btree_gist--1.1--1.2.sql +@@ -8,56 +8,72 @@ + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. + ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); ++ + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types + ('gbt_oid_distance(internal,oid,int2,oid)', '{internal,oid,int2,oid,internal}'), + ('gbt_oid_union(bytea,internal)', '{internal,internal}'), +-('gbt_oid_same(internal,internal,internal)', '{gbtreekey8,gbtreekey8,internal}'), ++('gbt_oid_same(internal,internal,internal)', '{SCH.gbtreekey8,SCH.gbtreekey8,internal}'), + ('gbt_int2_distance(internal,int2,int2,oid)', '{internal,int2,int2,oid,internal}'), + ('gbt_int2_union(bytea,internal)', '{internal,internal}'), +-('gbt_int2_same(internal,internal,internal)', '{gbtreekey4,gbtreekey4,internal}'), ++('gbt_int2_same(internal,internal,internal)', '{SCH.gbtreekey4,SCH.gbtreekey4,internal}'), + ('gbt_int4_distance(internal,int4,int2,oid)', '{internal,int4,int2,oid,internal}'), + ('gbt_int4_union(bytea,internal)', '{internal,internal}'), +-('gbt_int4_same(internal,internal,internal)', '{gbtreekey8,gbtreekey8,internal}'), ++('gbt_int4_same(internal,internal,internal)', '{SCH.gbtreekey8,SCH.gbtreekey8,internal}'), + ('gbt_int8_distance(internal,int8,int2,oid)', '{internal,int8,int2,oid,internal}'), + ('gbt_int8_union(bytea,internal)', '{internal,internal}'), +-('gbt_int8_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_int8_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_float4_distance(internal,float4,int2,oid)', '{internal,float4,int2,oid,internal}'), + ('gbt_float4_union(bytea,internal)', '{internal,internal}'), +-('gbt_float4_same(internal,internal,internal)', '{gbtreekey8,gbtreekey8,internal}'), ++('gbt_float4_same(internal,internal,internal)', '{SCH.gbtreekey8,SCH.gbtreekey8,internal}'), + ('gbt_float8_distance(internal,float8,int2,oid)', '{internal,float8,int2,oid,internal}'), + ('gbt_float8_union(bytea,internal)', '{internal,internal}'), +-('gbt_float8_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_float8_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_ts_distance(internal,timestamp,int2,oid)', '{internal,timestamp,int2,oid,internal}'), + ('gbt_tstz_distance(internal,timestamptz,int2,oid)', '{internal,timestamptz,int2,oid,internal}'), + ('gbt_ts_union(bytea,internal)', '{internal,internal}'), +-('gbt_ts_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_ts_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_time_distance(internal,time,int2,oid)', '{internal,time,int2,oid,internal}'), + ('gbt_time_union(bytea,internal)', '{internal,internal}'), +-('gbt_time_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_time_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_date_distance(internal,date,int2,oid)', '{internal,date,int2,oid,internal}'), + ('gbt_date_union(bytea,internal)', '{internal,internal}'), +-('gbt_date_same(internal,internal,internal)', '{gbtreekey8,gbtreekey8,internal}'), ++('gbt_date_same(internal,internal,internal)', '{SCH.gbtreekey8,SCH.gbtreekey8,internal}'), + ('gbt_intv_distance(internal,interval,int2,oid)', '{internal,interval,int2,oid,internal}'), + ('gbt_intv_union(bytea,internal)', '{internal,internal}'), +-('gbt_intv_same(internal,internal,internal)', '{gbtreekey32,gbtreekey32,internal}'), ++('gbt_intv_same(internal,internal,internal)', '{SCH.gbtreekey32,SCH.gbtreekey32,internal}'), + ('gbt_cash_distance(internal,money,int2,oid)', '{internal,money,int2,oid,internal}'), + ('gbt_cash_union(bytea,internal)', '{internal,internal}'), +-('gbt_cash_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_cash_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_macad_union(bytea,internal)', '{internal,internal}'), +-('gbt_macad_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}'), ++('gbt_macad_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}'), + ('gbt_text_union(bytea,internal)', '{internal,internal}'), +-('gbt_text_same(internal,internal,internal)', '{gbtreekey_var,gbtreekey_var,internal}'), ++('gbt_text_same(internal,internal,internal)', '{SCH.gbtreekey_var,SCH.gbtreekey_var,internal}'), + ('gbt_bytea_union(bytea,internal)', '{internal,internal}'), +-('gbt_bytea_same(internal,internal,internal)', '{gbtreekey_var,gbtreekey_var,internal}'), ++('gbt_bytea_same(internal,internal,internal)', '{SCH.gbtreekey_var,SCH.gbtreekey_var,internal}'), + ('gbt_numeric_union(bytea,internal)', '{internal,internal}'), +-('gbt_numeric_same(internal,internal,internal)', '{gbtreekey_var,gbtreekey_var,internal}'), ++('gbt_numeric_same(internal,internal,internal)', '{SCH.gbtreekey_var,SCH.gbtreekey_var,internal}'), + ('gbt_bit_union(bytea,internal)', '{internal,internal}'), +-('gbt_bit_same(internal,internal,internal)', '{gbtreekey_var,gbtreekey_var,internal}'), ++('gbt_bit_same(internal,internal,internal)', '{SCH.gbtreekey_var,SCH.gbtreekey_var,internal}'), + ('gbt_inet_union(bytea,internal)', '{internal,internal}'), +-('gbt_inet_same(internal,internal,internal)', '{gbtreekey16,gbtreekey16,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++('gbt_inet_same(internal,internal,internal)', '{SCH.gbtreekey16,SCH.gbtreekey16,internal}') ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; +diff --git a/contrib/citext/citext--1.1--1.2.sql b/contrib/citext/citext--1.1--1.2.sql +index 4f0e4bc..a8bba86 100644 +--- a/contrib/citext/citext--1.1--1.2.sql ++++ b/contrib/citext/citext--1.1--1.2.sql +@@ -41,14 +41,28 @@ ALTER FUNCTION replace(citext, citext, citext) PARALLEL SAFE; + ALTER FUNCTION split_part(citext, citext, int) PARALLEL SAFE; + ALTER FUNCTION translate(citext, citext, text) PARALLEL SAFE; + ++-- We have to update aggregates the hard way for lack of ALTER support ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); ++ + UPDATE pg_proc SET proparallel = 's' +-WHERE oid = 'min(citext)'::pg_catalog.regprocedure; ++WHERE oid = (my_schema || '.min(' || my_schema || '.citext)')::pg_catalog.regprocedure; + + UPDATE pg_proc SET proparallel = 's' +-WHERE oid = 'max(citext)'::pg_catalog.regprocedure; ++WHERE oid = (my_schema || '.max(' || my_schema || '.citext)')::pg_catalog.regprocedure; ++ ++UPDATE pg_aggregate SET aggcombinefn = (my_schema || '.citext_smaller')::regproc ++WHERE aggfnoid = (my_schema || '.max(' || my_schema || '.citext)')::pg_catalog.regprocedure; + +-UPDATE pg_aggregate SET aggcombinefn = 'citext_smaller' +-WHERE aggfnoid = 'max(citext)'::pg_catalog.regprocedure; ++UPDATE pg_aggregate SET aggcombinefn = (my_schema || '.citext_larger')::regproc ++WHERE aggfnoid = (my_schema || '.max(' || my_schema || '.citext)')::pg_catalog.regprocedure; + +-UPDATE pg_aggregate SET aggcombinefn = 'citext_larger' +-WHERE aggfnoid = 'max(citext)'::pg_catalog.regprocedure; ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; +diff --git a/contrib/citext/citext--1.2--1.3.sql b/contrib/citext/citext--1.2--1.3.sql +index 4ab8679..24a7145 100644 +--- a/contrib/citext/citext--1.2--1.3.sql ++++ b/contrib/citext/citext--1.2--1.3.sql +@@ -3,5 +3,19 @@ + -- complain if script is sourced in psql, rather than via ALTER EXTENSION + \echo Use "ALTER EXTENSION citext UPDATE TO '1.3'" to load this file. \quit + +-UPDATE pg_aggregate SET aggcombinefn = 'citext_smaller' +-WHERE aggfnoid = 'min(citext)'::pg_catalog.regprocedure; ++-- We have to update aggregates the hard way for lack of ALTER support ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); ++ ++UPDATE pg_aggregate SET aggcombinefn = (my_schema || '.citext_smaller')::regproc ++WHERE aggfnoid = (my_schema || '.min(' || my_schema || '.citext)')::pg_catalog.regprocedure; ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; +diff --git a/contrib/cube/cube--1.1--1.2.sql b/contrib/cube/cube--1.1--1.2.sql +index 64a531e..76aba23 100644 +--- a/contrib/cube/cube--1.1--1.2.sql ++++ b/contrib/cube/cube--1.1--1.2.sql +@@ -7,16 +7,31 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types +-('g_cube_consistent(internal,cube,int4,oid,internal)', '{internal,cube,int2,oid,internal}'), +-('g_cube_distance(internal,cube,smallint,oid)', '{internal,cube,smallint,oid,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types ++('g_cube_consistent(internal,SCH.cube,int4,oid,internal)', '{internal,SCH.cube,int2,oid,internal}'), ++('g_cube_distance(internal,SCH.cube,smallint,oid)', '{internal,SCH.cube,smallint,oid,internal}') ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION cube_in(cstring) PARALLEL SAFE; + ALTER FUNCTION cube(float8[], float8[]) PARALLEL SAFE; +diff --git a/contrib/earthdistance/earthdistance--1.1.sql b/contrib/earthdistance/earthdistance--1.1.sql +index 9136a54..9ef20ab 100644 +--- a/contrib/earthdistance/earthdistance--1.1.sql ++++ b/contrib/earthdistance/earthdistance--1.1.sql +@@ -31,7 +31,7 @@ CREATE DOMAIN earth AS cube + CONSTRAINT not_point check(cube_is_point(value)) + CONSTRAINT not_3d check(cube_dim(value) <= 3) + CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) / +- earth() - 1) < '10e-7'::float8); ++ earth() - '1'::float8) < '10e-7'::float8); + + CREATE FUNCTION sec_to_gc(float8) + RETURNS float8 +diff --git a/contrib/hstore/hstore--1.1--1.2.sql b/contrib/hstore/hstore--1.1--1.2.sql +index a868ffe..cc69fc7 100644 +--- a/contrib/hstore/hstore--1.1--1.2.sql ++++ b/contrib/hstore/hstore--1.1--1.2.sql +@@ -9,10 +9,13 @@ + -- dependent on the extension. + + DO LANGUAGE plpgsql +- + $$ +- ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); + BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + PERFORM 1 + FROM pg_proc p +@@ -27,6 +30,7 @@ BEGIN + + IF NOT FOUND + THEN ++ PERFORM pg_catalog.set_config('search_path', old_path, true); + + CREATE FUNCTION hstore_to_json(hstore) + RETURNS json +@@ -43,6 +47,7 @@ BEGIN + + END IF; + ++PERFORM pg_catalog.set_config('search_path', old_path, true); + END; + + $$; +diff --git a/contrib/hstore/hstore--1.3--1.4.sql b/contrib/hstore/hstore--1.3--1.4.sql +index d68956b..53f26f9 100644 +--- a/contrib/hstore/hstore--1.3--1.4.sql ++++ b/contrib/hstore/hstore--1.3--1.4.sql +@@ -7,23 +7,38 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types +-('ghstore_same(internal,internal,internal)', '{ghstore,ghstore,internal}'), +-('ghstore_consistent(internal,internal,int4,oid,internal)', '{internal,hstore,int2,oid,internal}'), +-('gin_extract_hstore(internal,internal)', '{hstore,internal}'), +-('gin_extract_hstore_query(internal,internal,int2,internal,internal)', '{hstore,internal,int2,internal,internal}'), +-('gin_consistent_hstore(internal,int2,internal,int4,internal,internal)', '{internal,int2,hstore,int4,internal,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types ++('ghstore_same(internal,internal,internal)', '{SCH.ghstore,SCH.ghstore,internal}'), ++('ghstore_consistent(internal,internal,int4,oid,internal)', '{internal,SCH.hstore,int2,oid,internal}'), ++('gin_extract_hstore(internal,internal)', '{SCH.hstore,internal}'), ++('gin_extract_hstore_query(internal,internal,int2,internal,internal)', '{SCH.hstore,internal,int2,internal,internal}'), ++('gin_consistent_hstore(internal,int2,internal,int4,internal,internal)', '{internal,int2,SCH.hstore,int4,internal,internal}') ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); + + UPDATE pg_catalog.pg_proc SET +- prorettype = 'ghstore'::pg_catalog.regtype +-WHERE oid = pg_catalog.to_regprocedure('ghstore_union(internal,internal)'); ++ prorettype = (my_schema || '.ghstore')::pg_catalog.regtype ++WHERE oid = pg_catalog.to_regprocedure((my_schema || '.ghstore_union(internal,internal)')); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION hstore_in(cstring) PARALLEL SAFE; + ALTER FUNCTION hstore_out(hstore) PARALLEL SAFE; +diff --git a/contrib/intagg/intagg--1.0--1.1.sql b/contrib/intagg/intagg--1.0--1.1.sql +index b2a2820..c0cc17a 100644 +--- a/contrib/intagg/intagg--1.0--1.1.sql ++++ b/contrib/intagg/intagg--1.0--1.1.sql +@@ -6,6 +6,18 @@ + ALTER FUNCTION int_agg_state(internal, int4) PARALLEL SAFE; + ALTER FUNCTION int_agg_final_array(internal) PARALLEL SAFE; + ALTER FUNCTION int_array_enum(int4[]) PARALLEL SAFE; ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_proc SET proparallel = 's' +-WHERE oid = 'int_array_aggregate(int4)'::pg_catalog.regprocedure; ++WHERE oid = (my_schema || '.int_array_aggregate(int4)')::pg_catalog.regprocedure; ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; +diff --git a/contrib/intarray/intarray--1.1--1.2.sql b/contrib/intarray/intarray--1.1--1.2.sql +index 468f245..919340e 100644 +--- a/contrib/intarray/intarray--1.1--1.2.sql ++++ b/contrib/intarray/intarray--1.1--1.2.sql +@@ -7,23 +7,38 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types + ('g_int_consistent(internal,_int4,int4,oid,internal)', '{internal,_int4,int2,oid,internal}'), + ('g_intbig_consistent(internal,internal,int4,oid,internal)', '{internal,_int4,int2,oid,internal}'), +-('g_intbig_same(internal,internal,internal)', '{intbig_gkey,intbig_gkey,internal}'), ++('g_intbig_same(internal,internal,internal)', '{SCH.intbig_gkey,SCH.intbig_gkey,internal}'), + ('ginint4_queryextract(internal,internal,int2,internal,internal,internal,internal)', '{_int4,internal,int2,internal,internal,internal,internal}'), + ('ginint4_consistent(internal,int2,internal,int4,internal,internal,internal,internal)', '{internal,int2,_int4,int4,internal,internal,internal,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); + + UPDATE pg_catalog.pg_proc SET +- prorettype = 'intbig_gkey'::pg_catalog.regtype +-WHERE oid = pg_catalog.to_regprocedure('g_intbig_union(internal,internal)'); ++ prorettype = (my_schema || '.intbig_gkey')::pg_catalog.regtype ++WHERE oid = pg_catalog.to_regprocedure(my_schema || '.g_intbig_union(internal,internal)'); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION bqarr_in(cstring) PARALLEL SAFE; + ALTER FUNCTION bqarr_out(query_int) PARALLEL SAFE; +diff --git a/contrib/ltree/ltree--1.0--1.1.sql b/contrib/ltree/ltree--1.0--1.1.sql +index 155751a..2ce6f5a 100644 +--- a/contrib/ltree/ltree--1.0--1.1.sql ++++ b/contrib/ltree/ltree--1.0--1.1.sql +@@ -7,26 +7,41 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types +-('ltree_consistent(internal,internal,int2,oid,internal)', '{internal,ltree,int2,oid,internal}'), +-('ltree_same(internal,internal,internal)', '{ltree_gist,ltree_gist,internal}'), +-('_ltree_consistent(internal,internal,int2,oid,internal)', '{internal,_ltree,int2,oid,internal}'), +-('_ltree_same(internal,internal,internal)', '{ltree_gist,ltree_gist,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types ++('ltree_consistent(internal,internal,int2,oid,internal)', '{internal,SCH.ltree,int2,oid,internal}'), ++('ltree_same(internal,internal,internal)', '{SCH.ltree_gist,SCH.ltree_gist,internal}'), ++('_ltree_consistent(internal,internal,int2,oid,internal)', '{internal,SCH._ltree,int2,oid,internal}'), ++('_ltree_same(internal,internal,internal)', '{SCH.ltree_gist,SCH.ltree_gist,internal}') ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); + + UPDATE pg_catalog.pg_proc SET +- prorettype = 'ltree_gist'::pg_catalog.regtype +-WHERE oid = pg_catalog.to_regprocedure('ltree_union(internal,internal)'); ++ prorettype = (my_schema || '.ltree_gist')::pg_catalog.regtype ++WHERE oid = pg_catalog.to_regprocedure(my_schema || '.ltree_union(internal,internal)'); + + UPDATE pg_catalog.pg_proc SET +- prorettype = 'ltree_gist'::pg_catalog.regtype +-WHERE oid = pg_catalog.to_regprocedure('_ltree_union(internal,internal)'); ++ prorettype = (my_schema || '.ltree_gist')::pg_catalog.regtype ++WHERE oid = pg_catalog.to_regprocedure(my_schema || '._ltree_union(internal,internal)'); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION ltree_in(cstring) PARALLEL SAFE; + ALTER FUNCTION ltree_out(ltree) PARALLEL SAFE; +diff --git a/contrib/pg_trgm/pg_trgm--1.2--1.3.sql b/contrib/pg_trgm/pg_trgm--1.2--1.3.sql +index b082dcd..8dc772c 100644 +--- a/contrib/pg_trgm/pg_trgm--1.2--1.3.sql ++++ b/contrib/pg_trgm/pg_trgm--1.2--1.3.sql +@@ -7,21 +7,36 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types + ('gtrgm_consistent(internal,text,int4,oid,internal)', '{internal,text,int2,oid,internal}'), + ('gtrgm_distance(internal,text,int4,oid)', '{internal,text,int2,oid,internal}'), + ('gtrgm_union(bytea,internal)', '{internal,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); + + UPDATE pg_catalog.pg_proc SET +- prorettype = 'gtrgm'::pg_catalog.regtype +-WHERE oid = pg_catalog.to_regprocedure('gtrgm_union(internal,internal)'); ++ prorettype = (my_schema || '.gtrgm')::pg_catalog.regtype ++WHERE oid = pg_catalog.to_regprocedure(my_schema || '.gtrgm_union(internal,internal)'); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION set_limit(float4) PARALLEL UNSAFE; + ALTER FUNCTION show_limit() PARALLEL SAFE; +diff --git a/contrib/seg/seg--1.0--1.1.sql b/contrib/seg/seg--1.0--1.1.sql +index 2dcd4d4..ae6cb2f 100644 +--- a/contrib/seg/seg--1.0--1.1.sql ++++ b/contrib/seg/seg--1.0--1.1.sql +@@ -7,15 +7,30 @@ + -- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, + -- wherein the signatures have been updated already. In that case to_regprocedure() will + -- return NULL and no updates will happen. ++DO LANGUAGE plpgsql ++$$ ++DECLARE ++ my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); ++ old_path pg_catalog.text := pg_catalog.current_setting('search_path'); ++BEGIN ++-- for safety, transiently set search_path to just pg_catalog+pg_temp ++PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + + UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) + FROM (VALUES +-(NULL::pg_catalog.text, NULL::pg_catalog.regtype[]), -- establish column types +-('gseg_consistent(internal,seg,int4,oid,internal)', '{internal,seg,int2,oid,internal}') +-) AS update_data (oldproc, newtypes) +-WHERE oid = pg_catalog.to_regprocedure(oldproc); ++(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types ++('gseg_consistent(internal,SCH.seg,int4,oid,internal)', '{internal,SCH.seg,int2,oid,internal}') ++) AS update_data (oldproc, newtypestext), ++LATERAL ( ++ SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ ++) ls ++WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); ++ ++PERFORM pg_catalog.set_config('search_path', old_path, true); ++END ++$$; + + ALTER FUNCTION seg_in(cstring) PARALLEL SAFE; + ALTER FUNCTION seg_out(seg) PARALLEL SAFE; + +diff --git a/doc/src/sgml/earthdistance.sgml b/doc/src/sgml/earthdistance.sgml +index 6dedc4a..a58c5a1 100644 +--- a/doc/src/sgml/earthdistance.sgml ++++ b/doc/src/sgml/earthdistance.sgml +@@ -10,9 +10,8 @@ + + The earthdistance module provides two different approaches to + calculating great circle distances on the surface of the Earth. The one +- described first depends on the cube module (which +- must be installed before earthdistance can be +- installed). The second one is based on the built-in point data type, ++ described first depends on the cube module. ++ The second one is based on the built-in point data type, + using longitude and latitude for the coordinates. + + +@@ -23,6 +22,28 @@ + project.) + + ++ ++ The cube module must be installed ++ before earthdistance can be installed ++ (although you can use the CASCADE option ++ of CREATE EXTENSION to install both in one command). ++ ++ ++ ++ ++ It is strongly recommended that earthdistance ++ and cube be installed in the same schema, and that ++ that schema be one for which CREATE privilege has not been and will not ++ be granted to any untrusted users. ++ Otherwise there are installation-time security hazards ++ if earthdistance's schema contains objects defined ++ by a hostile user. ++ Furthermore, when using earthdistance's functions ++ after installation, the entire search path should contain only trusted ++ schemas. ++ ++ ++ + + Cube-based Earth Distances + +diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml +index 962515c..4901fe3 100644 +--- a/doc/src/sgml/extend.sgml ++++ b/doc/src/sgml/extend.sgml +@@ -342,7 +342,7 @@ + + + The extension script may set privileges on objects that are part of the +- extension via GRANT and REVOKE ++ extension, using GRANT and REVOKE + statements. The final set of privileges for each object (if any are set) + will be stored in the + pg_init_privs + +@@ -542,9 +516,38 @@ + + If this parameter is true (which is the default), + only superusers can create the extension or update it to a new +- version. If it is set to false, just the privileges ++ version (but see also trusted, below). ++ If it is set to false, just the privileges + required to execute the commands in the installation or update script + are required. ++ This should normally be set to true if any of the ++ script commands require superuser privileges. (Such commands would ++ fail anyway, but it's more user-friendly to give the error up front.) ++ ++ ++ ++ ++ ++ trusted (boolean) ++ ++ ++ This parameter, if set to true (which is not the ++ default), allows some non-superusers to install an extension that ++ has superuser set to true. ++ Specifically, installation will be permitted for anyone who has ++ CREATE privilege on the current database. ++ When the user executing CREATE EXTENSION is not ++ a superuser but is allowed to install by virtue of this parameter, ++ then the installation or update script is run as the bootstrap ++ superuser, not as the calling user. ++ This parameter is irrelevant if superuser is ++ false. ++ Generally, this should not be set true for extensions that could ++ allow access to otherwise-superuser-only abilities, such as ++ file system access. ++ Also, marking an extension trusted requires significant extra effort ++ to write the extension's installation and update script(s) securely; ++ see . + + + +@@ -686,7 +689,7 @@ + schema; that is, CREATE EXTENSION does the equivalent of + this: + +-SET LOCAL search_path TO @extschema@; ++SET LOCAL search_path TO @extschema@, pg_temp; + + This allows the objects created by the script file to go into the target + schema. The script file can change search_path if it wishes, +@@ -706,9 +709,15 @@ SET LOCAL search_path TO @extschema@; + + + If any prerequisite extensions are listed in requires +- in the control file, their target schemas are appended to the initial +- setting of search_path. This allows their objects to be +- visible to the new extension's script file. ++ in the control file, their target schemas are added to the initial ++ setting of search_path, following the new ++ extension's target schema. This allows their objects to be visible to ++ the new extension's script file. ++ ++ ++ ++ For security, pg_temp is automatically appended to ++ the end of search_path in all cases. + + + +@@ -962,6 +971,154 @@ SELECT * FROM pg_extension_update_paths('extension_name'); + + + ++ ++ Security Considerations for Extensions ++ ++ ++ Widely-distributed extensions should assume little about the database ++ they occupy. Therefore, it's appropriate to write functions provided ++ by an extension in a secure style that cannot be compromised by ++ search-path-based attacks. ++ ++ ++ ++ An extension that has the superuser property set to ++ true must also consider security hazards for the actions taken within ++ its installation and update scripts. It is not terribly difficult for ++ a malicious user to create trojan-horse objects that will compromise ++ later execution of a carelessly-written extension script, allowing that ++ user to acquire superuser privileges. ++ ++ ++ ++ If an extension is marked trusted, then its ++ installation schema can be selected by the installing user, who might ++ intentionally use an insecure schema in hopes of gaining superuser ++ privileges. Therefore, a trusted extension is extremely exposed from a ++ security standpoint, and all its script commands must be carefully ++ examined to ensure that no compromise is possible. ++ ++ ++ ++ Advice about writing functions securely is provided in ++ below, and advice ++ about writing installation scripts securely is provided in ++ . ++ ++ ++ ++ Security Considerations for Extension Functions ++ ++ ++ SQL-language and PL-language functions provided by extensions are at ++ risk of search-path-based attacks when they are executed, since ++ parsing of these functions occurs at execution time not creation time. ++ ++ ++ ++ The CREATE ++ FUNCTION reference page contains advice about ++ writing SECURITY DEFINER functions safely. It's ++ good practice to apply those techniques for any function provided by ++ an extension, since the function might be called by a high-privilege ++ user. ++ ++ ++ ++ ++ If you cannot set the search_path to contain only ++ secure schemas, assume that each unqualified name could resolve to an ++ object that a malicious user has defined. Beware of constructs that ++ depend on search_path implicitly; for ++ example, IN ++ and CASE expression WHEN ++ always select an operator using the search path. In their place, use ++ OPERATOR(schema.=) ANY ++ and CASE WHEN expression. ++ ++ ++ ++ A general-purpose extension usually should not assume that it's been ++ installed into a secure schema, which means that even schema-qualified ++ references to its own objects are not entirely risk-free. For ++ example, if the extension has defined a ++ function myschema.myfunc(bigint) then a call such ++ as myschema.myfunc(42) could be captured by a ++ hostile function myschema.myfunc(integer). Be ++ careful that the data types of function and operator parameters exactly ++ match the declared argument types, using explicit casts where necessary. ++ ++ ++ ++ ++ Security Considerations for Extension Scripts ++ ++ ++ An extension installation or update script should be written to guard ++ against search-path-based attacks occurring when the script executes. ++ If an object reference in the script can be made to resolve to some ++ other object than the script author intended, then a compromise might ++ occur immediately, or later when the mis-defined extension object is ++ used. ++ ++ ++ ++ DDL commands such as CREATE FUNCTION ++ and CREATE OPERATOR CLASS are generally secure, ++ but beware of any command having a general-purpose expression as a ++ component. For example, CREATE VIEW needs to be ++ vetted, as does a DEFAULT expression ++ in CREATE FUNCTION. ++ ++ ++ ++ Sometimes an extension script might need to execute general-purpose ++ SQL, for example to make catalog adjustments that aren't possible via ++ DDL. Be careful to execute such commands with a ++ secure search_path; do not ++ trust the path provided by CREATE/ALTER EXTENSION ++ to be secure. Best practice is to temporarily ++ set search_path to 'pg_catalog, ++ pg_temp' and insert references to the extension's ++ installation schema explicitly where needed. (This practice might ++ also be helpful for creating views.) Examples can be found in ++ the contrib modules in ++ the PostgreSQL source code distribution. ++ ++ ++ ++ Cross-extension references are extremely difficult to make fully ++ secure, partially because of uncertainty about which schema the other ++ extension is in. The hazards are reduced if both extensions are ++ installed in the same schema, because then a hostile object cannot be ++ placed ahead of the referenced extension in the installation-time ++ search_path. However, no mechanism currently exists ++ to require that. For now, best practice is to not mark an extension ++ trusted if it depends on another one, unless that other one is always ++ installed in pg_catalog. ++ ++ ++ ++ Do not use CREATE OR REPLACE ++ FUNCTION, except in an update script that must change the ++ definition of a function that is known to be an extension member ++ already. (Likewise for other OR REPLACE options.) ++ Using OR REPLACE unnecessarily not only has a risk ++ of accidentally overwriting someone else's function, but it creates a ++ security hazard since the overwritten function would still be owned by ++ its original owner, who could modify it. ++ ++ ++ ++ + + Extension Example + +@@ -981,18 +1138,18 @@ SELECT * FROM pg_extension_update_paths('extension_name'); + + CREATE TYPE pair AS ( k text, v text ); + +-CREATE OR REPLACE FUNCTION pair(text, text) ++CREATE FUNCTION pair(text, text) + RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::@extschema@.pair;'; + + CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, PROCEDURE = pair); + + -- "SET search_path" is easy to get right, but qualified names perform better. +-CREATE OR REPLACE FUNCTION lower(pair) ++CREATE FUNCTION lower(pair) + RETURNS pair LANGUAGE SQL + AS 'SELECT ROW(lower($1.k), lower($1.v))::@extschema@.pair;' + SET search_path = pg_temp; + +-CREATE OR REPLACE FUNCTION pair_concat(pair, pair) ++CREATE FUNCTION pair_concat(pair, pair) + RETURNS pair LANGUAGE SQL + AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k, + $1.v OPERATOR(pg_catalog.||) $2.v)::@extschema@.pair;'; +@@ -1007,6 +1164,7 @@ AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k, + # pair extension + comment = 'A key/value pair data type' + default_version = '1.0' ++# cannot be relocatable because of use of @extschema@ + relocatable = false + + +diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml +index db5d440..fee2812 100644 +--- a/doc/src/sgml/hstore.sgml ++++ b/doc/src/sgml/hstore.sgml +@@ -633,6 +633,15 @@ ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; + convention). If you use them, hstore values are mapped to + Python dictionaries. + ++ ++ ++ ++ It is strongly recommended that the transform extensions be installed in ++ the same schema as hstore. Otherwise there are ++ installation-time security hazards if a transform extension's schema ++ contains objects defined by a hostile user. ++ ++ + + + +diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml +index 77599ad..16d6a9b 100644 +--- a/doc/src/sgml/ltree.sgml ++++ b/doc/src/sgml/ltree.sgml +@@ -675,6 +675,15 @@ ltreetest=> SELECT ins_label(path,2,'Space') FROM test WHERE path <@ 'Top. + creating a function, ltree values are mapped to Python lists. + (The reverse is currently not supported, however.) + ++ ++ ++ ++ It is strongly recommended that the transform extensions be installed in ++ the same schema as ltree. Otherwise there are ++ installation-time security hazards if a transform extension's schema ++ contains objects defined by a hostile user. ++ ++ + + + +diff --git a/doc/src/sgml/ref/create_extension.sgml b/doc/src/sgml/ref/create_extension.sgml +index 14e9101..8016c78 100644 +--- a/doc/src/sgml/ref/create_extension.sgml ++++ b/doc/src/sgml/ref/create_extension.sgml +@@ -193,6 +193,33 @@ CREATE EXTENSION [ IF NOT EXISTS ] extension_name + system views. + + ++ ++ ++ Installing an extension as superuser requires trusting that the ++ extension's author wrote the extension installation script in a secure ++ fashion. It is not terribly difficult for a malicious user to create ++ trojan-horse objects that will compromise later execution of a ++ carelessly-written extension script, allowing that user to acquire ++ superuser privileges. However, trojan-horse objects are only hazardous ++ if they are in the search_path during script ++ execution, meaning that they are in the extension's installation target ++ schema or in the schema of some extension it depends on. Therefore, a ++ good rule of thumb when dealing with extensions whose scripts have not ++ been carefully vetted is to install them only into schemas for which ++ CREATE privilege has not been and will not be granted to any untrusted ++ users. Likewise for any extensions they depend on. ++ ++ ++ ++ The extensions supplied with PostgreSQL are ++ believed to be secure against installation-time attacks of this sort, ++ except for a few that depend on other extensions. As stated in the ++ documentation for those extensions, they should be installed into secure ++ schemas, or installed into the same schemas as the extensions they ++ depend on, or both. ++ ++ ++ + + For information about writing new extensions, see + . +@@ -204,8 +231,13 @@ CREATE EXTENSION [ IF NOT EXISTS ] extension_name + + + Install the hstore extension into the +- current database: ++ current database, placing its objects in schema addons: ++ ++CREATE EXTENSION hstore SCHEMA addons; ++ ++ Another way to accomplish the same thing: + ++SET search_path = addons; + CREATE EXTENSION hstore; + + +diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c +index e4340ee..068c463 100644 +--- a/src/backend/commands/extension.c ++++ b/src/backend/commands/extension.c +@@ -838,9 +838,21 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, + GUC_ACTION_SAVE, true, 0, false); + + /* +- * Set up the search path to contain the target schema, then the schemas +- * of any prerequisite extensions, and nothing else. In particular this +- * makes the target schema be the default creation target namespace. ++ * Similarly disable check_function_bodies, to ensure that SQL functions ++ * won't be parsed during creation. ++ */ ++ if (check_function_bodies) ++ (void) set_config_option("check_function_bodies", "off", ++ PGC_USERSET, PGC_S_SESSION, ++ GUC_ACTION_SAVE, true, 0, false); ++ ++ /* ++ * Set up the search path to have the target schema first, making it be ++ * the default creation target namespace. Then add the schemas of any ++ * prerequisite extensions, unless they are in pg_catalog which would be ++ * searched anyway. (Listing pg_catalog explicitly in a non-first ++ * position would be bad for security.) Finally add pg_temp to ensure ++ * that temp objects can't take precedence over others. + * + * Note: it might look tempting to use PushOverrideSearchPath for this, + * but we cannot do that. We have to actually set the search_path GUC in +@@ -854,9 +866,10 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, + Oid reqschema = lfirst_oid(lc); + char *reqname = get_namespace_name(reqschema); + +- if (reqname) ++ if (reqname && strcmp(reqname, "pg_catalog") != 0) + appendStringInfo(&pathbuf, ", %s", quote_identifier(reqname)); + } ++ appendStringInfoString(&pathbuf, ", pg_temp"); + + (void) set_config_option("search_path", pathbuf.data, + PGC_USERSET, PGC_S_SESSION, +diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c +index 6674b41..b637cd4 100644 +--- a/src/backend/commands/operatorcmds.c ++++ b/src/backend/commands/operatorcmds.c +@@ -297,6 +297,7 @@ ValidateJoinEstimator(List *joinName) + { + Oid typeId[5]; + Oid joinOid; ++ Oid joinOid2; + AclResult aclresult; + + typeId[0] = INTERNALOID; /* PlannerInfo */ +@@ -307,15 +308,26 @@ ValidateJoinEstimator(List *joinName) + + /* + * As of Postgres 8.4, the preferred signature for join estimators has 5 +- * arguments, but we still allow the old 4-argument form. Try the +- * preferred form first. ++ * arguments, but we still allow the old 4-argument form. Whine about ++ * ambiguity if both forms exist. + */ + joinOid = LookupFuncName(joinName, 5, typeId, true); +- if (!OidIsValid(joinOid)) +- joinOid = LookupFuncName(joinName, 4, typeId, true); +- /* If not found, reference the 5-argument signature in error msg */ +- if (!OidIsValid(joinOid)) +- joinOid = LookupFuncName(joinName, 5, typeId, false); ++ joinOid2 = LookupFuncName(joinName, 4, typeId, true); ++ if (OidIsValid(joinOid)) ++ { ++ if (OidIsValid(joinOid2)) ++ ereport(ERROR, ++ (errcode(ERRCODE_AMBIGUOUS_FUNCTION), ++ errmsg("join estimator function %s has multiple matches", ++ NameListToString(joinName)))); ++ } ++ else ++ { ++ joinOid = joinOid2; ++ /* If not found, reference the 5-argument signature in error msg */ ++ if (!OidIsValid(joinOid)) ++ joinOid = LookupFuncName(joinName, 5, typeId, false); ++ } + + /* estimators must return float8 */ + if (get_func_rettype(joinOid) != FLOAT8OID) + +diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c +index 8e5134b..6172d47 100644 +--- a/src/backend/commands/typecmds.c ++++ b/src/backend/commands/typecmds.c +@@ -1659,7 +1659,11 @@ static Oid + findTypeInputFunction(List *procname, Oid typeOid) + { + Oid argList[3]; ++ int nmatches = 0; + Oid procOid; ++ Oid procOid2; ++ Oid procOid3; ++ Oid procOid4; + + /* + * Input functions can take a single argument of type CSTRING, or three +@@ -1670,29 +1674,42 @@ findTypeInputFunction(List *procname, Oid typeOid) + */ + argList[0] = CSTRINGOID; + +- procOid = LookupFuncName(procname, 1, argList, true); +- if (OidIsValid(procOid)) +- return procOid; +- + argList[1] = OIDOID; + argList[2] = INT4OID; + +- procOid = LookupFuncName(procname, 3, argList, true); ++ procOid = LookupFuncName(procname, 1, argList, true); + if (OidIsValid(procOid)) +- return procOid; ++ nmatches++; ++ procOid2 = LookupFuncName(procname, 3, argList, true); ++ if (OidIsValid(procOid2)) ++ nmatches++; + + /* No luck, try it with OPAQUE */ + argList[0] = OPAQUEOID; + +- procOid = LookupFuncName(procname, 1, argList, true); ++ procOid3 = LookupFuncName(procname, 1, argList, true); ++ if (OidIsValid(procOid3)) ++ nmatches++; ++ procOid4 = LookupFuncName(procname, 3, argList, true); ++ if (OidIsValid(procOid4)) ++ nmatches++; + +- if (!OidIsValid(procOid)) +- { +- argList[1] = OIDOID; +- argList[2] = INT4OID; ++ if (nmatches > 1) ++ ereport(ERROR, ++ (errcode(ERRCODE_AMBIGUOUS_FUNCTION), ++ errmsg("type input function %s has multiple matches", ++ NameListToString(procname)))); + +- procOid = LookupFuncName(procname, 3, argList, true); +- } ++ if (OidIsValid(procOid)) ++ return procOid; ++ if (OidIsValid(procOid2)) ++ return procOid2; ++ ++ /* Cases with OPAQUE need adjustment */ ++ if (OidIsValid(procOid3)) ++ procOid = procOid3; ++ else ++ procOid = procOid4; + + if (OidIsValid(procOid)) + { +@@ -1778,6 +1795,7 @@ findTypeReceiveFunction(List *procname, Oid typeOid) + { + Oid argList[3]; + Oid procOid; ++ Oid procOid2; + + /* + * Receive functions can take a single argument of type INTERNAL, or three +@@ -1785,17 +1803,24 @@ findTypeReceiveFunction(List *procname, Oid typeOid) + */ + argList[0] = INTERNALOID; + +- procOid = LookupFuncName(procname, 1, argList, true); +- if (OidIsValid(procOid)) +- return procOid; +- + argList[1] = OIDOID; + argList[2] = INT4OID; + +- procOid = LookupFuncName(procname, 3, argList, true); ++ procOid = LookupFuncName(procname, 1, argList, true); ++ procOid2 = LookupFuncName(procname, 3, argList, true); + if (OidIsValid(procOid)) ++ { ++ if (OidIsValid(procOid2)) ++ ereport(ERROR, ++ (errcode(ERRCODE_AMBIGUOUS_FUNCTION), ++ errmsg("type receive function %s has multiple matches", ++ NameListToString(procname)))); + return procOid; ++ } ++ else if (OidIsValid(procOid2)) ++ return procOid2; + ++ /* If not found, reference the 1-argument signature in error msg */ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function %s does not exist", +-- +2.23.0 + -- Gitee From 5e2334ac4b30cf39d74649b88dbb0c1d9919396a Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 14:57:52 +0800 Subject: [PATCH 02/10] update postgresql.spec. --- postgresql.spec | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/postgresql.spec b/postgresql.spec index b61c128..b836346 100644 --- a/postgresql.spec +++ b/postgresql.spec @@ -4,7 +4,7 @@ Name: postgresql Version: 10.5 -Release: 17 +Release: 18 Summary: PostgreSQL client programs License: PostgreSQL URL: http://www.postgresql.org/ @@ -23,19 +23,21 @@ Source11: macros.postgresql Source12: macros.postgresql-test Source13: postgresql_pkg_tests.sh -Patch0000: 0000-postgresql-var-run-socket.patch -Patch0001: 0000-rpm-pgsql.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 -Patch6004: CVE-2019-10130.patch -Patch6005: CVE-2020-1720.patch +Patch1: 0001-postgresql-var-run-socket.patch +Patch2: 0002-rpm-pgsql.patch +Patch3: 0003-CVE-2019-10164-1.patch +Patch4: 0004-CVE-2019-10164-2.patch +Patch5: 0005-CVE-2019-10208.patch +Patch6: 0006-CVE-2018-16850.patch +Patch7: 0007-CVE-2019-10130.patch +Patch8: 0008-CVE-2020-1720.patch +Patch9: 0009-CVE-2020-14349-1.patch +Patch10: 0010-CVE-2020-14349-2.patch +Patch11: 0011-CVE-2020-14350.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 -BuildRequires: util-linux m4 elinks docbook-utils help2man +BuildRequires: util-linux m4 elinks docbook-utils help2man docbook-style-xsl BuildRequires: python3 python3-devel tcl-devel openssl-devel krb5-devel openldap-devel gettext >= 0.10.35 BuildRequires: uuid-devel libxml2-devel libxslt-devel pam-devel systemtap-sdt-devel libselinux-devel Requires: %{name}-libs = %{version}-%{release} @@ -158,14 +160,17 @@ that want to run build-time testsuite against running PostgreSQL server. sha256sum -c %{SOURCE3} ) %setup -q -%patch0000 -p1 -%patch0001 -p1 -%patch6000 -p1 -%patch6001 -p1 -%patch6002 -p1 -%patch6003 -p1 -%patch6004 -p1 -%patch6005 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 %build if [ x"`id -u`" = x0 ]; then @@ -430,6 +435,12 @@ find_lang_bins pltcl.lst pltcl %attr(-,postgres,postgres) %{_libdir}/pgsql/test %changelog +* Web Sep 9 2020 yanglongkang - 10.5-18 +- Fix CVE-2020-14349 CVE-2020-14350 + +* Tue Aug 18 2020 yanglongkang - 10.5-17 +- add release for update + * Fri Jun 19 2020 cuibaobao - 10.5-16 - Type: enhancement - DESC: delete all about residual parse_upgrade_setup in postgresql-setup -- Gitee From 035557467056419af93b8ea71632d7edab501a9b Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:00:30 +0800 Subject: [PATCH 03/10] rename 0000-postgresql-var-run-socket.patch to 0001-postgresql-var-run-socket.patch. --- ...l-var-run-socket.patch => 0001-postgresql-var-run-socket.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 0000-postgresql-var-run-socket.patch => 0001-postgresql-var-run-socket.patch (100%) diff --git a/0000-postgresql-var-run-socket.patch b/0001-postgresql-var-run-socket.patch similarity index 100% rename from 0000-postgresql-var-run-socket.patch rename to 0001-postgresql-var-run-socket.patch -- Gitee From 39114a8c4de42518cf5595d4eab84e48dd27d504 Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:01:23 +0800 Subject: [PATCH 04/10] rename 0000-rpm-pgsql.patch to 0002-rpm-pgsql.patch. --- 0000-rpm-pgsql.patch => 0002-rpm-pgsql.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 0000-rpm-pgsql.patch => 0002-rpm-pgsql.patch (100%) diff --git a/0000-rpm-pgsql.patch b/0002-rpm-pgsql.patch similarity index 100% rename from 0000-rpm-pgsql.patch rename to 0002-rpm-pgsql.patch -- Gitee From 4354dbb2d90328ffab36bdd11a90c1b058359b4d Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:01:47 +0800 Subject: [PATCH 05/10] rename 6000-CVE-2019-10164-1.patch to 0003-CVE-2019-10164-1.patch. --- 6000-CVE-2019-10164-1.patch => 0003-CVE-2019-10164-1.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 6000-CVE-2019-10164-1.patch => 0003-CVE-2019-10164-1.patch (100%) diff --git a/6000-CVE-2019-10164-1.patch b/0003-CVE-2019-10164-1.patch similarity index 100% rename from 6000-CVE-2019-10164-1.patch rename to 0003-CVE-2019-10164-1.patch -- Gitee From c9d5ba945fbf4221df84ea06c99c82036a2d4778 Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:02:06 +0800 Subject: [PATCH 06/10] rename 6001-CVE-2019-10164-2.patch to 0004-CVE-2019-10164-2.patch. --- 6001-CVE-2019-10164-2.patch => 0004-CVE-2019-10164-2.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 6001-CVE-2019-10164-2.patch => 0004-CVE-2019-10164-2.patch (100%) diff --git a/6001-CVE-2019-10164-2.patch b/0004-CVE-2019-10164-2.patch similarity index 100% rename from 6001-CVE-2019-10164-2.patch rename to 0004-CVE-2019-10164-2.patch -- Gitee From 46fc7d335744ad9fb841a3960d844d879968d9e3 Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:02:30 +0800 Subject: [PATCH 07/10] rename CVE-2019-10208.patch to 0005-CVE-2019-10208.patch. --- CVE-2019-10208.patch => 0005-CVE-2019-10208.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CVE-2019-10208.patch => 0005-CVE-2019-10208.patch (100%) diff --git a/CVE-2019-10208.patch b/0005-CVE-2019-10208.patch similarity index 100% rename from CVE-2019-10208.patch rename to 0005-CVE-2019-10208.patch -- Gitee From 7462e32d678f470ade7361811ee454a195bb4c06 Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:02:56 +0800 Subject: [PATCH 08/10] rename CVE-2018-16850.patch to 0006-CVE-2018-16850.patch. --- CVE-2018-16850.patch => 0006-CVE-2018-16850.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CVE-2018-16850.patch => 0006-CVE-2018-16850.patch (100%) diff --git a/CVE-2018-16850.patch b/0006-CVE-2018-16850.patch similarity index 100% rename from CVE-2018-16850.patch rename to 0006-CVE-2018-16850.patch -- Gitee From fe0124244318793f6f993dd7431010a5294bb897 Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:03:16 +0800 Subject: [PATCH 09/10] rename CVE-2019-10130.patch to 0007-CVE-2019-10130.patch. --- CVE-2019-10130.patch => 0007-CVE-2019-10130.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CVE-2019-10130.patch => 0007-CVE-2019-10130.patch (100%) diff --git a/CVE-2019-10130.patch b/0007-CVE-2019-10130.patch similarity index 100% rename from CVE-2019-10130.patch rename to 0007-CVE-2019-10130.patch -- Gitee From f62288da9dd13275d820f4c0f5c620c2b62e74bf Mon Sep 17 00:00:00 2001 From: Markeryang <747675909@qq.com> Date: Thu, 10 Sep 2020 15:17:22 +0800 Subject: [PATCH 10/10] rename CVE-2020-1720.patch to 0008-CVE-2020-1720.patch. --- CVE-2020-1720.patch => 0008-CVE-2020-1720.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CVE-2020-1720.patch => 0008-CVE-2020-1720.patch (100%) diff --git a/CVE-2020-1720.patch b/0008-CVE-2020-1720.patch similarity index 100% rename from CVE-2020-1720.patch rename to 0008-CVE-2020-1720.patch -- Gitee