Skip to content

Commit

Permalink
Allow to run pg_repack by non-superuser
Browse files Browse the repository at this point in the history
Now everybody how has access to repack_trigger() and repack_apply() and
relevant objects can call that functions.

Functions repack_swap(), repack_drop() and repack_index_swap() can be
called by superuser and owners of a table.

Cherry-pick the commit 326b6e1 to not cause segmentation fault when
using -k option and not having enough permissions.
  • Loading branch information
za-arthur committed Nov 1, 2024
1 parent 632f67d commit ecbc587
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 14 deletions.
3 changes: 2 additions & 1 deletion doc/pg_repack.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ You can choose one of the following methods to reorganize:

NOTICE:

* Only superusers can use the utility.
* Only superusers or owners of tables and indexes can use the utility. To run
pg_repack as an owner you need to use the option `--no-superuser-check`.
* Target table must have a PRIMARY KEY, or at least a UNIQUE total index on a
NOT NULL column.

Expand Down
3 changes: 2 additions & 1 deletion doc/pg_repack_jp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ pg_repackでは再編成する方法として次のものが選択できます

.. NOTICE:
* Only superusers can use the utility.
* Only superusers or owners of tables and indexes can use the utility. To run
pg_repack as an owner you need to use the option `--no-superuser-check`.
* Target table must have a PRIMARY KEY, or at least a UNIQUE total index on a
NOT NULL column.
Expand Down
28 changes: 16 additions & 12 deletions lib/repack.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,20 @@ static void swap_heap_or_index_files(Oid r1, Oid r2);

/* check access authority */
static void
must_be_superuser(const char *func)
must_be_owner(Oid relId)
{
if (!superuser())
elog(ERROR, "must be superuser to use %s function", func);
#if PG_VERSION_NUM >= 160000
if (!object_ownercheck(RelationRelationId, relId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relId)),
get_rel_name(relId));
#elif PG_VERSION_NUM >= 110000
if (!pg_class_ownercheck(relId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relId)),
get_rel_name(relId));
#else
if (!pg_class_ownercheck(relId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, get_rel_name(relId));
#endif
}


Expand Down Expand Up @@ -163,9 +173,6 @@ repack_trigger(PG_FUNCTION_ARGS)
Oid relid;
StringInfo sql;

/* authority check */
must_be_superuser("repack_trigger");

/* make sure it's called as a trigger at all */
if (!CALLED_AS_TRIGGER(fcinfo) ||
!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
Expand Down Expand Up @@ -259,9 +266,6 @@ repack_apply(PG_FUNCTION_ARGS)

initStringInfo(&sql_pop);

/* authority check */
must_be_superuser("repack_apply");

/* connect to SPI manager */
repack_init();

Expand Down Expand Up @@ -859,7 +863,7 @@ repack_swap(PG_FUNCTION_ARGS)
Oid owner2;

/* authority check */
must_be_superuser("repack_swap");
must_be_owner(oid);

/* connect to SPI manager */
repack_init();
Expand Down Expand Up @@ -1060,7 +1064,7 @@ repack_drop(PG_FUNCTION_ARGS)
}

/* authority check */
must_be_superuser("repack_drop");
must_be_owner(oid);

/* connect to SPI manager */
repack_init();
Expand Down Expand Up @@ -1413,7 +1417,7 @@ repack_index_swap(PG_FUNCTION_ARGS)
HeapTuple tuple;

/* authority check */
must_be_superuser("repack_index_swap");
must_be_owner(orig_idx_oid);

/* connect to SPI manager */
repack_init();
Expand Down
13 changes: 13 additions & 0 deletions regress/expected/nosuper.out
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,17 @@ ERROR: pg_repack failed with error: You must be a superuser to use pg_repack
ERROR: pg_repack failed with error: ERROR: permission denied for schema repack
LINE 1: select repack.version(), repack.version_sql()
^
GRANT ALL ON ALL TABLES IN SCHEMA repack TO nosuper;
GRANT USAGE ON SCHEMA repack TO nosuper;
-- => ERROR
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check
INFO: repacking table "public.tbl_cluster"
ERROR: query failed: ERROR: current transaction is aborted, commands ignored until end of transaction block
DETAIL: query was: RESET lock_timeout
ERROR: query failed: ERROR: current transaction is aborted, commands ignored until end of transaction block
DETAIL: query was: RESET lock_timeout
ERROR: permission denied for table tbl_cluster
ERROR: permission denied for table tbl_cluster
REVOKE ALL ON ALL TABLES IN SCHEMA repack FROM nosuper;
REVOKE USAGE ON SCHEMA repack FROM nosuper;
DROP ROLE IF EXISTS nosuper;
15 changes: 15 additions & 0 deletions regress/expected/nosuper_1.out
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,19 @@ ERROR: pg_repack failed with error: You must be a superuser to use pg_repack
-- => ERROR
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check
ERROR: pg_repack failed with error: ERROR: permission denied for schema repack
LINE 1: select repack.version(), repack.version_sql()
^
GRANT ALL ON ALL TABLES IN SCHEMA repack TO nosuper;
GRANT USAGE ON SCHEMA repack TO nosuper;
-- => ERROR
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check
INFO: repacking table "public.tbl_cluster"
ERROR: query failed: ERROR: current transaction is aborted, commands ignored until end of transaction block
DETAIL: query was: RESET lock_timeout
ERROR: query failed: ERROR: current transaction is aborted, commands ignored until end of transaction block
DETAIL: query was: RESET lock_timeout
ERROR: permission denied for relation tbl_cluster
ERROR: permission denied for relation tbl_cluster
REVOKE ALL ON ALL TABLES IN SCHEMA repack FROM nosuper;
REVOKE USAGE ON SCHEMA repack FROM nosuper;
DROP ROLE IF EXISTS nosuper;
9 changes: 9 additions & 0 deletions regress/sql/nosuper.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,13 @@ CREATE ROLE nosuper WITH LOGIN;
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper
-- => ERROR
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check

GRANT ALL ON ALL TABLES IN SCHEMA repack TO nosuper;
GRANT USAGE ON SCHEMA repack TO nosuper;

-- => ERROR
\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check

REVOKE ALL ON ALL TABLES IN SCHEMA repack FROM nosuper;
REVOKE USAGE ON SCHEMA repack FROM nosuper;
DROP ROLE IF EXISTS nosuper;

0 comments on commit ecbc587

Please sign in to comment.