diff options
author | Kang Kai <kai.kang@windriver.com> | 2014-10-29 08:30:54 +0800 |
---|---|---|
committer | Martin Jansa <Martin.Jansa@gmail.com> | 2014-11-07 15:05:45 +0100 |
commit | 30f8a0515a959ac4c45771b406fdcf01cc1aca1c (patch) | |
tree | 72f50d28a114f4f59708435f8f0a59998b593ea1 | |
parent | b89271147deaa0a409a5626d98681bb6f16528e2 (diff) | |
download | meta-openembedded-30f8a0515a959ac4c45771b406fdcf01cc1aca1c.tar.gz |
postgresql: add fix for CVE-2014-0061 Security Advisory
The validator functions for the procedural languages (PLs) in PostgreSQL
before 8.4.20, 9.0.x before 9.0.16, 9.1.x before 9.1.12, 9.2.x before
9.2.7, and 9.3.x before 9.3.3 allow remote authenticated users to gain
privileges via a function that is (1) defined in another language or (2)
not allowed to be directly called by the user due to permissions.
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0061
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
-rw-r--r-- | meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch | 267 | ||||
-rw-r--r-- | meta-oe/recipes-support/postgresql/postgresql.inc | 1 |
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 000000000..cc2183a2a --- /dev/null +++ b/meta-oe/recipes-support/postgresql/files/0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch | |||
@@ -0,0 +1,267 @@ | |||
1 | From 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 Mon Sep 17 00:00:00 2001 | ||
2 | From: Noah Misch <noah@leadboat.com> | ||
3 | Date: Mon, 17 Feb 2014 09:33:31 -0500 | ||
4 | Subject: [PATCH] Prevent privilege escalation in explicit calls to PL | ||
5 | validators. | ||
6 | |||
7 | commit 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 REL9_2_STABLE | ||
8 | |||
9 | The primary role of PL validators is to be called implicitly during | ||
10 | CREATE FUNCTION, but they are also normal functions that a user can call | ||
11 | explicitly. Add a permissions check to each validator to ensure that a | ||
12 | user cannot use explicit validator calls to achieve things he could not | ||
13 | otherwise achieve. Back-patch to 8.4 (all supported versions). | ||
14 | Non-core procedural language extensions ought to make the same two-line | ||
15 | change to their own validators. | ||
16 | |||
17 | Andres Freund, reviewed by Tom Lane and Noah Misch. | ||
18 | |||
19 | Security: CVE-2014-0061 | ||
20 | |||
21 | Upstream-Status: Backport | ||
22 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
23 | --- | ||
24 | doc/src/sgml/plhandler.sgml | 5 ++- | ||
25 | src/backend/catalog/pg_proc.c | 9 ++++ | ||
26 | src/backend/commands/functioncmds.c | 1 - | ||
27 | src/backend/utils/fmgr/fmgr.c | 84 +++++++++++++++++++++++++++++++++++ | ||
28 | src/include/fmgr.h | 1 + | ||
29 | src/pl/plperl/plperl.c | 4 ++ | ||
30 | src/pl/plpgsql/src/pl_handler.c | 3 + | ||
31 | src/pl/plpython/plpy_main.c | 4 ++ | ||
32 | 8 files changed, 109 insertions(+), 2 deletions(-) | ||
33 | |||
34 | diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml | ||
35 | index 024ef9d..aa4bba3 100644 | ||
36 | --- a/doc/src/sgml/plhandler.sgml | ||
37 | +++ b/doc/src/sgml/plhandler.sgml | ||
38 | @@ -178,7 +178,10 @@ CREATE LANGUAGE plsample | ||
39 | or updated a function written in the procedural language. | ||
40 | The passed-in OID is the OID of the function's <classname>pg_proc</> | ||
41 | row. The validator must fetch this row in the usual way, and do | ||
42 | - whatever checking is appropriate. Typical checks include verifying | ||
43 | + whatever checking is appropriate. | ||
44 | + First, call <function>CheckFunctionValidatorAccess()</> to diagnose | ||
45 | + explicit calls to the validator that the user could not achieve through | ||
46 | + <command>CREATE FUNCTION</>. Typical checks then include verifying | ||
47 | that the function's argument and result types are supported by the | ||
48 | language, and that the function's body is syntactically correct | ||
49 | in the language. If the validator finds the function to be okay, | ||
50 | diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c | ||
51 | index 3812408..3124868 100644 | ||
52 | --- a/src/backend/catalog/pg_proc.c | ||
53 | +++ b/src/backend/catalog/pg_proc.c | ||
54 | @@ -718,6 +718,9 @@ fmgr_internal_validator(PG_FUNCTION_ARGS) | ||
55 | Datum tmp; | ||
56 | char *prosrc; | ||
57 | |||
58 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
59 | + PG_RETURN_VOID(); | ||
60 | + | ||
61 | /* | ||
62 | * We do not honor check_function_bodies since it's unlikely the function | ||
63 | * name will be found later if it isn't there now. | ||
64 | @@ -763,6 +766,9 @@ fmgr_c_validator(PG_FUNCTION_ARGS) | ||
65 | char *prosrc; | ||
66 | char *probin; | ||
67 | |||
68 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
69 | + PG_RETURN_VOID(); | ||
70 | + | ||
71 | /* | ||
72 | * It'd be most consistent to skip the check if !check_function_bodies, | ||
73 | * but the purpose of that switch is to be helpful for pg_dump loading, | ||
74 | @@ -814,6 +820,9 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) | ||
75 | bool haspolyarg; | ||
76 | int i; | ||
77 | |||
78 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
79 | + PG_RETURN_VOID(); | ||
80 | + | ||
81 | tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); | ||
82 | if (!HeapTupleIsValid(tuple)) | ||
83 | elog(ERROR, "cache lookup failed for function %u", funcoid); | ||
84 | diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c | ||
85 | index 9ba6dd8..ea74b5e 100644 | ||
86 | --- a/src/backend/commands/functioncmds.c | ||
87 | +++ b/src/backend/commands/functioncmds.c | ||
88 | @@ -997,7 +997,6 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString) | ||
89 | prorows); | ||
90 | } | ||
91 | |||
92 | - | ||
93 | /* | ||
94 | * Guts of function deletion. | ||
95 | * | ||
96 | diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c | ||
97 | index 2ec63fa..8d6f183 100644 | ||
98 | --- a/src/backend/utils/fmgr/fmgr.c | ||
99 | +++ b/src/backend/utils/fmgr/fmgr.c | ||
100 | @@ -24,6 +24,7 @@ | ||
101 | #include "miscadmin.h" | ||
102 | #include "nodes/nodeFuncs.h" | ||
103 | #include "pgstat.h" | ||
104 | +#include "utils/acl.h" | ||
105 | #include "utils/builtins.h" | ||
106 | #include "utils/fmgrtab.h" | ||
107 | #include "utils/guc.h" | ||
108 | @@ -2445,3 +2446,86 @@ get_call_expr_arg_stable(Node *expr, int argnum) | ||
109 | |||
110 | return false; | ||
111 | } | ||
112 | + | ||
113 | +/*------------------------------------------------------------------------- | ||
114 | + * Support routines for procedural language implementations | ||
115 | + *------------------------------------------------------------------------- | ||
116 | + */ | ||
117 | + | ||
118 | +/* | ||
119 | + * Verify that a validator is actually associated with the language of a | ||
120 | + * particular function and that the user has access to both the language and | ||
121 | + * the function. All validators should call this before doing anything | ||
122 | + * substantial. Doing so ensures a user cannot achieve anything with explicit | ||
123 | + * calls to validators that he could not achieve with CREATE FUNCTION or by | ||
124 | + * simply calling an existing function. | ||
125 | + * | ||
126 | + * When this function returns false, callers should skip all validation work | ||
127 | + * and call PG_RETURN_VOID(). This never happens at present; it is reserved | ||
128 | + * for future expansion. | ||
129 | + * | ||
130 | + * In particular, checking that the validator corresponds to the function's | ||
131 | + * language allows untrusted language validators to assume they process only | ||
132 | + * superuser-chosen source code. (Untrusted language call handlers, by | ||
133 | + * definition, do assume that.) A user lacking the USAGE language privilege | ||
134 | + * would be unable to reach the validator through CREATE FUNCTION, so we check | ||
135 | + * that to block explicit calls as well. Checking the EXECUTE privilege on | ||
136 | + * the function is often superfluous, because most users can clone the | ||
137 | + * function to get an executable copy. It is meaningful against users with no | ||
138 | + * database TEMP right and no permanent schema CREATE right, thereby unable to | ||
139 | + * create any function. Also, if the function tracks persistent state by | ||
140 | + * function OID or name, validating the original function might permit more | ||
141 | + * mischief than creating and validating a clone thereof. | ||
142 | + */ | ||
143 | +bool | ||
144 | +CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid) | ||
145 | +{ | ||
146 | + HeapTuple procTup; | ||
147 | + HeapTuple langTup; | ||
148 | + Form_pg_proc procStruct; | ||
149 | + Form_pg_language langStruct; | ||
150 | + AclResult aclresult; | ||
151 | + | ||
152 | + /* Get the function's pg_proc entry */ | ||
153 | + procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid)); | ||
154 | + if (!HeapTupleIsValid(procTup)) | ||
155 | + elog(ERROR, "cache lookup failed for function %u", functionOid); | ||
156 | + procStruct = (Form_pg_proc) GETSTRUCT(procTup); | ||
157 | + | ||
158 | + /* | ||
159 | + * Fetch pg_language entry to know if this is the correct validation | ||
160 | + * function for that pg_proc entry. | ||
161 | + */ | ||
162 | + langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(procStruct->prolang)); | ||
163 | + if (!HeapTupleIsValid(langTup)) | ||
164 | + elog(ERROR, "cache lookup failed for language %u", procStruct->prolang); | ||
165 | + langStruct = (Form_pg_language) GETSTRUCT(langTup); | ||
166 | + | ||
167 | + if (langStruct->lanvalidator != validatorOid) | ||
168 | + ereport(ERROR, | ||
169 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), | ||
170 | + errmsg("language validation function %u called for language %u instead of %u", | ||
171 | + validatorOid, procStruct->prolang, | ||
172 | + langStruct->lanvalidator))); | ||
173 | + | ||
174 | + /* first validate that we have permissions to use the language */ | ||
175 | + aclresult = pg_language_aclcheck(procStruct->prolang, GetUserId(), | ||
176 | + ACL_USAGE); | ||
177 | + if (aclresult != ACLCHECK_OK) | ||
178 | + aclcheck_error(aclresult, ACL_KIND_LANGUAGE, | ||
179 | + NameStr(langStruct->lanname)); | ||
180 | + | ||
181 | + /* | ||
182 | + * Check whether we are allowed to execute the function itself. If we can | ||
183 | + * execute it, there should be no possible side-effect of | ||
184 | + * compiling/validation that execution can't have. | ||
185 | + */ | ||
186 | + aclresult = pg_proc_aclcheck(functionOid, GetUserId(), ACL_EXECUTE); | ||
187 | + if (aclresult != ACLCHECK_OK) | ||
188 | + aclcheck_error(aclresult, ACL_KIND_PROC, NameStr(procStruct->proname)); | ||
189 | + | ||
190 | + ReleaseSysCache(procTup); | ||
191 | + ReleaseSysCache(langTup); | ||
192 | + | ||
193 | + return true; | ||
194 | +} | ||
195 | diff --git a/src/include/fmgr.h b/src/include/fmgr.h | ||
196 | index 0a25776..f944cc6 100644 | ||
197 | --- a/src/include/fmgr.h | ||
198 | +++ b/src/include/fmgr.h | ||
199 | @@ -624,6 +624,7 @@ extern Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum); | ||
200 | extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum); | ||
201 | extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum); | ||
202 | extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum); | ||
203 | +extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid); | ||
204 | |||
205 | /* | ||
206 | * Routines in dfmgr.c | ||
207 | diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c | ||
208 | index 7c2aee9..49d50c4 100644 | ||
209 | --- a/src/pl/plperl/plperl.c | ||
210 | +++ b/src/pl/plperl/plperl.c | ||
211 | @@ -1847,6 +1847,9 @@ plperl_validator(PG_FUNCTION_ARGS) | ||
212 | bool istrigger = false; | ||
213 | int i; | ||
214 | |||
215 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
216 | + PG_RETURN_VOID(); | ||
217 | + | ||
218 | /* Get the new function's pg_proc entry */ | ||
219 | tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); | ||
220 | if (!HeapTupleIsValid(tuple)) | ||
221 | @@ -1926,6 +1929,7 @@ PG_FUNCTION_INFO_V1(plperlu_validator); | ||
222 | Datum | ||
223 | plperlu_validator(PG_FUNCTION_ARGS) | ||
224 | { | ||
225 | + /* call plperl validator with our fcinfo so it gets our oid */ | ||
226 | return plperl_validator(fcinfo); | ||
227 | } | ||
228 | |||
229 | diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c | ||
230 | index 022ec3f..00b1a6f 100644 | ||
231 | --- a/src/pl/plpgsql/src/pl_handler.c | ||
232 | +++ b/src/pl/plpgsql/src/pl_handler.c | ||
233 | @@ -227,6 +227,9 @@ plpgsql_validator(PG_FUNCTION_ARGS) | ||
234 | bool istrigger = false; | ||
235 | int i; | ||
236 | |||
237 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
238 | + PG_RETURN_VOID(); | ||
239 | + | ||
240 | /* Get the new function's pg_proc entry */ | ||
241 | tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); | ||
242 | if (!HeapTupleIsValid(tuple)) | ||
243 | diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c | ||
244 | index c4de762..3847847 100644 | ||
245 | --- a/src/pl/plpython/plpy_main.c | ||
246 | +++ b/src/pl/plpython/plpy_main.c | ||
247 | @@ -159,6 +159,9 @@ plpython_validator(PG_FUNCTION_ARGS) | ||
248 | Form_pg_proc procStruct; | ||
249 | bool is_trigger; | ||
250 | |||
251 | + if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) | ||
252 | + PG_RETURN_VOID(); | ||
253 | + | ||
254 | if (!check_function_bodies) | ||
255 | { | ||
256 | PG_RETURN_VOID(); | ||
257 | @@ -184,6 +187,7 @@ plpython_validator(PG_FUNCTION_ARGS) | ||
258 | Datum | ||
259 | plpython2_validator(PG_FUNCTION_ARGS) | ||
260 | { | ||
261 | + /* call plpython validator with our fcinfo so it gets our oid */ | ||
262 | return plpython_validator(fcinfo); | ||
263 | } | ||
264 | #endif /* PY_MAJOR_VERSION < 3 */ | ||
265 | -- | ||
266 | 1.7.5.4 | ||
267 | |||
diff --git a/meta-oe/recipes-support/postgresql/postgresql.inc b/meta-oe/recipes-support/postgresql/postgresql.inc index d6a4cd781..e2e5947b7 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 \ | |||
33 | file://0001-Use-pkg-config-for-libxml2-detection.patch \ | 33 | file://0001-Use-pkg-config-for-libxml2-detection.patch \ |
34 | file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \ | 34 | file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \ |
35 | file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \ | 35 | file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \ |
36 | file://0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch \ | ||
36 | " | 37 | " |
37 | 38 | ||
38 | LEAD_SONAME = "libpq.so" | 39 | LEAD_SONAME = "libpq.so" |