Skip to content

Commit 151c22d

Browse files
Revert MAINTAIN privilege and pg_maintain predefined role.
This reverts the following commits: 4dbdb82, c2122aa, 5b1a879, 9e1e9d6, ff9618e, 60684dd, 4441fc7, and b5d6382. A role with the MAINTAIN privilege may be able to use search_path tricks to escalate privileges to the table owner. Unfortunately, it is too late in the v16 development cycle to apply the proposed fix, i.e., restricting search_path when running maintenance commands. Bumps catversion. Reviewed-by: Jeff Davis Discussion: https://postgr.es/m/E1q7j7Y-000z1H-Hr%40gemulon.postgresql.org Backpatch-through: 16
1 parent ec99d6e commit 151c22d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+179
-445
lines changed

doc/src/sgml/ddl.sgml

+9-26
Original file line numberDiff line numberDiff line change
@@ -1718,8 +1718,8 @@ ALTER TABLE products RENAME TO items;
17181718
<literal>INSERT</literal>, <literal>UPDATE</literal>, <literal>DELETE</literal>,
17191719
<literal>TRUNCATE</literal>, <literal>REFERENCES</literal>, <literal>TRIGGER</literal>,
17201720
<literal>CREATE</literal>, <literal>CONNECT</literal>, <literal>TEMPORARY</literal>,
1721-
<literal>EXECUTE</literal>, <literal>USAGE</literal>, <literal>SET</literal>,
1722-
<literal>ALTER SYSTEM</literal>, and <literal>MAINTAIN</literal>.
1721+
<literal>EXECUTE</literal>, <literal>USAGE</literal>, <literal>SET</literal>
1722+
and <literal>ALTER SYSTEM</literal>.
17231723
The privileges applicable to a particular
17241724
object vary depending on the object's type (table, function, etc.).
17251725
More detail about the meanings of these privileges appears below.
@@ -2010,19 +2010,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
20102010
</para>
20112011
</listitem>
20122012
</varlistentry>
2013-
2014-
<varlistentry id="ddl-priv-maintain">
2015-
<term><literal>MAINTAIN</literal></term>
2016-
<listitem>
2017-
<para>
2018-
Allows <command>VACUUM</command>, <command>ANALYZE</command>,
2019-
<command>CLUSTER</command>, <command>REFRESH MATERIALIZED VIEW</command>,
2020-
<command>REINDEX</command>, and <command>LOCK TABLE</command> on a
2021-
relation.
2022-
</para>
2023-
</listitem>
2024-
</varlistentry>
2025-
</variablelist>
2013+
</variablelist>
20262014

20272015
The privileges required by other commands are listed on the
20282016
reference page of the respective command.
@@ -2171,11 +2159,6 @@ REVOKE ALL ON accounts FROM PUBLIC;
21712159
<entry><literal>A</literal></entry>
21722160
<entry><literal>PARAMETER</literal></entry>
21732161
</row>
2174-
<row>
2175-
<entry><literal>MAINTAIN</literal></entry>
2176-
<entry><literal>m</literal></entry>
2177-
<entry><literal>TABLE</literal></entry>
2178-
</row>
21792162
</tbody>
21802163
</tgroup>
21812164
</table>
@@ -2266,7 +2249,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
22662249
</row>
22672250
<row>
22682251
<entry><literal>TABLE</literal> (and table-like objects)</entry>
2269-
<entry><literal>arwdDxtm</literal></entry>
2252+
<entry><literal>arwdDxt</literal></entry>
22702253
<entry>none</entry>
22712254
<entry><literal>\dp</literal></entry>
22722255
</row>
@@ -2325,11 +2308,11 @@ GRANT SELECT (col1), UPDATE (col1) ON mytable TO miriam_rw;
23252308
<programlisting>
23262309
=&gt; \dp mytable
23272310
Access privileges
2328-
Schema | Name | Type | Access privileges | Column privileges | Policies
2329-
--------+---------+-------+------------------------+-----------------------+----------
2330-
public | mytable | table | miriam=arwdDxtm/miriam+| col1: +|
2331-
| | | =r/miriam +| miriam_rw=rw/miriam |
2332-
| | | admin=arw/miriam | |
2311+
Schema | Name | Type | Access privileges | Column privileges | Policies
2312+
--------+---------+-------+-----------------------+-----------------------+----------
2313+
public | mytable | table | miriam=arwdDxt/miriam+| col1: +|
2314+
| | | =r/miriam +| miriam_rw=rw/miriam |
2315+
| | | admin=arw/miriam | |
23332316
(1 row)
23342317
</programlisting>
23352318
</para>

doc/src/sgml/func.sgml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23545,7 +23545,7 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
2354523545
are <literal>SELECT</literal>, <literal>INSERT</literal>,
2354623546
<literal>UPDATE</literal>, <literal>DELETE</literal>,
2354723547
<literal>TRUNCATE</literal>, <literal>REFERENCES</literal>,
23548-
<literal>TRIGGER</literal>, and <literal>MAINTAIN</literal>.
23548+
and <literal>TRIGGER</literal>.
2354923549
</para></entry>
2355023550
</row>
2355123551

doc/src/sgml/ref/alter_default_privileges.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ALTER DEFAULT PRIVILEGES
2828

2929
<phrase>where <replaceable class="parameter">abbreviated_grant_or_revoke</replaceable> is one of:</phrase>
3030

31-
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
31+
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
3232
[, ...] | ALL [ PRIVILEGES ] }
3333
ON TABLES
3434
TO { [ GROUP ] <replaceable class="parameter">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
@@ -51,7 +51,7 @@ GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] }
5151
TO { [ GROUP ] <replaceable class="parameter">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
5252

5353
REVOKE [ GRANT OPTION FOR ]
54-
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
54+
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
5555
[, ...] | ALL [ PRIVILEGES ] }
5656
ON TABLES
5757
FROM { [ GROUP ] <replaceable class="parameter">role_name</replaceable> | PUBLIC } [, ...]

doc/src/sgml/ref/analyze.sgml

+4-2
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,11 @@ ANALYZE [ VERBOSE ] [ <replaceable class="parameter">table_and_columns</replacea
182182
<title>Notes</title>
183183

184184
<para>
185-
To analyze a table, one must ordinarily have the <literal>MAINTAIN</literal>
186-
privilege on the table. However, database owners are allowed to
185+
To analyze a table, one must ordinarily be the table's owner or a
186+
superuser. However, database owners are allowed to
187187
analyze all tables in their databases, except shared catalogs.
188+
(The restriction for shared catalogs means that a true database-wide
189+
<command>ANALYZE</command> can only be performed by a superuser.)
188190
<command>ANALYZE</command> will skip over any tables that the calling user
189191
does not have permission to analyze.
190192
</para>

doc/src/sgml/ref/cluster.sgml

+3-7
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ CLUSTER [VERBOSE]
7070
<command>CLUSTER</command> without a
7171
<replaceable class="parameter">table_name</replaceable> reclusters all the
7272
previously-clustered tables in the current database that the calling user
73-
has privileges for. This form of <command>CLUSTER</command> cannot be
74-
executed inside a transaction block.
73+
owns, or all such tables if called by a superuser. This
74+
form of <command>CLUSTER</command> cannot be executed inside a transaction
75+
block.
7576
</para>
7677

7778
<para>
@@ -132,11 +133,6 @@ CLUSTER [VERBOSE]
132133
<refsect1>
133134
<title>Notes</title>
134135

135-
<para>
136-
To cluster a table, one must have the <literal>MAINTAIN</literal> privilege
137-
on the table.
138-
</para>
139-
140136
<para>
141137
In cases where you are accessing single rows randomly
142138
within a table, the actual order of the data in the

doc/src/sgml/ref/grant.sgml

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ PostgreSQL documentation
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
24+
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
2525
[, ...] | ALL [ PRIVILEGES ] }
2626
ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...]
2727
| ALL TABLES IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] }
@@ -193,7 +193,6 @@ GRANT <replaceable class="parameter">role_name</replaceable> [, ...] TO <replace
193193
<term><literal>USAGE</literal></term>
194194
<term><literal>SET</literal></term>
195195
<term><literal>ALTER SYSTEM</literal></term>
196-
<term><literal>MAINTAIN</literal></term>
197196
<listitem>
198197
<para>
199198
Specific types of privileges, as defined in <xref linkend="ddl-priv"/>.

doc/src/sgml/ref/lock.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
166166

167167
<para>
168168
To lock a table, the user must have the right privilege for the specified
169-
<replaceable class="parameter">lockmode</replaceable>.
170-
If the user has <literal>MAINTAIN</literal>,
169+
<replaceable class="parameter">lockmode</replaceable>, or be the table's
170+
owner or a superuser. If the user has
171171
<literal>UPDATE</literal>, <literal>DELETE</literal>, or
172172
<literal>TRUNCATE</literal> privileges on the table, any <replaceable
173173
class="parameter">lockmode</replaceable> is permitted. If the user has

doc/src/sgml/ref/refresh_materialized_view.sgml

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] <replaceable class="parameter">name</
3131

3232
<para>
3333
<command>REFRESH MATERIALIZED VIEW</command> completely replaces the
34-
contents of a materialized view. To execute this command you must have the
35-
<literal>MAINTAIN</literal>
36-
privilege on the materialized view. The old contents are discarded. If
34+
contents of a materialized view. To execute this command you must be the
35+
owner of the materialized view. The old contents are discarded. If
3736
<literal>WITH DATA</literal> is specified (or defaults) the backing query
3837
is executed to provide the new data, and the materialized view is left in a
3938
scannable state. If <literal>WITH NO DATA</literal> is specified no new

doc/src/sgml/ref/reindex.sgml

+9-14
Original file line numberDiff line numberDiff line change
@@ -292,21 +292,16 @@ REINDEX [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] { DA
292292
</para>
293293

294294
<para>
295-
Reindexing a single index or table requires
296-
having the <literal>MAINTAIN</literal> privilege on the
297-
table. Note that while <command>REINDEX</command> on a partitioned index or
298-
table requires having the <literal>MAINTAIN</literal> privilege on the
299-
partitioned table, such commands skip the privilege checks when processing
300-
the individual partitions. Reindexing a schema or database requires being the
301-
owner of that schema or database or having privileges of the
302-
<link linkend="predefined-roles-table"><literal>pg_maintain</literal></link>
303-
role. Note specifically that it's thus
295+
Reindexing a single index or table requires being the owner of that
296+
index or table. Reindexing a schema or database requires being the
297+
owner of that schema or database. Note specifically that it's thus
304298
possible for non-superusers to rebuild indexes of tables owned by
305-
other users. However, as a special exception,
306-
<command>REINDEX DATABASE</command>, <command>REINDEX SCHEMA</command>,
307-
and <command>REINDEX SYSTEM</command> will skip indexes on shared catalogs
308-
unless the user has the <literal>MAINTAIN</literal> privilege on the
309-
catalog.
299+
other users. However, as a special exception, when
300+
<command>REINDEX DATABASE</command>, <command>REINDEX SCHEMA</command>
301+
or <command>REINDEX SYSTEM</command> is issued by a non-superuser,
302+
indexes on shared catalogs will be skipped unless the user owns the
303+
catalog (which typically won't be the case). Of course, superusers
304+
can always reindex anything.
310305
</para>
311306

312307
<para>

doc/src/sgml/ref/revoke.sgml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ PostgreSQL documentation
2222
<refsynopsisdiv>
2323
<synopsis>
2424
REVOKE [ GRANT OPTION FOR ]
25-
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
25+
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
2626
[, ...] | ALL [ PRIVILEGES ] }
2727
ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...]
2828
| ALL TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }

doc/src/sgml/ref/vacuum.sgml

+4-2
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,11 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="paramet
444444
<title>Notes</title>
445445

446446
<para>
447-
To vacuum a table, one must ordinarily have the <literal>MAINTAIN</literal>
448-
privilege on the table. However, database owners are allowed to
447+
To vacuum a table, one must ordinarily be the table's owner or a
448+
superuser. However, database owners are allowed to
449449
vacuum all tables in their databases, except shared catalogs.
450+
(The restriction for shared catalogs means that a true database-wide
451+
<command>VACUUM</command> can only be performed by a superuser.)
450452
<command>VACUUM</command> will skip over any tables that the calling user
451453
does not have permission to vacuum.
452454
</para>

doc/src/sgml/user-manag.sgml

-12
Original file line numberDiff line numberDiff line change
@@ -683,18 +683,6 @@ DROP ROLE doomed_role;
683683
the <link linkend="sql-checkpoint"><command>CHECKPOINT</command></link>
684684
command.</entry>
685685
</row>
686-
<row>
687-
<entry>pg_maintain</entry>
688-
<entry>Allow executing
689-
<link linkend="sql-vacuum"><command>VACUUM</command></link>,
690-
<link linkend="sql-analyze"><command>ANALYZE</command></link>,
691-
<link linkend="sql-cluster"><command>CLUSTER</command></link>,
692-
<link linkend="sql-refreshmaterializedview"><command>REFRESH MATERIALIZED VIEW</command></link>,
693-
<link linkend="sql-reindex"><command>REINDEX</command></link>,
694-
and <link linkend="sql-lock"><command>LOCK TABLE</command></link> on all
695-
relations, as if having <literal>MAINTAIN</literal> rights on those
696-
objects, even without having it explicitly.</entry>
697-
</row>
698686
<row>
699687
<entry>pg_use_reserved_connections</entry>
700688
<entry>Allow use of connection slots reserved via

src/backend/catalog/aclchk.c

-15
Original file line numberDiff line numberDiff line change
@@ -2612,8 +2612,6 @@ string_to_privilege(const char *privname)
26122612
return ACL_SET;
26132613
if (strcmp(privname, "alter system") == 0)
26142614
return ACL_ALTER_SYSTEM;
2615-
if (strcmp(privname, "maintain") == 0)
2616-
return ACL_MAINTAIN;
26172615
if (strcmp(privname, "rule") == 0)
26182616
return 0; /* ignore old RULE privileges */
26192617
ereport(ERROR,
@@ -2655,8 +2653,6 @@ privilege_to_string(AclMode privilege)
26552653
return "SET";
26562654
case ACL_ALTER_SYSTEM:
26572655
return "ALTER SYSTEM";
2658-
case ACL_MAINTAIN:
2659-
return "MAINTAIN";
26602656
default:
26612657
elog(ERROR, "unrecognized privilege: %d", (int) privilege);
26622658
}
@@ -3388,17 +3384,6 @@ pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
33883384
has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
33893385
result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
33903386

3391-
/*
3392-
* Check if ACL_MAINTAIN is being checked and, if so, and not already set
3393-
* as part of the result, then check if the user is a member of the
3394-
* pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH
3395-
* MATERIALIZED VIEW, and REINDEX on all relations.
3396-
*/
3397-
if (mask & ACL_MAINTAIN &&
3398-
!(result & ACL_MAINTAIN) &&
3399-
has_privs_of_role(roleid, ROLE_PG_MAINTAIN))
3400-
result |= ACL_MAINTAIN;
3401-
34023387
return result;
34033388
}
34043389

src/backend/commands/analyze.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,16 @@ analyze_rel(Oid relid, RangeVar *relation,
159159
return;
160160

161161
/*
162-
* Check if relation needs to be skipped based on privileges. This check
162+
* Check if relation needs to be skipped based on ownership. This check
163163
* happens also when building the relation list to analyze for a manual
164164
* operation, and needs to be done additionally here as ANALYZE could
165-
* happen across multiple transactions where privileges could have changed
166-
* in-between. Make sure to generate only logs for ANALYZE in this case.
165+
* happen across multiple transactions where relation ownership could have
166+
* changed in-between. Make sure to generate only logs for ANALYZE in
167+
* this case.
167168
*/
168-
if (!vacuum_is_permitted_for_relation(RelationGetRelid(onerel),
169-
onerel->rd_rel,
170-
params->options & ~VACOPT_VACUUM))
169+
if (!vacuum_is_relation_owner(RelationGetRelid(onerel),
170+
onerel->rd_rel,
171+
params->options & VACOPT_ANALYZE))
171172
{
172173
relation_close(onerel, ShareUpdateExclusiveLock);
173174
return;

0 commit comments

Comments
 (0)