1
0
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:
Noah Misch
2015-09-20 20:45:41 -04:00
parent 1be9d65e17
commit 6dae6edcd8
8 changed files with 34 additions and 241 deletions

View File

@ -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

View File

@ -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 */