user_signal-v2.patch
text/x-patch
Filename: user_signal-v2.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 0 | 0 |
| src/backend/utils/adt/misc.c | 0 | 0 |
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index e7f7fe0..f145c3f 100644
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
*************** SELECT set_config('log_statement_stats',
*** 14244,14251 ****
<para>
The functions shown in <xref
linkend="functions-admin-signal-table"> send control signals to
! other server processes. Use of these functions is restricted
! to superusers.
</para>
<table id="functions-admin-signal-table">
--- 14244,14251 ----
<para>
The functions shown in <xref
linkend="functions-admin-signal-table"> send control signals to
! other server processes. Use of these functions is usually restricted
! to superusers, with noted exceptions.
</para>
<table id="functions-admin-signal-table">
*************** SELECT set_config('log_statement_stats',
*** 14262,14268 ****
<literal><function>pg_cancel_backend(<parameter>pid</parameter> <type>int</>)</function></literal>
</entry>
<entry><type>boolean</type></entry>
! <entry>Cancel a backend's current query</entry>
</row>
<row>
<entry>
--- 14262,14271 ----
<literal><function>pg_cancel_backend(<parameter>pid</parameter> <type>int</>)</function></literal>
</entry>
<entry><type>boolean</type></entry>
! <entry>Cancel a backend's current query. You can execute this against
! another backend that has exactly the same role as the user calling the
! function. In all other cases, you must be a superuser.
! </entry>
</row>
<row>
<entry>
*************** SELECT set_config('log_statement_stats',
*** 14304,14309 ****
--- 14307,14316 ----
<command>postgres</command> processes on the server (using
<application>ps</> on Unix or the <application>Task
Manager</> on <productname>Windows</>).
+ For the more permissive <function>pg_cancel_backend</>, the role of an
+ active backend can be found from
+ the <structfield>usename</structfield> column of the
+ <structname>pg_stat_activity</structname> view.
</para>
<para>
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 7a2e0c8..b052149 100644
*** a/src/backend/utils/adt/misc.c
--- b/src/backend/utils/adt/misc.c
***************
*** 30,35 ****
--- 30,36 ----
#include "postmaster/syslogger.h"
#include "storage/fd.h"
#include "storage/pmsignal.h"
+ #include "storage/proc.h"
#include "storage/procarray.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
*************** current_query(PG_FUNCTION_ARGS)
*** 71,84 ****
/*
* Functions to send signals to other backends.
*/
static bool
pg_signal_backend(int pid, int sig)
{
! if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! (errmsg("must be superuser to signal other server processes"))));
if (!IsBackendPid(pid))
{
--- 72,115 ----
/*
* Functions to send signals to other backends.
+ *
+ * When calling pg_signal_backend, non-superusers are allowed to send signals
+ * to other backends if they are running as the same role. Make sure you're
+ * comfortable with that before using it for other types of signaling. If not,
+ * add your own checks first, as pg_terminate_backend does here.
*/
static bool
pg_signal_backend(int pid, int sig)
{
! PGPROC *proc;
! bool allowed = false;
!
! if (superuser())
! allowed = true;
! else
! {
! /*
! * Check for matching roles if we've already failed the superuser test.
! *
! * Trust that BackendPidGetProc will return NULL if the pid isn't valid,
! * even though the check for whether it's a backend process is below.
! * The IsBackendPid check can't be relied on as definitive even if it
! * was first. The process might end between successive checks
! * regardless of their order, and we don't want to acquire a lock just
! * just to eliminate that possibility. Since the signal being passed
! * might be a request for cancellation, this is not necessarily even a
! * problem.
! */
! proc = BackendPidGetProc(pid);
!
! if ((proc != NULL) && (proc->roleId == GetUserId()))
! allowed = true;
! }
!
! if (!allowed)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! (errmsg("must be superuser or have the same role to signal other server processes"))));
if (!IsBackendPid(pid))
{
*************** pg_cancel_backend(PG_FUNCTION_ARGS)
*** 115,120 ****
--- 146,161 ----
Datum
pg_terminate_backend(PG_FUNCTION_ARGS)
{
+ /*
+ * Since the permissions check for signaling isn't as strict as for
+ * termination, run the superuser only one here and suggest alternatives.
+ */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to terminate other server processes"),
+ errhint("you can use pg_cancel_backend() on your own processes")));
+
PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
}