]> granicus.if.org Git - postgresql/commitdiff
Require execute permission on the trigger function for CREATE TRIGGER.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Feb 2012 20:39:02 +0000 (15:39 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Feb 2012 20:39:02 +0000 (15:39 -0500)
This check was overlooked when we added function execute permissions to the
system years ago.  For an ordinary trigger function it's not a big deal,
since trigger functions execute with the permissions of the table owner,
so they couldn't do anything the user issuing the CREATE TRIGGER couldn't
have done anyway.  However, if a trigger function is SECURITY DEFINER,
that is not the case.  The lack of checking would allow another user to
install it on his own table and then invoke it with, essentially, forged
input data; which the trigger function is unlikely to realize, so it might
do something undesirable, for instance insert false entries in an audit log
table.

Reported by Dinesh Kumar, patch by Robert Haas

Security: CVE-2012-0866

doc/src/sgml/ref/create_trigger.sgml
src/backend/commands/trigger.c

index a7915cf09f4bf21d0cdde311c36725797c08fdf3..aed07a9dfb35966cca2070f36adca5e915a45995 100644 (file)
@@ -362,7 +362,8 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
 
   <para>
    To create a trigger on a table, the user must have the
-   <literal>TRIGGER</literal> privilege on the table.
+   <literal>TRIGGER</literal> privilege on the table.  The user must
+   also have <literal>EXECUTE</literal> privilege on the trigger function.
   </para>
 
   <para>
index f4352aef4eb32494cf3abd1183a91ec6544d4111..ef32571eaa73855f315db5e40225982c379811a0 100644 (file)
@@ -106,8 +106,8 @@ static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
  * if TRUE causes us to modify the given trigger name to ensure uniqueness.
  *
  * When isInternal is not true we require ACL_TRIGGER permissions on the
- * relation.  For internal triggers the caller must apply any required
- * permission checks.
+ * relation, as well as ACL_EXECUTE on the trigger function.  For internal
+ * triggers the caller must apply any required permission checks.
  *
  * Note: can return InvalidOid if we decided to not create a trigger at all,
  * but a foreign-key constraint.  This is a kluge for backwards compatibility.
@@ -366,6 +366,13 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
         * Find and validate the trigger function.
         */
        funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
+       if (!isInternal)
+       {
+               aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
+               if (aclresult != ACLCHECK_OK)
+                       aclcheck_error(aclresult, ACL_KIND_PROC,
+                                                  NameListToString(stmt->funcname));
+       }
        funcrettype = get_func_rettype(funcoid);
        if (funcrettype != TRIGGEROID)
        {