All,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Stephen Frost <sfr...@snowman.net> writes:
> >     if (lockmode == AccessShareLock)
> >         aclresult = pg_class_aclcheck(reloid, GetUserId(),
> >                                       ACL_SELECT);
> > +   else if (lockmode == RowExclusiveLock)
> > +       aclresult = pg_class_aclcheck(reloid, GetUserId(),
> > +                        ACL_INSERT | ACL_UPDATE | ACL_DELETE | 
> > ACL_TRUNCATE);
> >     else
> >         aclresult = pg_class_aclcheck(reloid, GetUserId(),
> >                                       ACL_UPDATE | ACL_DELETE | 
> > ACL_TRUNCATE);
> 
> Perhaps it would be better to refactor with a local variable for the
> aclmask and just one instance of the pg_class_aclcheck call.  Also, I'm
> pretty sure that the documentation work needed is more extensive
> than the actual patch ;-).  Otherwise, I don't see a problem with this.

Now for a blast from the past...  This came up again on IRC recently and
reminded me that I ran into the same issue a couple years back.  Updated
patch includes the refactoring suggested and includes documentation.

Not going to be back-patched, as discussed with Robert.

Barring objections, I'll push this later today.

        Thanks!

                Stephen
From d2b0fbc9fd8c0783f870fef3c901f7f8891c6e90 Mon Sep 17 00:00:00 2001
From: Stephen Frost <sfr...@snowman.net>
Date: Mon, 11 May 2015 09:14:49 -0400
Subject: [PATCH] Allow LOCK TABLE .. ROW EXCLUSIVE MODE with INSERT

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      |  8 +++++---
 src/backend/commands/lockcmds.c | 12 ++++++++----
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml
index 913afe7..b946eab 100644
--- a/doc/src/sgml/ref/lock.sgml
+++ b/doc/src/sgml/ref/lock.sgml
@@ -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>
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index bdec2ff..a167082 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -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;
 }
-- 
1.9.1

Attachment: signature.asc
Description: Digital signature

Reply via email to