diff options
author | Fujii Masao <fujii@postgresql.org> | 2020-02-18 13:13:15 +0900 |
---|---|---|
committer | Fujii Masao <fujii@postgresql.org> | 2020-02-18 13:13:15 +0900 |
commit | b7e51b350c4e6b1cb3404588cf11801525e2336f (patch) | |
tree | e87519c47dc0b7db46751f3aa7cb079c61024fa1 /src/backend/commands/lockcmds.c | |
parent | 958f9fb98da97a1d781a3766ea86bcdba3b216c5 (diff) | |
download | postgresql-b7e51b350c4e6b1cb3404588cf11801525e2336f.tar.gz postgresql-b7e51b350c4e6b1cb3404588cf11801525e2336f.zip |
Make inherited LOCK TABLE perform access permission checks on parent table only.
Previously, LOCK TABLE command through a parent table checked
the permissions on not only the parent table but also the children
tables inherited from it. This was a bug and inherited queries should
perform access permission checks on the parent table only. This
commit fixes LOCK TABLE so that it does not check the permission
on children tables.
This patch is applied only in the master branch. We decided not to
back-patch because it's not hard to imagine that there are some
applications expecting the old behavior and the change breaks their
security.
Author: Amit Langote
Reviewed-by: Fujii Masao
Discussion: https://postgr.es/m/CAHGQGwE+GauyG7POtRfRwwthAGwTjPQYdFHR97+LzA4RHGnJxA@mail.gmail.com
Diffstat (limited to 'src/backend/commands/lockcmds.c')
-rw-r--r-- | src/backend/commands/lockcmds.c | 33 |
1 files changed, 11 insertions, 22 deletions
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index 329ab849c0b..d8cafc42bb5 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -28,7 +28,7 @@ #include "utils/lsyscache.h" #include "utils/syscache.h" -static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid); +static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait); static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode, Oid userid); static void RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg); @@ -59,7 +59,7 @@ LockTableCommand(LockStmt *lockstmt) if (get_rel_relkind(reloid) == RELKIND_VIEW) LockViewRecurse(reloid, lockstmt->mode, lockstmt->nowait, NIL); else if (recurse) - LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait, GetUserId()); + LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait); } } @@ -108,35 +108,26 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid, /* * Apply LOCK TABLE recursively over an inheritance tree * - * We use find_inheritance_children not find_all_inheritors to avoid taking - * locks far in advance of checking privileges. This means we'll visit - * multiply-inheriting children more than once, but that's no problem. + * This doesn't check permission to perform LOCK TABLE on the child tables, + * because getting here means that the user has permission to lock the + * parent which is enough. */ static void -LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid) +LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait) { List *children; ListCell *lc; - children = find_inheritance_children(reloid, NoLock); + children = find_all_inheritors(reloid, NoLock, NULL); foreach(lc, children) { Oid childreloid = lfirst_oid(lc); - AclResult aclresult; - /* Check permissions before acquiring the lock. */ - aclresult = LockTableAclCheck(childreloid, lockmode, userid); - if (aclresult != ACLCHECK_OK) - { - char *relname = get_rel_name(childreloid); - - if (!relname) - continue; /* child concurrently dropped, just skip it */ - aclcheck_error(aclresult, get_relkind_objtype(get_rel_relkind(childreloid)), relname); - } + /* Parent already locked. */ + if (childreloid == reloid) + continue; - /* We have enough rights to lock the relation; do so. */ if (!nowait) LockRelationOid(childreloid, lockmode); else if (!ConditionalLockRelationOid(childreloid, lockmode)) @@ -162,8 +153,6 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid) UnlockRelationOid(childreloid, lockmode); continue; } - - LockTableRecurse(childreloid, lockmode, nowait, userid); } } @@ -241,7 +230,7 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context) if (relkind == RELKIND_VIEW) LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views); else if (rte->inh) - LockTableRecurse(relid, context->lockmode, context->nowait, context->viewowner); + LockTableRecurse(relid, context->lockmode, context->nowait); } return query_tree_walker(query, |