aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-support')
-rw-r--r--meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch267
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql.inc1
2 files changed, 268 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch b/meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch
new file mode 100644
index 0000000000..cc2183a2ab
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch
@@ -0,0 +1,267 @@
+From 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 Mon Sep 17 00:00:00 2001
+From: Noah Misch <noah@leadboat.com>
+Date: Mon, 17 Feb 2014 09:33:31 -0500
+Subject: [PATCH] Prevent privilege escalation in explicit calls to PL
+ validators.
+
+commit 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 REL9_2_STABLE
+
+The primary role of PL validators is to be called implicitly during
+CREATE FUNCTION, but they are also normal functions that a user can call
+explicitly. Add a permissions check to each validator to ensure that a
+user cannot use explicit validator calls to achieve things he could not
+otherwise achieve. Back-patch to 8.4 (all supported versions).
+Non-core procedural language extensions ought to make the same two-line
+change to their own validators.
+
+Andres Freund, reviewed by Tom Lane and Noah Misch.
+
+Security: CVE-2014-0061
+
+Upstream-Status: Backport
+Signed-off-by: Kai Kang <kai.kang@windriver.com>
+---
+ doc/src/sgml/plhandler.sgml | 5 ++-
+ src/backend/catalog/pg_proc.c | 9 ++++
+ src/backend/commands/functioncmds.c | 1 -
+ src/backend/utils/fmgr/fmgr.c | 84 +++++++++++++++++++++++++++++++++++
+ src/include/fmgr.h | 1 +
+ src/pl/plperl/plperl.c | 4 ++
+ src/pl/plpgsql/src/pl_handler.c | 3 +
+ src/pl/plpython/plpy_main.c | 4 ++
+ 8 files changed, 109 insertions(+), 2 deletions(-)
+
+diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml
+index 024ef9d..aa4bba3 100644
+--- a/doc/src/sgml/plhandler.sgml
++++ b/doc/src/sgml/plhandler.sgml
+@@ -178,7 +178,10 @@ CREATE LANGUAGE plsample
+ or updated a function written in the procedural language.
+ The passed-in OID is the OID of the function's <classname>pg_proc</>
+ row. The validator must fetch this row in the usual way, and do
+- whatever checking is appropriate. Typical checks include verifying
++ whatever checking is appropriate.
++ First, call <function>CheckFunctionValidatorAccess()</> to diagnose
++ explicit calls to the validator that the user could not achieve through
++ <command>CREATE FUNCTION</>. Typical checks then include verifying
+ that the function's argument and result types are supported by the
+ language, and that the function's body is syntactically correct
+ in the language. If the validator finds the function to be okay,
+diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
+index 3812408..3124868 100644
+--- a/src/backend/catalog/pg_proc.c
++++ b/src/backend/catalog/pg_proc.c
+@@ -718,6 +718,9 @@ fmgr_internal_validator(PG_FUNCTION_ARGS)
+ Datum tmp;
+ char *prosrc;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ /*
+ * We do not honor check_function_bodies since it's unlikely the function
+ * name will be found later if it isn't there now.
+@@ -763,6 +766,9 @@ fmgr_c_validator(PG_FUNCTION_ARGS)
+ char *prosrc;
+ char *probin;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ /*
+ * It'd be most consistent to skip the check if !check_function_bodies,
+ * but the purpose of that switch is to be helpful for pg_dump loading,
+@@ -814,6 +820,9 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
+ bool haspolyarg;
+ int i;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcoid);
+diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
+index 9ba6dd8..ea74b5e 100644
+--- a/src/backend/commands/functioncmds.c
++++ b/src/backend/commands/functioncmds.c
+@@ -997,7 +997,6 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
+ prorows);
+ }
+
+-
+ /*
+ * Guts of function deletion.
+ *
+diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
+index 2ec63fa..8d6f183 100644
+--- a/src/backend/utils/fmgr/fmgr.c
++++ b/src/backend/utils/fmgr/fmgr.c
+@@ -24,6 +24,7 @@
+ #include "miscadmin.h"
+ #include "nodes/nodeFuncs.h"
+ #include "pgstat.h"
++#include "utils/acl.h"
+ #include "utils/builtins.h"
+ #include "utils/fmgrtab.h"
+ #include "utils/guc.h"
+@@ -2445,3 +2446,86 @@ get_call_expr_arg_stable(Node *expr, int argnum)
+
+ return false;
+ }
++
++/*-------------------------------------------------------------------------
++ * Support routines for procedural language implementations
++ *-------------------------------------------------------------------------
++ */
++
++/*
++ * Verify that a validator is actually associated with the language of a
++ * particular function and that the user has access to both the language and
++ * the function. All validators should call this before doing anything
++ * substantial. Doing so ensures a user cannot achieve anything with explicit
++ * calls to validators that he could not achieve with CREATE FUNCTION or by
++ * simply calling an existing function.
++ *
++ * When this function returns false, callers should skip all validation work
++ * and call PG_RETURN_VOID(). This never happens at present; it is reserved
++ * for future expansion.
++ *
++ * In particular, checking that the validator corresponds to the function's
++ * language allows untrusted language validators to assume they process only
++ * superuser-chosen source code. (Untrusted language call handlers, by
++ * definition, do assume that.) A user lacking the USAGE language privilege
++ * would be unable to reach the validator through CREATE FUNCTION, so we check
++ * that to block explicit calls as well. Checking the EXECUTE privilege on
++ * the function is often superfluous, because most users can clone the
++ * function to get an executable copy. It is meaningful against users with no
++ * database TEMP right and no permanent schema CREATE right, thereby unable to
++ * create any function. Also, if the function tracks persistent state by
++ * function OID or name, validating the original function might permit more
++ * mischief than creating and validating a clone thereof.
++ */
++bool
++CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
++{
++ HeapTuple procTup;
++ HeapTuple langTup;
++ Form_pg_proc procStruct;
++ Form_pg_language langStruct;
++ AclResult aclresult;
++
++ /* Get the function's pg_proc entry */
++ procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
++ if (!HeapTupleIsValid(procTup))
++ elog(ERROR, "cache lookup failed for function %u", functionOid);
++ procStruct = (Form_pg_proc) GETSTRUCT(procTup);
++
++ /*
++ * Fetch pg_language entry to know if this is the correct validation
++ * function for that pg_proc entry.
++ */
++ langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(procStruct->prolang));
++ if (!HeapTupleIsValid(langTup))
++ elog(ERROR, "cache lookup failed for language %u", procStruct->prolang);
++ langStruct = (Form_pg_language) GETSTRUCT(langTup);
++
++ if (langStruct->lanvalidator != validatorOid)
++ ereport(ERROR,
++ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
++ errmsg("language validation function %u called for language %u instead of %u",
++ validatorOid, procStruct->prolang,
++ langStruct->lanvalidator)));
++
++ /* first validate that we have permissions to use the language */
++ aclresult = pg_language_aclcheck(procStruct->prolang, GetUserId(),
++ ACL_USAGE);
++ if (aclresult != ACLCHECK_OK)
++ aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
++ NameStr(langStruct->lanname));
++
++ /*
++ * Check whether we are allowed to execute the function itself. If we can
++ * execute it, there should be no possible side-effect of
++ * compiling/validation that execution can't have.
++ */
++ aclresult = pg_proc_aclcheck(functionOid, GetUserId(), ACL_EXECUTE);
++ if (aclresult != ACLCHECK_OK)
++ aclcheck_error(aclresult, ACL_KIND_PROC, NameStr(procStruct->proname));
++
++ ReleaseSysCache(procTup);
++ ReleaseSysCache(langTup);
++
++ return true;
++}
+diff --git a/src/include/fmgr.h b/src/include/fmgr.h
+index 0a25776..f944cc6 100644
+--- a/src/include/fmgr.h
++++ b/src/include/fmgr.h
+@@ -624,6 +624,7 @@ extern Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum);
+ extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum);
+ extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum);
+ extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum);
++extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid);
+
+ /*
+ * Routines in dfmgr.c
+diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
+index 7c2aee9..49d50c4 100644
+--- a/src/pl/plperl/plperl.c
++++ b/src/pl/plperl/plperl.c
+@@ -1847,6 +1847,9 @@ plperl_validator(PG_FUNCTION_ARGS)
+ bool istrigger = false;
+ int i;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ /* Get the new function's pg_proc entry */
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+@@ -1926,6 +1929,7 @@ PG_FUNCTION_INFO_V1(plperlu_validator);
+ Datum
+ plperlu_validator(PG_FUNCTION_ARGS)
+ {
++ /* call plperl validator with our fcinfo so it gets our oid */
+ return plperl_validator(fcinfo);
+ }
+
+diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
+index 022ec3f..00b1a6f 100644
+--- a/src/pl/plpgsql/src/pl_handler.c
++++ b/src/pl/plpgsql/src/pl_handler.c
+@@ -227,6 +227,9 @@ plpgsql_validator(PG_FUNCTION_ARGS)
+ bool istrigger = false;
+ int i;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ /* Get the new function's pg_proc entry */
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
+index c4de762..3847847 100644
+--- a/src/pl/plpython/plpy_main.c
++++ b/src/pl/plpython/plpy_main.c
+@@ -159,6 +159,9 @@ plpython_validator(PG_FUNCTION_ARGS)
+ Form_pg_proc procStruct;
+ bool is_trigger;
+
++ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
++ PG_RETURN_VOID();
++
+ if (!check_function_bodies)
+ {
+ PG_RETURN_VOID();
+@@ -184,6 +187,7 @@ plpython_validator(PG_FUNCTION_ARGS)
+ Datum
+ plpython2_validator(PG_FUNCTION_ARGS)
+ {
++ /* call plpython validator with our fcinfo so it gets our oid */
+ return plpython_validator(fcinfo);
+ }
+ #endif /* PY_MAJOR_VERSION < 3 */
+--
+1.7.5.4
+
diff --git a/meta-oe/recipes-support/postgresql/postgresql.inc b/meta-oe/recipes-support/postgresql/postgresql.inc
index d6a4cd781f..e2e5947b7c 100644
--- a/meta-oe/recipes-support/postgresql/postgresql.inc
+++ b/meta-oe/recipes-support/postgresql/postgresql.inc
@@ -33,6 +33,7 @@ SRC_URI = "http://ftp.postgresql.org/pub/source/v${PV}/${BP}.tar.bz2 \
file://0001-Use-pkg-config-for-libxml2-detection.patch \
file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \
file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \
+ file://0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch \
"
LEAD_SONAME = "libpq.so"