Skip to content

CVE-2020-14350 #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ REGRESS = pathman_array_qual \
pathman_update_triggers \
pathman_upd_del \
pathman_utility_stmt \
pathman_views
pathman_views \
pathman_CVE-2020-14350


EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,19 @@ shared_preload_libraries = 'pg_pathman'

It is essential to restart the PostgreSQL instance. After that, execute the following query in psql:
```plpgsql
CREATE EXTENSION pg_pathman;
CREATE SCHEMA pathman;
GRANT USAGE ON SCHEMA pathman TO PUBLIC;
CREATE EXTENSION pg_pathman WITH SCHEMA pathman;
```

Done! Now it's time to setup your partitioning schemes.

> **Security notice**: pg_pathman is believed to be secure against
search-path-based attacks mentioned in Postgres
[documentation](https://www.postgresql.org/docs/current/sql-createextension.html). However,
if *your* calls of pathman's functions doesn't exactly match the signature, they
might be vulnerable to malicious overloading. If in doubt, install pathman to clean schema where nobody except superusers have CREATE object permission to avoid problems.

> **Windows-specific**: pg_pathman imports several symbols (e.g. None_Receiver, InvalidObjectAddress) from PostgreSQL, which is fine by itself, but requires that those symbols are marked as `PGDLLIMPORT`. Unfortunately, some of them are not exported from vanilla PostgreSQL, which means that you have to either use Postgres Pro Standard/Enterprise (which includes all necessary patches), or patch and build your own distribution of PostgreSQL.

## How to update
Expand Down Expand Up @@ -611,7 +619,7 @@ SELECT tableoid::regclass AS partition, * FROM partitioned_table;
- All running concurrent partitioning tasks can be listed using the `pathman_concurrent_part_tasks` view:
```plpgsql
SELECT * FROM pathman_concurrent_part_tasks;
userid | pid | dbid | relid | processed | status
userid | pid | dbid | relid | processed | status
--------+------+-------+-------+-----------+---------
dmitry | 7367 | 16384 | test | 472000 | working
(1 row)
Expand All @@ -625,7 +633,7 @@ WHERE parent = 'part_test'::regclass AND range_min::int < 500;
NOTICE: 1 rows copied from part_test_11
NOTICE: 100 rows copied from part_test_1
NOTICE: 100 rows copied from part_test_2
drop_range_partition
drop_range_partition
----------------------
dummy_test_11
dummy_test_1
Expand Down Expand Up @@ -780,8 +788,8 @@ All sections and data will remain unchanged and will be handled by the standard
Do not hesitate to post your issues, questions and new ideas at the [issues](https://github.com/postgrespro/pg_pathman/issues) page.

## Authors
[Ildar Musin](https://github.com/zilder)
Alexander Korotkov <a.korotkov(at)postgrespro.ru> Postgres Professional Ltd., Russia
[Dmitry Ivanov](https://github.com/funbringer)
Maksim Milyutin <m.milyutin(at)postgrespro.ru> Postgres Professional Ltd., Russia
[Ildar Musin](https://github.com/zilder)
Alexander Korotkov <a.korotkov(at)postgrespro.ru> Postgres Professional Ltd., Russia
[Dmitry Ivanov](https://github.com/funbringer)
Maksim Milyutin <m.milyutin(at)postgrespro.ru> Postgres Professional Ltd., Russia
[Ildus Kurbangaliev](https://github.com/ildus)
115 changes: 115 additions & 0 deletions expected/pathman_CVE-2020-14350.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Check fix for CVE-2020-14350.
* See also 7eeb1d986 postgresql commit.
*/
SET client_min_messages = 'warning';
DROP FUNCTION IF EXISTS _partition_data_concurrent(oid,integer);
DROP FUNCTION IF EXISTS create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
DROP TABLE IF EXISTS test1 CASCADE;
DROP TABLE IF EXISTS test2 CASCADE;
DROP ROLE IF EXISTS regress_hacker;
SET client_min_messages = 'notice';
CREATE EXTENSION pg_pathman;
CREATE ROLE regress_hacker LOGIN;
-- Test 1
RESET ROLE;
ALTER ROLE regress_hacker NOSUPERUSER;
SET ROLE regress_hacker;
SHOW is_superuser;
is_superuser
--------------
off
(1 row)

CREATE FUNCTION _partition_data_concurrent(relation oid, p_limit INT, OUT p_total BIGINT)
RETURNS bigint
AS $$
BEGIN
ALTER ROLE regress_hacker SUPERUSER;
SELECT _partition_data_concurrent(relation, NULL::text, NULL::text, p_limit) INTO p_total;
END
$$ LANGUAGE plpgsql;
CREATE TABLE test1(i INT4 NOT NULL);
INSERT INTO test1 SELECT generate_series(1, 500);
SELECT create_hash_partitions('test1', 'i', 5, false);
create_hash_partitions
------------------------
5
(1 row)

RESET ROLE;
SELECT partition_table_concurrently('test1', 10, 1);
NOTICE: worker started, you can stop it with the following command: select public.stop_concurrent_part_task('test1');
partition_table_concurrently
------------------------------

(1 row)

SELECT pg_sleep(1);
pg_sleep
----------

(1 row)

-- Test result (must be 'off')
SET ROLE regress_hacker;
SHOW is_superuser;
is_superuser
--------------
off
(1 row)

-- Test 2
RESET ROLE;
ALTER ROLE regress_hacker NOSUPERUSER;
SET ROLE regress_hacker;
SHOW is_superuser;
is_superuser
--------------
off
(1 row)

CREATE FUNCTION create_single_range_partition(parent_relid TEXT, start_value ANYELEMENT, end_value ANYELEMENT, partition_name TEXT)
RETURNS REGCLASS
AS $$
BEGIN
ALTER ROLE regress_hacker SUPERUSER;
RETURN create_single_range_partition(parent_relid, start_value, end_value, partition_name, NULL::text);
END
$$ LANGUAGE plpgsql;
RESET ROLE;
CREATE TABLE test2(i INT4 NOT NULL);
INSERT INTO test2 VALUES(0);
SELECT create_range_partitions('test2', 'i', 0, 1);
create_range_partitions
-------------------------
1
(1 row)

INSERT INTO test2 values(1);
-- Test result (must be 'off')
SET ROLE regress_hacker;
SHOW is_superuser;
is_superuser
--------------
off
(1 row)

-- Cleanup
RESET ROLE;
DROP FUNCTION _partition_data_concurrent(oid,integer);
DROP FUNCTION create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
DROP TABLE test1 CASCADE;
NOTICE: drop cascades to 5 other objects
DETAIL: drop cascades to table test1_0
drop cascades to table test1_1
drop cascades to table test1_2
drop cascades to table test1_3
drop cascades to table test1_4
DROP TABLE test2 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to sequence test2_seq
drop cascades to table test2_1
drop cascades to table test2_2
DROP ROLE regress_hacker;
DROP EXTENSION pg_pathman;
22 changes: 11 additions & 11 deletions hash.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
* hash.sql
* HASH partitioning functions
*
* Copyright (c) 2015-2016, Postgres Professional
* Copyright (c) 2015-2020, Postgres Professional
*
* ------------------------------------------------------------------------
*/

/*
* Creates hash partitions for specified relation
*/
CREATE OR REPLACE FUNCTION @[email protected]_hash_partitions(
CREATE FUNCTION @[email protected]_hash_partitions(
parent_relid REGCLASS,
expression TEXT,
partitions_count INT4,
Expand Down Expand Up @@ -53,7 +53,7 @@ SET client_min_messages = WARNING;
*
* lock_parent - should we take an exclusive lock?
*/
CREATE OR REPLACE FUNCTION @[email protected]_hash_partition(
CREATE FUNCTION @[email protected]_hash_partition(
old_partition REGCLASS,
new_partition REGCLASS,
lock_parent BOOL DEFAULT TRUE)
Expand Down Expand Up @@ -110,18 +110,18 @@ BEGIN

/* Fetch definition of old_partition's HASH constraint */
SELECT pg_catalog.pg_get_constraintdef(oid) FROM pg_catalog.pg_constraint
WHERE conrelid = old_partition AND quote_ident(conname) = old_constr_name
WHERE conrelid = old_partition AND pg_catalog.quote_ident(conname) = old_constr_name
INTO old_constr_def;

/* Detach old partition */
EXECUTE format('ALTER TABLE %s NO INHERIT %s', old_partition, parent_relid);
EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %s',
EXECUTE pg_catalog.format('ALTER TABLE %s NO INHERIT %s', old_partition, parent_relid);
EXECUTE pg_catalog.format('ALTER TABLE %s DROP CONSTRAINT %s',
old_partition,
old_constr_name);

/* Attach the new one */
EXECUTE format('ALTER TABLE %s INHERIT %s', new_partition, parent_relid);
EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %s %s',
EXECUTE pg_catalog.format('ALTER TABLE %s INHERIT %s', new_partition, parent_relid);
EXECUTE pg_catalog.format('ALTER TABLE %s ADD CONSTRAINT %s %s',
new_partition,
@[email protected]_check_constraint_name(new_partition::REGCLASS),
old_constr_def);
Expand All @@ -146,7 +146,7 @@ $$ LANGUAGE plpgsql;
/*
* Just create HASH partitions, called by create_hash_partitions().
*/
CREATE OR REPLACE FUNCTION @[email protected]_hash_partitions_internal(
CREATE FUNCTION @[email protected]_hash_partitions_internal(
parent_relid REGCLASS,
attribute TEXT,
partitions_count INT4,
Expand All @@ -158,14 +158,14 @@ LANGUAGE C;
/*
* Calculates hash for integer value
*/
CREATE OR REPLACE FUNCTION @[email protected]_hash_part_idx(INT4, INT4)
CREATE FUNCTION @[email protected]_hash_part_idx(INT4, INT4)
RETURNS INTEGER AS 'pg_pathman', 'get_hash_part_idx'
LANGUAGE C STRICT;

/*
* Build hash condition for a CHECK CONSTRAINT
*/
CREATE OR REPLACE FUNCTION @[email protected]_hash_condition(
CREATE FUNCTION @[email protected]_hash_condition(
attribute_type REGTYPE,
attribute TEXT,
partitions_count INT4,
Expand Down
Loading