mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Remove the row_security=force GUC value.
Every query of a single ENABLE ROW SECURITY table has two meanings, with the row_security GUC selecting between them. With row_security=force available, every function author would have been advised to either set the GUC locally or test both meanings. Non-compliance would have threatened reliability and, for SECURITY DEFINER functions, security. Authors already face an obligation to account for search_path, and we should not mimic that example. With this change, only BYPASSRLS roles need exercise the aforementioned care. Back-patch to 9.5, where the row_security GUC was introduced. Since this narrows the domain of pg_db_role_setting.setconfig and pg_proc.proconfig, one might bump catversion. A row_security=force setting in one of those columns will elicit a clear message, so don't.
This commit is contained in:
@ -379,23 +379,6 @@ static const struct config_enum_entry huge_pages_options[] = {
|
||||
{NULL, 0, false}
|
||||
};
|
||||
|
||||
/*
|
||||
* Although only "on", "off", and "force" are documented, we
|
||||
* accept all the likely variants of "on" and "off".
|
||||
*/
|
||||
static const struct config_enum_entry row_security_options[] = {
|
||||
{"on", ROW_SECURITY_ON, false},
|
||||
{"off", ROW_SECURITY_OFF, false},
|
||||
{"force", ROW_SECURITY_FORCE, false},
|
||||
{"true", ROW_SECURITY_ON, true},
|
||||
{"false", ROW_SECURITY_OFF, true},
|
||||
{"yes", ROW_SECURITY_ON, true},
|
||||
{"no", ROW_SECURITY_OFF, true},
|
||||
{"1", ROW_SECURITY_ON, true},
|
||||
{"0", ROW_SECURITY_OFF, true},
|
||||
{NULL, 0, false}
|
||||
};
|
||||
|
||||
/*
|
||||
* Options for enum values stored in other modules
|
||||
*/
|
||||
@ -421,6 +404,7 @@ bool log_statement_stats = false; /* this is sort of all three
|
||||
bool log_btree_build_stats = false;
|
||||
char *event_source;
|
||||
|
||||
bool row_security;
|
||||
bool check_function_bodies = true;
|
||||
bool default_with_oids = false;
|
||||
bool SQL_inheritance = true;
|
||||
@ -452,8 +436,6 @@ int tcp_keepalives_idle;
|
||||
int tcp_keepalives_interval;
|
||||
int tcp_keepalives_count;
|
||||
|
||||
int row_security;
|
||||
|
||||
/*
|
||||
* This really belongs in pg_shmem.c, but is defined here so that it doesn't
|
||||
* need to be duplicated in all the different implementations of pg_shmem.c.
|
||||
@ -1374,6 +1356,15 @@ static struct config_bool ConfigureNamesBool[] =
|
||||
false,
|
||||
check_transaction_deferrable, NULL, NULL
|
||||
},
|
||||
{
|
||||
{"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
|
||||
gettext_noop("Enable row security."),
|
||||
gettext_noop("When enabled, row security will be applied to all users.")
|
||||
},
|
||||
&row_security,
|
||||
true,
|
||||
NULL, NULL, NULL
|
||||
},
|
||||
{
|
||||
{"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||
gettext_noop("Check function bodies during CREATE FUNCTION."),
|
||||
@ -3631,16 +3622,6 @@ static struct config_enum ConfigureNamesEnum[] =
|
||||
NULL, NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
|
||||
gettext_noop("Enable row security."),
|
||||
gettext_noop("When enabled, row security will be applied to all users.")
|
||||
},
|
||||
&row_security,
|
||||
ROW_SECURITY_ON, row_security_options,
|
||||
NULL, NULL, NULL
|
||||
},
|
||||
|
||||
/* End-of-list marker */
|
||||
{
|
||||
{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
|
||||
|
@ -87,32 +87,19 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
|
||||
/*
|
||||
* Check permissions
|
||||
*
|
||||
* If the relation has row level security enabled and the row_security GUC
|
||||
* is off, then check if the user has rights to bypass RLS for this
|
||||
* relation. Table owners can always bypass, as can any role with the
|
||||
* BYPASSRLS capability.
|
||||
*
|
||||
* If the role is the table owner, then we bypass RLS unless row_security
|
||||
* is set to 'force'. Note that superuser is always considered an owner.
|
||||
*
|
||||
* Return RLS_NONE_ENV to indicate that this decision depends on the
|
||||
* environment (in this case, what the current values of user_id and
|
||||
* row_security are).
|
||||
* Table owners always bypass RLS. Note that superuser is always
|
||||
* considered an owner. Return RLS_NONE_ENV to indicate that this
|
||||
* decision depends on the environment (in this case, the user_id).
|
||||
*/
|
||||
if (row_security != ROW_SECURITY_FORCE
|
||||
&& (pg_class_ownercheck(relid, user_id)))
|
||||
if (pg_class_ownercheck(relid, user_id))
|
||||
return RLS_NONE_ENV;
|
||||
|
||||
/*
|
||||
* If the row_security GUC is 'off' then check if the user has permission
|
||||
* to bypass it. Note that we have already handled the case where the
|
||||
* user is the table owner above.
|
||||
*
|
||||
* Note that row_security is always considered 'on' when querying through
|
||||
* a view or other cases where checkAsUser is true, so skip this if
|
||||
* checkAsUser is in use.
|
||||
* If the row_security GUC is 'off', check if the user has permission to
|
||||
* bypass RLS. row_security is always considered 'on' when querying
|
||||
* through a view or other cases where checkAsUser is valid.
|
||||
*/
|
||||
if (!checkAsUser && row_security == ROW_SECURITY_OFF)
|
||||
if (!row_security && !checkAsUser)
|
||||
{
|
||||
if (has_bypassrls_privilege(user_id))
|
||||
/* OK to bypass */
|
||||
|
Reference in New Issue
Block a user