Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Allow LOCK TABLE .. ROW EXCLUSIVE MODE with INSERT
authorStephen Frost <sfrost@snowman.net>
Mon, 11 May 2015 19:44:12 +0000 (15:44 -0400)
committerStephen Frost <sfrost@snowman.net>
Mon, 11 May 2015 19:44:12 +0000 (15:44 -0400)
INSERT acquires RowExclusiveLock during normal operation and therefore
it makes sense to allow LOCK TABLE .. ROW EXCLUSIVE MODE to be executed
by users who have INSERT rights on a table (even if they don't have
UPDATE or DELETE).

Not back-patching this as it's a behavior change which, strictly
speaking, loosens security restrictions.

Per discussion with Tom and Robert (circa 2013).

doc/src/sgml/ref/lock.sgml
src/backend/commands/lockcmds.c

index 913afe76dd41239187bd87e12ac745237eb41d56..b946eab3039e951d0eb5508f1905ed59e80bdd44 100644 (file)
@@ -161,9 +161,11 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [ * ]
 
    <para>
     <literal>LOCK TABLE ... IN ACCESS SHARE MODE</> requires <literal>SELECT</>
-    privileges on the target table.  All other forms of <command>LOCK</>
-    require table-level <literal>UPDATE</>, <literal>DELETE</>, or
-    <literal>TRUNCATE</> privileges.
+    privileges on the target table.  <literal>LOCK TABLE ... IN ROW EXCLUSIVE
+    MODE</> requires <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
+    or <literal>TRUNCATE</> privileges on the target table. All other forms of
+    <command>LOCK</> require table-level <literal>UPDATE</>, <literal>DELETE</>,
+    or <literal>TRUNCATE</> privileges.
    </para>
 
    <para>
index bdec2ff545c9e61b419ec4b6ef4c2396d80a9ab7..a1670821aa4291fba6078e9cde94ccc9f1635826 100644 (file)
@@ -169,13 +169,17 @@ static AclResult
 LockTableAclCheck(Oid reloid, LOCKMODE lockmode)
 {
    AclResult   aclresult;
+   AclMode     aclmask;
 
    /* Verify adequate privilege */
    if (lockmode == AccessShareLock)
-       aclresult = pg_class_aclcheck(reloid, GetUserId(),
-                                     ACL_SELECT);
+       aclmask = ACL_SELECT;
+   else if (lockmode == RowExclusiveLock)
+       aclmask = ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE;
    else
-       aclresult = pg_class_aclcheck(reloid, GetUserId(),
-                                     ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);
+       aclmask = ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE;
+
+   aclresult = pg_class_aclcheck(reloid, GetUserId(), aclmask);
+
    return aclresult;
 }