diff options
Diffstat (limited to 'meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch')
-rw-r--r-- | meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch | 267 |
1 files changed, 0 insertions, 267 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 deleted file mode 100644 index cc2183a2ab..0000000000 --- a/meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch +++ /dev/null @@ -1,267 +0,0 @@ -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 - |