Skip to content

Commit 7654169

Browse files
committed
Implement function privilege separation
1 parent 85794a1 commit 7654169

File tree

1 file changed

+60
-19
lines changed

1 file changed

+60
-19
lines changed

pg_show_plans.c

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,19 @@
1212

1313
/* Includes */
1414
#include "postgres.h"
15-
/* Comments just indicate which includes are still in use. */
16-
#include "commands/explain.h" /* To explain statements. */
17-
#include "fmgr.h" /* PG_RETURN_VOID() */
18-
#include "funcapi.h" /* To return sets in SQL funcs. */
19-
#include "lib/stringinfo.h" /* StringInfo */
20-
#include "miscadmin.h" /* process_shared_preload_libraries_in_progress */
21-
#include "storage/ipc.h" /* shmem_startup_hook_type */
22-
#include "storage/lwlock.h" /* Locking mechanism, for shared data safety. */
23-
#include "storage/shmem.h" /* RequestAddinShmemSpace() */
24-
#include "utils/builtins.h" /* CStringGetTextDatum() */
25-
#include "utils/guc.h" /* For GUC variables. */
2615

16+
#include "catalog/pg_authid.h"
17+
#include "commands/explain.h"
18+
#include "fmgr.h"
19+
#include "funcapi.h"
20+
#include "lib/stringinfo.h"
21+
#include "miscadmin.h"
22+
#include "storage/ipc.h"
23+
#include "storage/lwlock.h"
24+
#include "storage/shmem.h"
25+
#include "utils/acl.h"
26+
#include "utils/builtins.h"
27+
#include "utils/guc.h"
2728

2829
/* Constants and Macros */
2930
PG_MODULE_MAGIC;
@@ -83,6 +84,12 @@ static pgspEntry *create_hash_entry(const pgspHashKey *key);
8384
static void append_query_plan(ExplainState *es);
8485
/* on_shmem_exit() callback to delete hash entry on client disconnect. */
8586
static void cleanup(int code, Datum arg);
87+
/* Set extension state, either enable or disable. */
88+
static void set_state(const bool state);
89+
/* Set query plan output format: text, json, ... */
90+
static void set_format(const int format);
91+
/* Check whether the user has required privileges. */
92+
static bool is_allowed_role(void);
8693
/* Hook functions. */
8794
/* Ask for shared memory. */
8895
#if PG_VERSION_NUM >= 150000
@@ -314,6 +321,33 @@ void cleanup(int code, Datum arg)
314321
LWLockRelease(pgsp->lock);
315322
}
316323

324+
void
325+
set_state(const bool state)
326+
{
327+
if (is_allowed_role())
328+
pgsp->is_enabled = state;
329+
}
330+
331+
void
332+
set_format(const int format)
333+
{
334+
if (is_allowed_role())
335+
pgsp->plan_format = format;
336+
}
337+
338+
bool
339+
is_allowed_role(void)
340+
{
341+
bool is_allowed_role = false;
342+
#if PG_VERSION_NUM >= 140000
343+
is_allowed_role = is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS);
344+
#else
345+
is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
346+
#endif
347+
return is_allowed_role;
348+
349+
}
350+
317351
#if PG_VERSION_NUM >= 150000
318352
void
319353
pgvp_shmem_request(void)
@@ -431,42 +465,42 @@ pgsp_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction,
431465
Datum
432466
pg_show_plans_enable(PG_FUNCTION_ARGS)
433467
{
434-
pgsp->is_enabled = true;
468+
set_state(true);
435469
PG_RETURN_VOID();
436470
}
437471

438472
Datum
439473
pg_show_plans_disable(PG_FUNCTION_ARGS)
440474
{
441-
pgsp->is_enabled = false;
475+
set_state(false);
442476
PG_RETURN_VOID();
443477
}
444478

445479
Datum
446480
pgsp_format_text(PG_FUNCTION_ARGS)
447481
{
448-
pgsp->plan_format = EXPLAIN_FORMAT_TEXT;
482+
set_format(EXPLAIN_FORMAT_TEXT);
449483
PG_RETURN_VOID();
450484
}
451485

452486
Datum
453487
pgsp_format_json(PG_FUNCTION_ARGS)
454488
{
455-
pgsp->plan_format = EXPLAIN_FORMAT_JSON;
489+
set_format(EXPLAIN_FORMAT_JSON);
456490
PG_RETURN_VOID();
457491
}
458492

459493
Datum
460494
pgsp_format_yaml(PG_FUNCTION_ARGS)
461495
{
462-
pgsp->plan_format = EXPLAIN_FORMAT_YAML;
496+
set_format(EXPLAIN_FORMAT_YAML);
463497
PG_RETURN_VOID();
464498
}
465499

466500
Datum
467501
pgsp_format_xml(PG_FUNCTION_ARGS)
468502
{
469-
pgsp->plan_format = EXPLAIN_FORMAT_XML;
503+
set_format(EXPLAIN_FORMAT_XML);
470504
PG_RETURN_VOID();
471505
}
472506

@@ -530,8 +564,15 @@ pg_show_plans(PG_FUNCTION_ARGS)
530564
if (is_done) /* Done processing a hash entry? */
531565
{ /* Grab a new one. */
532566
pgvp_tmp_entry = hash_seq_search(hash_seq);
533-
/* Skip empty entries. */
534-
while (pgvp_tmp_entry->n_plans < 1) {
567+
/* Skip empty entries and the ones the user is not
568+
* allowed to see. */
569+
for (;;) {
570+
if (pgvp_tmp_entry->n_plans >= 1) {
571+
if (is_allowed_role())
572+
break;
573+
else if (pgvp_tmp_entry->user_id == GetUserId())
574+
break;
575+
}
535576
if (call_cntr == max_calls-1) { /* No more entries. */
536577
hash_seq_term(hash_seq);
537578
LWLockRelease(pgsp->lock);

0 commit comments

Comments
 (0)