Skip to content

Commit 15f5893

Browse files
svenklemmtimescale-automation
authored andcommitted
Check hypertable ownership before recompression
The SQL functions for compressing and rebuilding chunks did not verify that the caller owned the hypertable. The first-time compression path was protected by a check inside a shared helper, but the recompression paths skipped it. Any user who could read a chunk OID from the catalog could trigger a recompression on chunks owned by someone else. Add the ownership check at the entry of each affected function. (cherry picked from commit c3e42dd)
1 parent 94039e3 commit 15f5893

8 files changed

Lines changed: 38 additions & 0 deletions

File tree

.unreleased/pr_9800

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #9800 Check hypertable ownership before recompression

tsl/src/compression/api.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ tsl_compress_chunk(PG_FUNCTION_ARGS)
886886

887887
TS_PREVENT_FUNC_IF_READ_ONLY();
888888
Chunk *chunk = ts_chunk_get_by_relid(uncompressed_chunk_id, true);
889+
ts_hypertable_permissions_check(chunk->hypertable_relid, GetUserId());
889890

890891
uncompressed_chunk_id = tsl_compress_chunk_wrapper(chunk, if_not_compressed, recompress);
891892

@@ -1029,6 +1030,7 @@ tsl_rebuild_columnstore(PG_FUNCTION_ARGS)
10291030
}
10301031

10311032
Chunk *chunk = ts_chunk_get_by_relid(chunk_relid, true);
1033+
ts_hypertable_permissions_check(chunk->hypertable_relid, GetUserId());
10321034

10331035
if (!ts_chunk_is_compressed(chunk) || ts_chunk_is_frozen(chunk))
10341036
{

tsl/src/compression/recompress.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <postgres.h>
88
#include "debug_point.h"
9+
#include <miscadmin.h>
910
#include <parser/parse_coerce.h>
1011
#include <parser/parse_relation.h>
1112
#include <utils/inval.h>
@@ -22,6 +23,7 @@
2223
#include "create.h"
2324
#include "debug_assert.h"
2425
#include "guc.h"
26+
#include "hypertable.h"
2527
#include "indexing.h"
2628
#include "recompress.h"
2729
#include "ts_catalog/array_utils.h"
@@ -82,6 +84,7 @@ tsl_recompress_chunk_segmentwise(PG_FUNCTION_ARGS)
8284
ts_feature_flag_check(FEATURE_HYPERTABLE_COMPRESSION);
8385
TS_PREVENT_FUNC_IF_READ_ONLY();
8486
Chunk *chunk = ts_chunk_get_by_relid(uncompressed_chunk_id, true);
87+
ts_hypertable_permissions_check(chunk->hypertable_relid, GetUserId());
8588

8689
if (!ts_chunk_is_partial(chunk))
8790
{

tsl/test/expected/compression_permissions-15.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ ERROR: must be owner of table conditions
5959
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
6060
SELECT compress_chunk(show_chunks('conditions'));
6161
ERROR: must be owner of hypertable "conditions"
62+
SELECT compress_chunk(show_chunks('conditions'), recompress => true);
63+
ERROR: must be owner of hypertable "conditions"
6264
SELECT decompress_chunk(show_chunks('conditions'));
6365
ERROR: must be owner of hypertable "conditions"
66+
SELECT show_chunks('conditions') AS chunk LIMIT 1 \gset
67+
CALL _timescaledb_functions.rebuild_columnstore(:'chunk'::regclass);
68+
ERROR: must be owner of hypertable "conditions"
69+
SELECT _timescaledb_functions.recompress_chunk_segmentwise(show_chunks('conditions'));
70+
ERROR: must be owner of hypertable "conditions"
6471
select add_compression_policy('conditions', '1day'::interval);
6572
ERROR: must be owner of hypertable "conditions"
6673
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER

tsl/test/expected/compression_permissions-16.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ ERROR: must be owner of table conditions
5959
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
6060
SELECT compress_chunk(show_chunks('conditions'));
6161
ERROR: must be owner of hypertable "conditions"
62+
SELECT compress_chunk(show_chunks('conditions'), recompress => true);
63+
ERROR: must be owner of hypertable "conditions"
6264
SELECT decompress_chunk(show_chunks('conditions'));
6365
ERROR: must be owner of hypertable "conditions"
66+
SELECT show_chunks('conditions') AS chunk LIMIT 1 \gset
67+
CALL _timescaledb_functions.rebuild_columnstore(:'chunk'::regclass);
68+
ERROR: must be owner of hypertable "conditions"
69+
SELECT _timescaledb_functions.recompress_chunk_segmentwise(show_chunks('conditions'));
70+
ERROR: must be owner of hypertable "conditions"
6471
select add_compression_policy('conditions', '1day'::interval);
6572
ERROR: must be owner of hypertable "conditions"
6673
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER

tsl/test/expected/compression_permissions-17.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ ERROR: must be owner of table conditions
5959
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
6060
SELECT compress_chunk(show_chunks('conditions'));
6161
ERROR: must be owner of hypertable "conditions"
62+
SELECT compress_chunk(show_chunks('conditions'), recompress => true);
63+
ERROR: must be owner of hypertable "conditions"
6264
SELECT decompress_chunk(show_chunks('conditions'));
6365
ERROR: must be owner of hypertable "conditions"
66+
SELECT show_chunks('conditions') AS chunk LIMIT 1 \gset
67+
CALL _timescaledb_functions.rebuild_columnstore(:'chunk'::regclass);
68+
ERROR: must be owner of hypertable "conditions"
69+
SELECT _timescaledb_functions.recompress_chunk_segmentwise(show_chunks('conditions'));
70+
ERROR: must be owner of hypertable "conditions"
6471
select add_compression_policy('conditions', '1day'::interval);
6572
ERROR: must be owner of hypertable "conditions"
6673
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER

tsl/test/expected/compression_permissions-18.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ ERROR: must be owner of table conditions
5959
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
6060
SELECT compress_chunk(show_chunks('conditions'));
6161
ERROR: must be owner of hypertable "conditions"
62+
SELECT compress_chunk(show_chunks('conditions'), recompress => true);
63+
ERROR: must be owner of hypertable "conditions"
6264
SELECT decompress_chunk(show_chunks('conditions'));
6365
ERROR: must be owner of hypertable "conditions"
66+
SELECT show_chunks('conditions') AS chunk LIMIT 1 \gset
67+
CALL _timescaledb_functions.rebuild_columnstore(:'chunk'::regclass);
68+
ERROR: must be owner of hypertable "conditions"
69+
SELECT _timescaledb_functions.recompress_chunk_segmentwise(show_chunks('conditions'));
70+
ERROR: must be owner of hypertable "conditions"
6471
select add_compression_policy('conditions', '1day'::interval);
6572
ERROR: must be owner of hypertable "conditions"
6673
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER

tsl/test/sql/compression_permissions.sql.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ alter table conditions set (timescaledb.compress, timescaledb.compress_segmentby
6060
--- compress_chunks and decompress_chunks fail without correct perm --
6161
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
6262
SELECT compress_chunk(show_chunks('conditions'));
63+
SELECT compress_chunk(show_chunks('conditions'), recompress => true);
6364
SELECT decompress_chunk(show_chunks('conditions'));
65+
SELECT show_chunks('conditions') AS chunk LIMIT 1 \gset
66+
CALL _timescaledb_functions.rebuild_columnstore(:'chunk'::regclass);
67+
SELECT _timescaledb_functions.recompress_chunk_segmentwise(show_chunks('conditions'));
6468
select add_compression_policy('conditions', '1day'::interval);
6569

6670
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER

0 commit comments

Comments
 (0)