1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Introduce pg_signal_autovacuum_worker.

Since commit 3a9b18b309, roles with privileges of pg_signal_backend
cannot signal autovacuum workers.  Many users treated the ability
to signal autovacuum workers as a feature instead of a bug, so we
are reintroducing it via a new predefined role.  Having privileges
of this new role, named pg_signal_autovacuum_worker, only permits
signaling autovacuum workers.  It does not permit signaling other
types of superuser backends.

Bumps catversion.

Author: Kirill Reshke
Reviewed-by: Anthony Leung, Michael Paquier, Andrey Borodin
Discussion: https://postgr.es/m/CALdSSPhC4GGmbnugHfB9G0%3DfAxjCSug_-rmL9oUh0LTxsyBfsg%40mail.gmail.com
This commit is contained in:
Nathan Bossart
2024-07-09 13:03:40 -05:00
parent 629520be5f
commit ccd38024bc
5 changed files with 56 additions and 10 deletions

View File

@ -28163,6 +28163,10 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
calling role is a member of the role whose backend is being canceled or calling role is a member of the role whose backend is being canceled or
the calling role has privileges of <literal>pg_signal_backend</literal>, the calling role has privileges of <literal>pg_signal_backend</literal>,
however only superusers can cancel superuser backends. however only superusers can cancel superuser backends.
As an exception, roles with privileges of
<literal>pg_signal_autovacuum_worker</literal> are permitted to
cancel autovacuum worker processes, which are otherwise considered
superuser backends.
</para></entry> </para></entry>
</row> </row>
@ -28237,6 +28241,10 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
is a member of the role whose backend is being terminated or the is a member of the role whose backend is being terminated or the
calling role has privileges of <literal>pg_signal_backend</literal>, calling role has privileges of <literal>pg_signal_backend</literal>,
however only superusers can terminate superuser backends. however only superusers can terminate superuser backends.
As an exception, roles with privileges of
<literal>pg_signal_autovacuum_worker</literal> are permitted to
terminate autovacuum worker processes, which are otherwise considered
superuser backends.
</para> </para>
<para> <para>
If <parameter>timeout</parameter> is not specified or zero, this If <parameter>timeout</parameter> is not specified or zero, this

View File

@ -661,6 +661,11 @@ DROP ROLE doomed_role;
<entry>pg_signal_backend</entry> <entry>pg_signal_backend</entry>
<entry>Signal another backend to cancel a query or terminate its session.</entry> <entry>Signal another backend to cancel a query or terminate its session.</entry>
</row> </row>
<row>
<entry>pg_signal_autovacuum_worker</entry>
<entry>Signal an autovacuum worker to cancel the current table's vacuum
or terminate its session.</entry>
</row>
<row> <row>
<entry>pg_read_server_files</entry> <entry>pg_read_server_files</entry>
<entry>Allow reading files from any location the database can access on the server with COPY and <entry>Allow reading files from any location the database can access on the server with COPY and

View File

@ -34,8 +34,9 @@
* role as the backend being signaled. For "dangerous" signals, an explicit * role as the backend being signaled. For "dangerous" signals, an explicit
* check for superuser needs to be done prior to calling this function. * check for superuser needs to be done prior to calling this function.
* *
* Returns 0 on success, 1 on general failure, 2 on normal permission error * Returns 0 on success, 1 on general failure, 2 on normal permission error,
* and 3 if the caller needs to be a superuser. * 3 if the caller needs to be a superuser, and 4 if the caller needs to have
* privileges of pg_signal_autovacuum_worker.
* *
* In the event of a general failure (return code 1), a warning message will * In the event of a general failure (return code 1), a warning message will
* be emitted. For permission errors, doing that is the responsibility of * be emitted. For permission errors, doing that is the responsibility of
@ -45,6 +46,7 @@
#define SIGNAL_BACKEND_ERROR 1 #define SIGNAL_BACKEND_ERROR 1
#define SIGNAL_BACKEND_NOPERMISSION 2 #define SIGNAL_BACKEND_NOPERMISSION 2
#define SIGNAL_BACKEND_NOSUPERUSER 3 #define SIGNAL_BACKEND_NOSUPERUSER 3
#define SIGNAL_BACKEND_NOAUTOVAC 4
static int static int
pg_signal_backend(int pid, int sig) pg_signal_backend(int pid, int sig)
{ {
@ -77,15 +79,27 @@ pg_signal_backend(int pid, int sig)
/* /*
* Only allow superusers to signal superuser-owned backends. Any process * Only allow superusers to signal superuser-owned backends. Any process
* not advertising a role might have the importance of a superuser-owned * not advertising a role might have the importance of a superuser-owned
* backend, so treat it that way. * backend, so treat it that way. As an exception, we allow roles with
* privileges of pg_signal_autovacuum_worker to signal autovacuum workers
* (which do not advertise a role).
*
* Otherwise, users can signal backends for roles they have privileges of.
*/ */
if ((!OidIsValid(proc->roleId) || superuser_arg(proc->roleId)) && if (!OidIsValid(proc->roleId) || superuser_arg(proc->roleId))
!superuser()) {
return SIGNAL_BACKEND_NOSUPERUSER; ProcNumber procNumber = GetNumberFromPGProc(proc);
PgBackendStatus *procStatus = pgstat_get_beentry_by_proc_number(procNumber);
/* Users can signal backends they have role membership in. */ if (procStatus && procStatus->st_backendType == B_AUTOVAC_WORKER)
if (!has_privs_of_role(GetUserId(), proc->roleId) && {
!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND)) if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM_WORKER))
return SIGNAL_BACKEND_NOAUTOVAC;
}
else if (!superuser())
return SIGNAL_BACKEND_NOSUPERUSER;
}
else if (!has_privs_of_role(GetUserId(), proc->roleId) &&
!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
return SIGNAL_BACKEND_NOPERMISSION; return SIGNAL_BACKEND_NOPERMISSION;
/* /*
@ -130,6 +144,13 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
errdetail("Only roles with the %s attribute may cancel queries of roles with the %s attribute.", errdetail("Only roles with the %s attribute may cancel queries of roles with the %s attribute.",
"SUPERUSER", "SUPERUSER"))); "SUPERUSER", "SUPERUSER")));
if (r == SIGNAL_BACKEND_NOAUTOVAC)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to cancel query"),
errdetail("Only roles with privileges of the \"%s\" role may cancel autovacuum workers.",
"pg_signal_autovacuum_worker")));
if (r == SIGNAL_BACKEND_NOPERMISSION) if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@ -236,6 +257,13 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.", errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
"SUPERUSER", "SUPERUSER"))); "SUPERUSER", "SUPERUSER")));
if (r == SIGNAL_BACKEND_NOAUTOVAC)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to terminate process"),
errdetail("Only roles with privileges of the \"%s\" role may terminate autovacuum workers.",
"pg_signal_autovacuum_worker")));
if (r == SIGNAL_BACKEND_NOPERMISSION) if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),

View File

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202407082 #define CATALOG_VERSION_NO 202407091
#endif #endif

View File

@ -99,5 +99,10 @@
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
rolpassword => '_null_', rolvaliduntil => '_null_' }, rolpassword => '_null_', rolvaliduntil => '_null_' },
{ oid => '8916', oid_symbol => 'ROLE_PG_SIGNAL_AUTOVACUUM_WORKER',
rolname => 'pg_signal_autovacuum_worker', rolsuper => 'f', rolinherit => 't',
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
rolpassword => '_null_', rolvaliduntil => '_null_' },
] ]