Allow LOCK TABLE .. ROW EXCLUSIVE MODE with INSERT
authorStephen Frost
Mon, 11 May 2015 19:44:12 +0000 (15:44 -0400)
committerStephen Frost
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 ] name [ * ]
 
    
     LOCK TABLE ... IN ACCESS SHARE MODE requires SELECT
-    privileges on the target table.  All other forms of LOCK
-    require table-level UPDATE, DELETE, or
-    TRUNCATE privileges.
+    privileges on the target table.  LOCK TABLE ... IN ROW EXCLUSIVE
+    MODE requires INSERT, UPDATE, DELETE,
+    or TRUNCATE privileges on the target table. All other forms of
+    LOCK require table-level UPDATE, DELETE,
+    or TRUNCATE privileges.
    
 
    
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;
 }