|
34 | 34 | * role as the backend being signaled. For "dangerous" signals, an explicit
|
35 | 35 | * check for superuser needs to be done prior to calling this function.
|
36 | 36 | *
|
37 |
| - * Returns 0 on success, 1 on general failure, 2 on normal permission error |
38 |
| - * and 3 if the caller needs to be a superuser. |
| 37 | + * Returns 0 on success, 1 on general failure, 2 on normal permission error, |
| 38 | + * 3 if the caller needs to be a superuser, and 4 if the caller needs to have |
| 39 | + * privileges of pg_signal_autovacuum_worker. |
39 | 40 | *
|
40 | 41 | * In the event of a general failure (return code 1), a warning message will
|
41 | 42 | * be emitted. For permission errors, doing that is the responsibility of
|
|
45 | 46 | #define SIGNAL_BACKEND_ERROR 1
|
46 | 47 | #define SIGNAL_BACKEND_NOPERMISSION 2
|
47 | 48 | #define SIGNAL_BACKEND_NOSUPERUSER 3
|
| 49 | +#define SIGNAL_BACKEND_NOAUTOVAC 4 |
48 | 50 | static int
|
49 | 51 | pg_signal_backend(int pid, int sig)
|
50 | 52 | {
|
@@ -77,15 +79,27 @@ pg_signal_backend(int pid, int sig)
|
77 | 79 | /*
|
78 | 80 | * Only allow superusers to signal superuser-owned backends. Any process
|
79 | 81 | * not advertising a role might have the importance of a superuser-owned
|
80 |
| - * backend, so treat it that way. |
| 82 | + * backend, so treat it that way. As an exception, we allow roles with |
| 83 | + * privileges of pg_signal_autovacuum_worker to signal autovacuum workers |
| 84 | + * (which do not advertise a role). |
| 85 | + * |
| 86 | + * Otherwise, users can signal backends for roles they have privileges of. |
81 | 87 | */
|
82 |
| - if ((!OidIsValid(proc->roleId) || superuser_arg(proc->roleId)) && |
83 |
| - !superuser()) |
84 |
| - return SIGNAL_BACKEND_NOSUPERUSER; |
| 88 | + if (!OidIsValid(proc->roleId) || superuser_arg(proc->roleId)) |
| 89 | + { |
| 90 | + ProcNumber procNumber = GetNumberFromPGProc(proc); |
| 91 | + PgBackendStatus *procStatus = pgstat_get_beentry_by_proc_number(procNumber); |
85 | 92 |
|
86 |
| - /* Users can signal backends they have role membership in. */ |
87 |
| - if (!has_privs_of_role(GetUserId(), proc->roleId) && |
88 |
| - !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND)) |
| 93 | + if (procStatus && procStatus->st_backendType == B_AUTOVAC_WORKER) |
| 94 | + { |
| 95 | + if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM_WORKER)) |
| 96 | + return SIGNAL_BACKEND_NOAUTOVAC; |
| 97 | + } |
| 98 | + else if (!superuser()) |
| 99 | + return SIGNAL_BACKEND_NOSUPERUSER; |
| 100 | + } |
| 101 | + else if (!has_privs_of_role(GetUserId(), proc->roleId) && |
| 102 | + !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND)) |
89 | 103 | return SIGNAL_BACKEND_NOPERMISSION;
|
90 | 104 |
|
91 | 105 | /*
|
@@ -130,6 +144,13 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
|
130 | 144 | errdetail("Only roles with the %s attribute may cancel queries of roles with the %s attribute.",
|
131 | 145 | "SUPERUSER", "SUPERUSER")));
|
132 | 146 |
|
| 147 | + if (r == SIGNAL_BACKEND_NOAUTOVAC) |
| 148 | + ereport(ERROR, |
| 149 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 150 | + errmsg("permission denied to cancel query"), |
| 151 | + errdetail("Only roles with privileges of the \"%s\" role may cancel autovacuum workers.", |
| 152 | + "pg_signal_autovacuum_worker"))); |
| 153 | + |
133 | 154 | if (r == SIGNAL_BACKEND_NOPERMISSION)
|
134 | 155 | ereport(ERROR,
|
135 | 156 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
@@ -236,6 +257,13 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
|
236 | 257 | errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
|
237 | 258 | "SUPERUSER", "SUPERUSER")));
|
238 | 259 |
|
| 260 | + if (r == SIGNAL_BACKEND_NOAUTOVAC) |
| 261 | + ereport(ERROR, |
| 262 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 263 | + errmsg("permission denied to terminate process"), |
| 264 | + errdetail("Only roles with privileges of the \"%s\" role may terminate autovacuum workers.", |
| 265 | + "pg_signal_autovacuum_worker"))); |
| 266 | + |
239 | 267 | if (r == SIGNAL_BACKEND_NOPERMISSION)
|
240 | 268 | ereport(ERROR,
|
241 | 269 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
0 commit comments