aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/misc.c
diff options
context:
space:
mode:
authorStephen Frost <sfrost@snowman.net>2015-03-19 15:02:33 -0400
committerStephen Frost <sfrost@snowman.net>2015-03-19 15:02:33 -0400
commitbf038899965263dbc4aef2b43c8fdfe6f49b788f (patch)
treef69bedcc39eee9b9916047915de92e00d8448761 /src/backend/utils/adt/misc.c
parent12968cf4085409c50f70c6643d92befdb34008f6 (diff)
downloadpostgresql-bf038899965263dbc4aef2b43c8fdfe6f49b788f.tar.gz
postgresql-bf038899965263dbc4aef2b43c8fdfe6f49b788f.zip
GetUserId() changes to has_privs_of_role()
The pg_stat and pg_signal-related functions have been using GetUserId() instead of has_privs_of_role() for checking if the current user should be able to see details in pg_stat_activity or signal other processes, requiring a user to do 'SET ROLE' for inheirited roles for a permissions check, unlike other permissions checks. This patch changes that behavior to, instead, act like most other permission checks and use has_privs_of_role(), removing the 'SET ROLE' need. Documentation and error messages updated accordingly. Per discussion with Alvaro, Peter, Adam (though not using Adam's patch), and Robert. Reviewed by Jeevan Chalke.
Diffstat (limited to 'src/backend/utils/adt/misc.c')
-rw-r--r--src/backend/utils/adt/misc.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 29f7c3badfd..61d609f9181 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -37,6 +37,7 @@
#include "utils/lsyscache.h"
#include "utils/ruleutils.h"
#include "tcop/tcopprot.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/timestamp.h"
@@ -81,7 +82,9 @@ current_query(PG_FUNCTION_ARGS)
* role as the backend being signaled. For "dangerous" signals, an explicit
* check for superuser needs to be done prior to calling this function.
*
- * Returns 0 on success, 1 on general failure, and 2 on 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.
+ *
* 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
* the caller.
@@ -89,6 +92,7 @@ current_query(PG_FUNCTION_ARGS)
#define SIGNAL_BACKEND_SUCCESS 0
#define SIGNAL_BACKEND_ERROR 1
#define SIGNAL_BACKEND_NOPERMISSION 2
+#define SIGNAL_BACKEND_NOSUPERUSER 3
static int
pg_signal_backend(int pid, int sig)
{
@@ -113,7 +117,12 @@ pg_signal_backend(int pid, int sig)
return SIGNAL_BACKEND_ERROR;
}
- if (!(superuser() || proc->roleId == GetUserId()))
+ /* Only allow superusers to signal superuser-owned backends. */
+ if (superuser_arg(proc->roleId) && !superuser())
+ return SIGNAL_BACKEND_NOSUPERUSER;
+
+ /* Users can signal backends they have role membership in. */
+ if (!has_privs_of_role(GetUserId(), proc->roleId))
return SIGNAL_BACKEND_NOPERMISSION;
/*
@@ -141,35 +150,49 @@ pg_signal_backend(int pid, int sig)
}
/*
- * Signal to cancel a backend process. This is allowed if you are superuser or
- * have the same role as the process being canceled.
+ * Signal to cancel a backend process. This is allowed if you are a member of
+ * the role whose process is being canceled.
+ *
+ * Note that only superusers can signal superuser-owned processes.
*/
Datum
pg_cancel_backend(PG_FUNCTION_ARGS)
{
int r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
+ if (r == SIGNAL_BACKEND_NOSUPERUSER)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be a superuser to cancel superuser query"))));
+
if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser or have the same role to cancel queries running in other server processes"))));
+ (errmsg("must be a member of the role whose query is being cancelled"))));
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
}
/*
- * Signal to terminate a backend process. This is allowed if you are superuser
- * or have the same role as the process being terminated.
+ * Signal to terminate a backend process. This is allowed if you are a member
+ * of the role whose process is being terminated.
+ *
+ * Note that only superusers can signal superuser-owned processes.
*/
Datum
pg_terminate_backend(PG_FUNCTION_ARGS)
{
int r = pg_signal_backend(PG_GETARG_INT32(0), SIGTERM);
+ if (r == SIGNAL_BACKEND_NOSUPERUSER)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be a superuser to terminate superuser process"))));
+
if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser or have the same role to terminate other server processes"))));
+ (errmsg("must be a member of the role whose process is being terminated"))));
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
}