1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

Clean up some mess in row-security patches.

Fix unsafe coding around PG_TRY in RelationBuildRowSecurity: can't change
a variable inside PG_TRY and then use it in PG_CATCH without marking it
"volatile".  In this case though it seems saner to avoid that by doing
a single assignment before entering the TRY block.

I started out just intending to fix that, but the more I looked at the
row-security code the more distressed I got.  This patch also fixes
incorrect construction of the RowSecurityPolicy cache entries (there was
not sufficient care taken to copy pass-by-ref data into the cache memory
context) and a whole bunch of sloppiness around the definition and use of
pg_policy.polcmd.  You can't use nulls in that column because initdb will
mark it NOT NULL --- and I see no particular reason why a null entry would
be a good idea anyway, so changing initdb's behavior is not the right
answer.  The internal value of '\0' wouldn't be suitable in a "char" column
either, so after a bit of thought I settled on using '*' to represent ALL.
Chasing those changes down also revealed that somebody wasn't paying
attention to what the underlying values of ACL_UPDATE_CHR etc really were,
and there was a great deal of lackadaiscalness in the catalogs.sgml
documentation for pg_policy and pg_policies too.

This doesn't pretend to be a complete code review for the row-security
stuff, it just fixes the things that were in my face while dealing with
the bugs in RelationBuildRowSecurity.
This commit is contained in:
Tom Lane
2015-01-24 16:16:22 -05:00
parent f8a4dd2e14
commit fd496129d1
11 changed files with 245 additions and 240 deletions

View File

@ -273,8 +273,7 @@ prepend_row_security_policies(Query* root, RangeTblEntry* rte, int rt_index)
* query, then set hasSubLinks on the Query to force subLinks to be
* properly expanded.
*/
if (hassublinks)
root->hasSubLinks = hassublinks;
root->hasSubLinks |= hassublinks;
/* If we got this far, we must have added quals */
return true;
@ -305,36 +304,36 @@ pull_row_security_policies(CmdType cmd, Relation relation, Oid user_id)
policy = (RowSecurityPolicy *) lfirst(item);
/* Always add ALL policies, if they exist. */
if (policy->cmd == '\0' &&
if (policy->polcmd == '*' &&
check_role_for_policy(policy->roles, user_id))
policies = lcons(policy, policies);
/* Build the list of policies to return. */
/* Add relevant command-specific policies to the list. */
switch(cmd)
{
case CMD_SELECT:
if (policy->cmd == ACL_SELECT_CHR
if (policy->polcmd == ACL_SELECT_CHR
&& check_role_for_policy(policy->roles, user_id))
policies = lcons(policy, policies);
break;
case CMD_INSERT:
/* If INSERT then only need to add the WITH CHECK qual */
if (policy->cmd == ACL_INSERT_CHR
if (policy->polcmd == ACL_INSERT_CHR
&& check_role_for_policy(policy->roles, user_id))
policies = lcons(policy, policies);
break;
case CMD_UPDATE:
if (policy->cmd == ACL_UPDATE_CHR
if (policy->polcmd == ACL_UPDATE_CHR
&& check_role_for_policy(policy->roles, user_id))
policies = lcons(policy, policies);
break;
case CMD_DELETE:
if (policy->cmd == ACL_DELETE_CHR
if (policy->polcmd == ACL_DELETE_CHR
&& check_role_for_policy(policy->roles, user_id))
policies = lcons(policy, policies);
break;
default:
elog(ERROR, "unrecognized command type.");
elog(ERROR, "unrecognized policy command type %d", (int) cmd);
break;
}
}
@ -354,7 +353,7 @@ pull_row_security_policies(CmdType cmd, Relation relation, Oid user_id)
policy = palloc0(sizeof(RowSecurityPolicy));
policy->policy_name = pstrdup("default-deny policy");
policy->policy_id = InvalidOid;
policy->cmd = '\0';
policy->polcmd = '*';
policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true,
'i');
policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,