diff options
author | Robert Haas <rhaas@postgresql.org> | 2010-07-22 00:47:59 +0000 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2010-07-22 00:47:59 +0000 |
commit | b8c6c71d1c513391975fc107a95f104aeeac3117 (patch) | |
tree | fac8a1a04bed94bd5944f1a3773aa4c4609e5f51 /src/backend/executor/execMain.c | |
parent | 9f8cf32b341f3af070c512c7d6ad7f6a5aa7505b (diff) |
Centralize DML permissions-checking logic.
Remove bespoke code in DoCopy and RI_Initial_Check, which now instead
fabricate call ExecCheckRTPerms with a manufactured RangeTblEntry.
This is intended to make it feasible for an enhanced security provider
to actually make use of ExecutorCheckPerms_hook, but also has the
advantage that RI_Initial_Check can allow use of the fast-path when
column-level but not table-level permissions are present.
KaiGai Kohei. Reviewed (in an earlier version) by Stephen Frost, and by me.
Some further changes to the comments by me.
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 9eb765378f5..87ca2a1b4b8 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.351 2010/07/12 17:01:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.352 2010/07/22 00:47:52 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -75,8 +75,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate, long numberTuples, ScanDirection direction, DestReceiver *dest); -static void ExecCheckRTPerms(List *rangeTable); -static void ExecCheckRTEPerms(RangeTblEntry *rte); +static bool ExecCheckRTEPerms(RangeTblEntry *rte); static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt); static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree); @@ -409,26 +408,42 @@ ExecutorRewind(QueryDesc *queryDesc) /* * ExecCheckRTPerms * Check access permissions for all relations listed in a range table. + * + * Returns true if permissions are adequate. Otherwise, throws an appropriate + * error if ereport_on_violation is true, or simply returns false otherwise. */ -static void -ExecCheckRTPerms(List *rangeTable) +bool +ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation) { ListCell *l; + bool result = true; foreach(l, rangeTable) { - ExecCheckRTEPerms((RangeTblEntry *) lfirst(l)); + RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); + + result = ExecCheckRTEPerms(rte); + if (!result) + { + Assert(rte->rtekind == RTE_RELATION); + if (ereport_on_violation) + aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, + get_rel_name(rte->relid)); + return false; + } } if (ExecutorCheckPerms_hook) - (*ExecutorCheckPerms_hook)(rangeTable); + result = (*ExecutorCheckPerms_hook)(rangeTable, + ereport_on_violation); + return result; } /* * ExecCheckRTEPerms * Check access permissions for a single RTE. */ -static void +static bool ExecCheckRTEPerms(RangeTblEntry *rte) { AclMode requiredPerms; @@ -445,14 +460,14 @@ ExecCheckRTEPerms(RangeTblEntry *rte) * Join, subquery, and special RTEs need no checks. */ if (rte->rtekind != RTE_RELATION) - return; + return true; /* * No work if requiredPerms is empty. */ requiredPerms = rte->requiredPerms; if (requiredPerms == 0) - return; + return true; relOid = rte->relid; @@ -480,8 +495,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte) * we can fail straight away. */ if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE)) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + return false; /* * Check to see if we have the needed privileges at column level. @@ -501,8 +515,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte) { if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT, ACLMASK_ANY) != ACLCHECK_OK) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + return false; } tmpset = bms_copy(rte->selectedCols); @@ -515,15 +528,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte) /* Whole-row reference, must have priv on all cols */ if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT, ACLMASK_ALL) != ACLCHECK_OK) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + return false; } else { - if (pg_attribute_aclcheck(relOid, col, userid, ACL_SELECT) - != ACLCHECK_OK) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + if (pg_attribute_aclcheck(relOid, col, userid, + ACL_SELECT) != ACLCHECK_OK) + return false; } } bms_free(tmpset); @@ -546,8 +557,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte) { if (pg_attribute_aclcheck_all(relOid, userid, remainingPerms, ACLMASK_ANY) != ACLCHECK_OK) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + return false; } tmpset = bms_copy(rte->modifiedCols); @@ -562,15 +572,15 @@ ExecCheckRTEPerms(RangeTblEntry *rte) } else { - if (pg_attribute_aclcheck(relOid, col, userid, remainingPerms) - != ACLCHECK_OK) - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, - get_rel_name(relOid)); + if (pg_attribute_aclcheck(relOid, col, userid, + remainingPerms) != ACLCHECK_OK) + return false; } } bms_free(tmpset); } } + return true; } /* @@ -636,7 +646,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) /* * Do permissions checks */ - ExecCheckRTPerms(rangeTable); + ExecCheckRTPerms(rangeTable, true); /* * initialize the node's execution state |