mirror of
https://github.com/postgres/postgres.git
synced 2025-06-17 17:02:08 +03:00
ALTER TABLE .. FORCE ROW LEVEL SECURITY
To allow users to force RLS to always be applied, even for table owners, add ALTER TABLE .. FORCE ROW LEVEL SECURITY. row_security=off overrides FORCE ROW LEVEL SECURITY, to ensure pg_dump output is complete (by default). Also add SECURITY_NOFORCE_RLS context to avoid data corruption when ALTER TABLE .. FORCE ROW SECURITY is being used. The SECURITY_NOFORCE_RLS security context is used only during referential integrity checks and is only considered in check_enable_rls() after we have already checked that the current user is the owner of the relation (which should always be the case during referential integrity checks). Back-patch to 9.5 where RLS was added.
This commit is contained in:
@ -419,6 +419,7 @@ static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKM
|
||||
static void ATExecGenericOptions(Relation rel, List *options);
|
||||
static void ATExecEnableRowSecurity(Relation rel);
|
||||
static void ATExecDisableRowSecurity(Relation rel);
|
||||
static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
|
||||
|
||||
static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
|
||||
ForkNumber forkNum, char relpersistence);
|
||||
@ -2930,6 +2931,8 @@ AlterTableGetLockLevel(List *cmds)
|
||||
case AT_SetNotNull:
|
||||
case AT_EnableRowSecurity:
|
||||
case AT_DisableRowSecurity:
|
||||
case AT_ForceRowSecurity:
|
||||
case AT_NoForceRowSecurity:
|
||||
cmd_lockmode = AccessExclusiveLock;
|
||||
break;
|
||||
|
||||
@ -3351,6 +3354,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
||||
case AT_DropOf: /* NOT OF */
|
||||
case AT_EnableRowSecurity:
|
||||
case AT_DisableRowSecurity:
|
||||
case AT_ForceRowSecurity:
|
||||
case AT_NoForceRowSecurity:
|
||||
ATSimplePermissions(rel, ATT_TABLE);
|
||||
/* These commands never recurse */
|
||||
/* No command-specific prep needed */
|
||||
@ -3667,6 +3672,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
case AT_DisableRowSecurity:
|
||||
ATExecDisableRowSecurity(rel);
|
||||
break;
|
||||
case AT_ForceRowSecurity:
|
||||
ATExecForceNoForceRowSecurity(rel, true);
|
||||
break;
|
||||
case AT_NoForceRowSecurity:
|
||||
ATExecForceNoForceRowSecurity(rel, false);
|
||||
break;
|
||||
case AT_GenericOptions:
|
||||
ATExecGenericOptions(rel, (List *) cmd->def);
|
||||
break;
|
||||
@ -11066,6 +11077,35 @@ ATExecDisableRowSecurity(Relation rel)
|
||||
heap_freetuple(tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER TABLE FORCE/NO FORCE ROW LEVEL SECURITY
|
||||
*/
|
||||
static void
|
||||
ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
|
||||
{
|
||||
Relation pg_class;
|
||||
Oid relid;
|
||||
HeapTuple tuple;
|
||||
|
||||
relid = RelationGetRelid(rel);
|
||||
|
||||
pg_class = heap_open(RelationRelationId, RowExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup failed for relation %u", relid);
|
||||
|
||||
((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls;
|
||||
simple_heap_update(pg_class, &tuple->t_self, tuple);
|
||||
|
||||
/* keep catalog indexes current */
|
||||
CatalogUpdateIndexes(pg_class, tuple);
|
||||
|
||||
heap_close(pg_class, RowExclusiveLock);
|
||||
heap_freetuple(tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER FOREIGN TABLE <name> OPTIONS (...)
|
||||
*/
|
||||
|
Reference in New Issue
Block a user