Use has_privs_for_roles for predefined role checks

Generally if a role is granted membership to another role with NOINHERIT
they must use SET ROLE to access the privileges of that role, however
with predefined roles the membership and privilege is conflated. Fix that
by replacing is_member_of_role with has_privs_for_role for predefined
roles. Patch does not remove is_member_of_role from acl.h, but it does
add a warning not to use that function for privilege checking. Not
backpatched based on hackers list discussion.

Author: Joshua Brindle
Reviewed-by: Stephen Frost, Nathan Bossart, Joe Conway
Discussion: https://postgr.es/m/flat/CAGB+Vh4Zv_TvKt2tv3QNS6tUM_F_9icmuj0zjywwcgVi4PAhFA@mail.gmail.com
This commit is contained in:
Joe Conway 2022-03-28 15:10:04 -04:00
parent 79de9842ab
commit 6198420ad8
23 changed files with 68 additions and 64 deletions

View File

@ -79,7 +79,7 @@ convert_and_check_filename(text *arg)
* files on the server as the PG user, so no need to do any further checks * files on the server as the PG user, so no need to do any further checks
* here. * here.
*/ */
if (is_member_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) if (has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
return filename; return filename;
/* /*

View File

@ -459,7 +459,7 @@ ALTER FOREIGN TABLE agg_text OWNER TO regress_file_fdw_user;
ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text'); ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
SET ROLE regress_file_fdw_user; SET ROLE regress_file_fdw_user;
ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text'); ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
ERROR: only superuser or a member of the pg_read_server_files role may specify the filename option of a file_fdw foreign table ERROR: only superuser or a role with privileges of the pg_read_server_files role may specify the filename option of a file_fdw foreign table
SET ROLE regress_file_fdw_superuser; SET ROLE regress_file_fdw_superuser;
-- cleanup -- cleanup
RESET ROLE; RESET ROLE;

View File

@ -269,16 +269,16 @@ file_fdw_validator(PG_FUNCTION_ARGS)
* otherwise there'd still be a security hole. * otherwise there'd still be a security hole.
*/ */
if (strcmp(def->defname, "filename") == 0 && if (strcmp(def->defname, "filename") == 0 &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("only superuser or a member of the pg_read_server_files role may specify the filename option of a file_fdw foreign table"))); errmsg("only superuser or a role with privileges of the pg_read_server_files role may specify the filename option of a file_fdw foreign table")));
if (strcmp(def->defname, "program") == 0 && if (strcmp(def->defname, "program") == 0 &&
!is_member_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM)) !has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("only superuser or a member of the pg_execute_server_program role may specify the program option of a file_fdw foreign table"))); errmsg("only superuser or a role with privileges of the pg_execute_server_program role may specify the program option of a file_fdw foreign table")));
filename = defGetString(def); filename = defGetString(def);
} }

View File

@ -1503,8 +1503,8 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
HASH_SEQ_STATUS hash_seq; HASH_SEQ_STATUS hash_seq;
pgssEntry *entry; pgssEntry *entry;
/* Superusers or members of pg_read_all_stats members are allowed */ /* Superusers or roles with the privileges of pg_read_all_stats members are allowed */
is_allowed_role = is_member_of_role(userid, ROLE_PG_READ_ALL_STATS); is_allowed_role = has_privs_of_role(userid, ROLE_PG_READ_ALL_STATS);
/* hash table must exist already */ /* hash table must exist already */
if (!pgss || !pgss_hash) if (!pgss || !pgss_hash)

View File

@ -104,7 +104,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_SELECT); ACL_SELECT);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclresult = is_member_of_role(GetUserId(), ROLE_PG_STAT_SCAN_TABLES) ? ACLCHECK_OK : ACLCHECK_NO_PRIV; aclresult = has_privs_of_role(GetUserId(), ROLE_PG_STAT_SCAN_TABLES) ? ACLCHECK_OK : ACLCHECK_NO_PRIV;
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind), aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),

View File

@ -22,9 +22,9 @@
functions in <xref linkend="functions-admin-genfile-table"/>, which functions in <xref linkend="functions-admin-genfile-table"/>, which
provide read-only access.) provide read-only access.)
Only files within the database cluster directory can be accessed, unless the Only files within the database cluster directory can be accessed, unless the
user is a superuser or given one of the pg_read_server_files, or pg_write_server_files user is a superuser or given privileges of one of the pg_read_server_files,
roles, as appropriate for the function, but either a relative or absolute path is or pg_write_server_files roles, as appropriate for the function, but either a
allowable. relative or absolute path is allowable.
</para> </para>
<table id="functions-adminpack-table"> <table id="functions-adminpack-table">

View File

@ -10044,8 +10044,8 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
<para> <para>
By default, the <structname>pg_backend_memory_contexts</structname> view can be By default, the <structname>pg_backend_memory_contexts</structname> view can be
read only by superusers or members of the <literal>pg_read_all_stats</literal> read only by superusers or roles with the privileges of the
role. <literal>pg_read_all_stats</literal> role.
</para> </para>
</sect1> </sect1>
@ -12552,7 +12552,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<para> <para>
Configuration file the current value was set in (null for Configuration file the current value was set in (null for
values set from sources other than configuration files, or when values set from sources other than configuration files, or when
examined by a user who is neither a superuser or a member of examined by a user who neither is a superuser nor has privileges of
<literal>pg_read_all_settings</literal>); helpful when using <literal>pg_read_all_settings</literal>); helpful when using
<literal>include</literal> directives in configuration files <literal>include</literal> directives in configuration files
</para></entry> </para></entry>
@ -12565,7 +12565,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<para> <para>
Line number within the configuration file the current value was Line number within the configuration file the current value was
set at (null for values set from sources other than configuration files, set at (null for values set from sources other than configuration files,
or when examined by a user who is neither a superuser or a member of or when examined by a user who neither is a superuser nor has privileges of
<literal>pg_read_all_settings</literal>). <literal>pg_read_all_settings</literal>).
</para></entry> </para></entry>
</row> </row>
@ -12941,8 +12941,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<para> <para>
By default, the <structname>pg_shmem_allocations</structname> view can be By default, the <structname>pg_shmem_allocations</structname> view can be
read only by superusers or members of the <literal>pg_read_all_stats</literal> read only by superusers or roles with privileges of the
role. <literal>pg_read_all_stats</literal> role.
</para> </para>
</sect1> </sect1>

View File

@ -25435,7 +25435,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
Cancels the current query of the session whose backend process has the Cancels the current query of the session whose backend process has the
specified process ID. This is also allowed if the specified process ID. This is also allowed if the
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 been granted <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.
</para></entry> </para></entry>
</row> </row>
@ -25508,7 +25508,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
Terminates the session whose backend process has the Terminates the session whose backend process has the
specified process ID. This is also allowed if the calling role specified process ID. This is also allowed if the calling role
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 been granted <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.
</para> </para>
<para> <para>
@ -26783,7 +26783,7 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
Computes the total disk space used by the database with the specified Computes the total disk space used by the database with the specified
name or OID. To use this function, you must name or OID. To use this function, you must
have <literal>CONNECT</literal> privilege on the specified database have <literal>CONNECT</literal> privilege on the specified database
(which is granted by default) or be a member of (which is granted by default) or have privileges of
the <literal>pg_read_all_stats</literal> role. the <literal>pg_read_all_stats</literal> role.
</para></entry> </para></entry>
</row> </row>
@ -26913,7 +26913,7 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
Computes the total disk space used in the tablespace with the Computes the total disk space used in the tablespace with the
specified name or OID. To use this function, you must specified name or OID. To use this function, you must
have <literal>CREATE</literal> privilege on the specified tablespace have <literal>CREATE</literal> privilege on the specified tablespace
or be a member of the <literal>pg_read_all_stats</literal> role, or have privileges of the <literal>pg_read_all_stats</literal> role,
unless it is the default tablespace for the current database. unless it is the default tablespace for the current database.
</para></entry> </para></entry>
</row> </row>
@ -27392,7 +27392,7 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
a dot, directories, and other special files are excluded. a dot, directories, and other special files are excluded.
</para> </para>
<para> <para>
This function is restricted to superusers and members of This function is restricted to superusers and roles with privileges of
the <literal>pg_monitor</literal> role by default, but other users can the <literal>pg_monitor</literal> role by default, but other users can
be granted EXECUTE to run the function. be granted EXECUTE to run the function.
</para></entry> </para></entry>
@ -27416,7 +27416,7 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
are excluded. are excluded.
</para> </para>
<para> <para>
This function is restricted to superusers and members of This function is restricted to superusers and roles with privileges of
the <literal>pg_monitor</literal> role by default, but other users can the <literal>pg_monitor</literal> role by default, but other users can
be granted EXECUTE to run the function. be granted EXECUTE to run the function.
</para></entry> </para></entry>

View File

@ -280,7 +280,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
(sessions belonging to a role that they are a member of). In rows about (sessions belonging to a role that they are a member of). In rows about
other sessions, many columns will be null. Note, however, that the other sessions, many columns will be null. Note, however, that the
existence of a session and its general properties such as its sessions user existence of a session and its general properties such as its sessions user
and database are visible to all users. Superusers and members of the and database are visible to all users. Superusers and roles with privileges of
built-in role <literal>pg_read_all_stats</literal> (see also <xref built-in role <literal>pg_read_all_stats</literal> (see also <xref
linkend="predefined-roles"/>) can see all the information about all sessions. linkend="predefined-roles"/>) can see all the information about all sessions.
</para> </para>

View File

@ -24,7 +24,7 @@
</para> </para>
<para> <para>
By default, use is restricted to superusers and members of the By default, use is restricted to superusers and roles with privileges of the
<literal>pg_monitor</literal> role. Access may be granted to others <literal>pg_monitor</literal> role. Access may be granted to others
using <command>GRANT</command>. using <command>GRANT</command>.
</para> </para>

View File

@ -16,7 +16,7 @@
</para> </para>
<para> <para>
By default use is restricted to superusers and members of the By default use is restricted to superusers and roles with privileges of the
<literal>pg_stat_scan_tables</literal> role. Access may be granted to others <literal>pg_stat_scan_tables</literal> role. Access may be granted to others
using <command>GRANT</command>. using <command>GRANT</command>.
</para> </para>

View File

@ -13,7 +13,7 @@
</para> </para>
<para> <para>
By default use is restricted to superusers, members of the By default use is restricted to superusers, roles with privileges of the
<literal>pg_stat_scan_tables</literal> role, and users with <literal>pg_stat_scan_tables</literal> role, and users with
<literal>SELECT</literal> permissions on the table. <literal>SELECT</literal> permissions on the table.
</para> </para>

View File

@ -384,7 +384,7 @@
</table> </table>
<para> <para>
For security reasons, only superusers and members of the For security reasons, only superusers and roles with privileges of the
<literal>pg_read_all_stats</literal> role are allowed to see the SQL text and <literal>pg_read_all_stats</literal> role are allowed to see the SQL text and
<structfield>queryid</structfield> of queries executed by other users. <structfield>queryid</structfield> of queries executed by other users.
Other users can see the statistics, however, if the view has been installed Other users can see the statistics, however, if the view has been installed

View File

@ -140,8 +140,8 @@
</variablelist> </variablelist>
<para> <para>
By default, these functions are executable only by superusers and members of the By default, these functions are executable only by superusers and roles with privileges
<literal>pg_stat_scan_tables</literal> role, with the exception of of the <literal>pg_stat_scan_tables</literal> role, with the exception of
<function>pg_truncate_visibility_map(relation regclass)</function> which can only <function>pg_truncate_visibility_map(relation regclass)</function> which can only
be executed by superusers. be executed by superusers.
</para> </para>

View File

@ -80,26 +80,26 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
{ {
if (stmt->is_program) if (stmt->is_program)
{ {
if (!is_member_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM)) if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of the pg_execute_server_program role to COPY to or from an external program"), errmsg("must be superuser or have privileges of the pg_execute_server_program role to COPY to or from an external program"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
} }
else else
{ {
if (is_from && !is_member_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES)) if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of the pg_read_server_files role to COPY from a file"), errmsg("must be superuser or have privileges of the pg_read_server_files role to COPY from a file"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
if (!is_from && !is_member_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of the pg_write_server_files role to COPY to a file"), errmsg("must be superuser or have privileges of the pg_write_server_files role to COPY to a file"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
} }

View File

@ -1403,12 +1403,12 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
/* Fetch values */ /* Fetch values */
values[0] = Int32GetDatum(pid); values[0] = Int32GetDatum(pid);
if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) if (!has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
{ {
/* /*
* Only superusers and members of pg_read_all_stats can see details. * Only superusers and roles with privileges of pg_read_all_stats
* Other users only get the pid value to know whether it is a WAL * can see details. Other users only get the pid value to know whether
* receiver, but no details. * it is a WAL receiver, but no details.
*/ */
MemSet(&nulls[1], true, sizeof(bool) * (tupdesc->natts - 1)); MemSet(&nulls[1], true, sizeof(bool) * (tupdesc->natts - 1));
} }

View File

@ -3473,12 +3473,12 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
memset(nulls, 0, sizeof(nulls)); memset(nulls, 0, sizeof(nulls));
values[0] = Int32GetDatum(pid); values[0] = Int32GetDatum(pid);
if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) if (!has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
{ {
/* /*
* Only superusers and members of pg_read_all_stats can see * Only superusers and roles with privileges of pg_read_all_stats
* details. Other users only get the pid value to know it's a * can see details. Other users only get the pid value to know
* walsender, but no details. * it's a walsender, but no details.
*/ */
MemSet(&nulls[1], true, PG_STAT_GET_WAL_SENDERS_COLS - 1); MemSet(&nulls[1], true, PG_STAT_GET_WAL_SENDERS_COLS - 1);
} }

View File

@ -4859,6 +4859,8 @@ has_privs_of_role(Oid member, Oid role)
* Is member a member of role (directly or indirectly)? * Is member a member of role (directly or indirectly)?
* *
* This is defined to recurse through roles regardless of rolinherit. * This is defined to recurse through roles regardless of rolinherit.
*
* Do not use this for privilege checking, instead use has_privs_of_role()
*/ */
bool bool
is_member_of_role(Oid member, Oid role) is_member_of_role(Oid member, Oid role)
@ -4899,6 +4901,8 @@ check_is_member_of_role(Oid member, Oid role)
* *
* This is identical to is_member_of_role except we ignore superuser * This is identical to is_member_of_role except we ignore superuser
* status. * status.
*
* Do not use this for privilege checking, instead use has_privs_of_role()
*/ */
bool bool
is_member_of_role_nosuper(Oid member, Oid role) is_member_of_role_nosuper(Oid member, Oid role)

View File

@ -112,12 +112,12 @@ calculate_database_size(Oid dbOid)
AclResult aclresult; AclResult aclresult;
/* /*
* User must have connect privilege for target database or be a member of * User must have connect privilege for target database or have privileges of
* pg_read_all_stats * pg_read_all_stats
*/ */
aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT); aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT);
if (aclresult != ACLCHECK_OK && if (aclresult != ACLCHECK_OK &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
{ {
aclcheck_error(aclresult, OBJECT_DATABASE, aclcheck_error(aclresult, OBJECT_DATABASE,
get_database_name(dbOid)); get_database_name(dbOid));
@ -196,12 +196,12 @@ calculate_tablespace_size(Oid tblspcOid)
AclResult aclresult; AclResult aclresult;
/* /*
* User must be a member of pg_read_all_stats or have CREATE privilege for * User must have privileges of pg_read_all_stats or have CREATE privilege for
* target tablespace, either explicitly granted or implicitly because it * target tablespace, either explicitly granted or implicitly because it
* is default for current database. * is default for current database.
*/ */
if (tblspcOid != MyDatabaseTableSpace && if (tblspcOid != MyDatabaseTableSpace &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
{ {
aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE); aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)

View File

@ -59,11 +59,11 @@ convert_and_check_filename(text *arg)
canonicalize_path(filename); /* filename can change length here */ canonicalize_path(filename); /* filename can change length here */
/* /*
* Members of the 'pg_read_server_files' role are allowed to access any * Roles with privleges of the 'pg_read_server_files' role are allowed to access
* files on the server as the PG user, so no need to do any further checks * any files on the server as the PG user, so no need to do any further checks
* here. * here.
*/ */
if (is_member_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES)) if (has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
return filename; return filename;
/* /*

View File

@ -34,7 +34,7 @@
#define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var)))) #define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var))))
#define HAS_PGSTAT_PERMISSIONS(role) (is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role)) #define HAS_PGSTAT_PERMISSIONS(role) (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
Datum Datum
pg_stat_get_numscans(PG_FUNCTION_ARGS) pg_stat_get_numscans(PG_FUNCTION_ARGS)

View File

@ -8228,10 +8228,10 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
return NULL; return NULL;
if (restrict_privileged && if (restrict_privileged &&
(record->flags & GUC_SUPERUSER_ONLY) && (record->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name))); name)));
switch (record->vartype) switch (record->vartype)
@ -8275,10 +8275,10 @@ GetConfigOptionResetString(const char *name)
record = find_option(name, false, false, ERROR); record = find_option(name, false, false, ERROR);
Assert(record != NULL); Assert(record != NULL);
if ((record->flags & GUC_SUPERUSER_ONLY) && if ((record->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name))); name)));
switch (record->vartype) switch (record->vartype)
@ -9566,7 +9566,7 @@ ShowAllGUCConfig(DestReceiver *dest)
if ((conf->flags & GUC_NO_SHOW_ALL) || if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && ((conf->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
continue; continue;
/* assign to the values array */ /* assign to the values array */
@ -9633,7 +9633,7 @@ get_explain_guc_options(int *num)
/* return only options visible to the current user */ /* return only options visible to the current user */
if ((conf->flags & GUC_NO_SHOW_ALL) || if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && ((conf->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
continue; continue;
/* return only options that are different from their boot values */ /* return only options that are different from their boot values */
@ -9715,10 +9715,10 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
} }
if ((record->flags & GUC_SUPERUSER_ONLY) && if ((record->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name))); name)));
if (varname) if (varname)
@ -9785,7 +9785,7 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
{ {
if ((conf->flags & GUC_NO_SHOW_ALL) || if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && ((conf->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))) !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
*noshow = true; *noshow = true;
else else
*noshow = false; *noshow = false;
@ -9980,7 +9980,7 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
* insufficiently-privileged users. * insufficiently-privileged users.
*/ */
if (conf->source == PGC_S_FILE && if (conf->source == PGC_S_FILE &&
is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)) has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
{ {
values[14] = conf->sourcefile; values[14] = conf->sourcefile;
snprintf(buffer, sizeof(buffer), "%d", conf->sourceline); snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);

View File

@ -1077,7 +1077,7 @@ SHOW session_preload_libraries;
SET SESSION AUTHORIZATION regress_role_nopriv; SET SESSION AUTHORIZATION regress_role_nopriv;
-- fails with role not member of pg_read_all_settings -- fails with role not member of pg_read_all_settings
SHOW session_preload_libraries; SHOW session_preload_libraries;
ERROR: must be superuser or a member of pg_read_all_settings to examine "session_preload_libraries" ERROR: must be superuser or have privileges of pg_read_all_settings to examine "session_preload_libraries"
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
ERROR: current transaction is aborted, commands ignored until end of transaction block ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK; ROLLBACK;