mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Create a pg_shdepend entry for each role in TO clause of policies.
CreatePolicy() and AlterPolicy() omit to create a pg_shdepend entry for each role in the TO clause. Fix this by creating a new shared dependency type called SHARED_DEPENDENCY_POLICY and assigning it to each role. Reported by Noah Misch. Patch by me, reviewed by Alvaro Herrera. Back-patch to 9.5 where RLS was introduced.
This commit is contained in:
@ -22,6 +22,7 @@
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/objectaccess.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_policy.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/policy.h"
|
||||
@ -48,7 +49,7 @@
|
||||
static void RangeVarCallbackForPolicy(const RangeVar *rv,
|
||||
Oid relid, Oid oldrelid, void *arg);
|
||||
static char parse_policy_command(const char *cmd_name);
|
||||
static ArrayType *policy_role_list_to_array(List *roles);
|
||||
static Datum *policy_role_list_to_array(List *roles, int *num_roles);
|
||||
|
||||
/*
|
||||
* Callback to RangeVarGetRelidExtended().
|
||||
@ -130,30 +131,28 @@ parse_policy_command(const char *cmd_name)
|
||||
|
||||
/*
|
||||
* policy_role_list_to_array
|
||||
* helper function to convert a list of RoleSpecs to an array of role ids.
|
||||
* helper function to convert a list of RoleSpecs to an array of
|
||||
* role id Datums.
|
||||
*/
|
||||
static ArrayType *
|
||||
policy_role_list_to_array(List *roles)
|
||||
static Datum *
|
||||
policy_role_list_to_array(List *roles, int *num_roles)
|
||||
{
|
||||
ArrayType *role_ids;
|
||||
Datum *temp_array;
|
||||
Datum *role_oids;
|
||||
ListCell *cell;
|
||||
int num_roles;
|
||||
int i = 0;
|
||||
|
||||
/* Handle no roles being passed in as being for public */
|
||||
if (roles == NIL)
|
||||
{
|
||||
temp_array = (Datum *) palloc(sizeof(Datum));
|
||||
temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
||||
*num_roles = 1;
|
||||
role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
|
||||
role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
||||
|
||||
role_ids = construct_array(temp_array, 1, OIDOID, sizeof(Oid), true,
|
||||
'i');
|
||||
return role_ids;
|
||||
return role_oids;
|
||||
}
|
||||
|
||||
num_roles = list_length(roles);
|
||||
temp_array = (Datum *) palloc(num_roles * sizeof(Datum));
|
||||
*num_roles = list_length(roles);
|
||||
role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
|
||||
|
||||
foreach(cell, roles)
|
||||
{
|
||||
@ -164,24 +163,24 @@ policy_role_list_to_array(List *roles)
|
||||
*/
|
||||
if (spec->roletype == ROLESPEC_PUBLIC)
|
||||
{
|
||||
if (num_roles != 1)
|
||||
if (*num_roles != 1)
|
||||
{
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("ignoring roles specified other than public"),
|
||||
errhint("All roles are members of the public role.")));
|
||||
temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
||||
num_roles = 1;
|
||||
break;
|
||||
*num_roles = 1;
|
||||
}
|
||||
role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
|
||||
|
||||
return role_oids;
|
||||
}
|
||||
else
|
||||
temp_array[i++] =
|
||||
role_oids[i++] =
|
||||
ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false));
|
||||
}
|
||||
|
||||
role_ids = construct_array(temp_array, num_roles, OIDOID, sizeof(Oid), true,
|
||||
'i');
|
||||
|
||||
return role_ids;
|
||||
return role_oids;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -463,6 +462,8 @@ CreatePolicy(CreatePolicyStmt *stmt)
|
||||
Relation target_table;
|
||||
Oid table_id;
|
||||
char polcmd;
|
||||
Datum *role_oids;
|
||||
int nitems = 0;
|
||||
ArrayType *role_ids;
|
||||
ParseState *qual_pstate;
|
||||
ParseState *with_check_pstate;
|
||||
@ -476,6 +477,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
|
||||
bool isnull[Natts_pg_policy];
|
||||
ObjectAddress target;
|
||||
ObjectAddress myself;
|
||||
int i;
|
||||
|
||||
/* Parse command */
|
||||
polcmd = parse_policy_command(stmt->cmd);
|
||||
@ -498,9 +500,10 @@ CreatePolicy(CreatePolicyStmt *stmt)
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("only WITH CHECK expression allowed for INSERT")));
|
||||
|
||||
|
||||
/* Collect role ids */
|
||||
role_ids = policy_role_list_to_array(stmt->roles);
|
||||
role_oids = policy_role_list_to_array(stmt->roles, &nitems);
|
||||
role_ids = construct_array(role_oids, nitems, OIDOID,
|
||||
sizeof(Oid), true, 'i');
|
||||
|
||||
/* Parse the supplied clause */
|
||||
qual_pstate = make_parsestate(NULL);
|
||||
@ -614,6 +617,18 @@ CreatePolicy(CreatePolicyStmt *stmt)
|
||||
recordDependencyOnExpr(&myself, with_check_qual,
|
||||
with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
|
||||
|
||||
/* Register role dependencies */
|
||||
target.classId = AuthIdRelationId;
|
||||
target.objectSubId = 0;
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
target.objectId = DatumGetObjectId(role_oids[i]);
|
||||
/* no dependency if public */
|
||||
if (target.objectId != ACL_ID_PUBLIC)
|
||||
recordSharedDependencyOn(&myself, &target,
|
||||
SHARED_DEPENDENCY_POLICY);
|
||||
}
|
||||
|
||||
/* Invalidate Relation Cache */
|
||||
CacheInvalidateRelcache(target_table);
|
||||
|
||||
@ -641,6 +656,8 @@ AlterPolicy(AlterPolicyStmt *stmt)
|
||||
Oid policy_id;
|
||||
Relation target_table;
|
||||
Oid table_id;
|
||||
Datum *role_oids;
|
||||
int nitems = 0;
|
||||
ArrayType *role_ids = NULL;
|
||||
List *qual_parse_rtable = NIL;
|
||||
List *with_check_parse_rtable = NIL;
|
||||
@ -658,10 +675,15 @@ AlterPolicy(AlterPolicyStmt *stmt)
|
||||
Datum cmd_datum;
|
||||
char polcmd;
|
||||
bool polcmd_isnull;
|
||||
int i;
|
||||
|
||||
/* Parse role_ids */
|
||||
if (stmt->roles != NULL)
|
||||
role_ids = policy_role_list_to_array(stmt->roles);
|
||||
{
|
||||
role_oids = policy_role_list_to_array(stmt->roles, &nitems);
|
||||
role_ids = construct_array(role_oids, nitems, OIDOID,
|
||||
sizeof(Oid), true, 'i');
|
||||
}
|
||||
|
||||
/* Get id of table. Also handles permissions checks. */
|
||||
table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock,
|
||||
@ -825,6 +847,19 @@ AlterPolicy(AlterPolicyStmt *stmt)
|
||||
recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
|
||||
DEPENDENCY_NORMAL);
|
||||
|
||||
/* Register role dependencies */
|
||||
deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
|
||||
target.classId = AuthIdRelationId;
|
||||
target.objectSubId = 0;
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
target.objectId = DatumGetObjectId(role_oids[i]);
|
||||
/* no dependency if public */
|
||||
if (target.objectId != ACL_ID_PUBLIC)
|
||||
recordSharedDependencyOn(&myself, &target,
|
||||
SHARED_DEPENDENCY_POLICY);
|
||||
}
|
||||
|
||||
heap_freetuple(new_tuple);
|
||||
|
||||
/* Invalidate Relation Cache */
|
||||
|
Reference in New Issue
Block a user