summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/postgresql
diff options
context:
space:
mode:
authorTudor Florea <tudor.florea@enea.com>2015-10-08 22:51:41 +0200
committerTudor Florea <tudor.florea@enea.com>2015-10-08 22:51:41 +0200
commit1219bf8a90a7bf8cd3a5363551ef635d51e8fc8e (patch)
treea21a5fc103bb3bd65ecd85ed22be5228fc54e447 /meta-oe/recipes-support/postgresql
downloadmeta-openembedded-1219bf8a90a7bf8cd3a5363551ef635d51e8fc8e.tar.gz
initial commit for Enea Linux 5.0 arm
Signed-off-by: Tudor Florea <tudor.florea@enea.com>
Diffstat (limited to 'meta-oe/recipes-support/postgresql')
-rw-r--r--meta-oe/recipes-support/postgresql/files/0001-Use-pkg-config-for-libxml2-detection.patch43
-rw-r--r--meta-oe/recipes-support/postgresql/files/0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch605
-rw-r--r--meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch273
-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/files/0005-Avoid-repeated-name-lookups-during-table-and-index-D.patch1082
-rw-r--r--meta-oe/recipes-support/postgresql/files/0006-Fix-handling-of-wide-datetime-input-output.patch465
-rw-r--r--meta-oe/recipes-support/postgresql/files/0007-Make-pqsignal-available-to-pg_regress-of-ECPG-and-is.patch75
-rw-r--r--meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch393
-rw-r--r--meta-oe/recipes-support/postgresql/files/no-ecpg-test.patch12
-rw-r--r--meta-oe/recipes-support/postgresql/files/postgresql-bashprofile4
-rw-r--r--meta-oe/recipes-support/postgresql/files/postgresql-setup73
-rw-r--r--meta-oe/recipes-support/postgresql/files/postgresql.init193
-rw-r--r--meta-oe/recipes-support/postgresql/files/postgresql.pam4
-rw-r--r--meta-oe/recipes-support/postgresql/files/postgresql.service27
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql-9.2.4/ecpg-parallel-make-fix.patch31
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql-9.2.4/remove.autoconf.version.check.patch15
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql.inc395
-rw-r--r--meta-oe/recipes-support/postgresql/postgresql_9.2.4.bb13
18 files changed, 3970 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/postgresql/files/0001-Use-pkg-config-for-libxml2-detection.patch b/meta-oe/recipes-support/postgresql/files/0001-Use-pkg-config-for-libxml2-detection.patch
new file mode 100644
index 000000000..d08ec6af1
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0001-Use-pkg-config-for-libxml2-detection.patch
@@ -0,0 +1,43 @@
1From d52e330be895bb8c5f0fb3e2884766acbd942a85 Mon Sep 17 00:00:00 2001
2From: Philip Balister <philip@balister.org>
3Date: Tue, 1 Jul 2014 09:40:44 -0400
4Subject: [PATCH] Use pkg-config for libxml2 detection.
5
6Upstream-Status: Inappropriate [configuration]
7
8xml2-config does not work. Use pkgconfig to set CPPFLAGS and LIBS.
9
10Signed-off-by: Philip Balister <philip@balister.org>
11---
12 configure.in | 15 ++-------------
13 1 file changed, 2 insertions(+), 13 deletions(-)
14
15diff --git a/configure.in b/configure.in
16index f8bf466..1f4fabf 100644
17--- a/configure.in
18+++ b/configure.in
19@@ -734,19 +734,8 @@ PGAC_ARG_BOOL(with, libxml, no, [build with XML support],
20 [AC_DEFINE([USE_LIBXML], 1, [Define to 1 to build with XML support. (--with-libxml)])])
21
22 if test "$with_libxml" = yes ; then
23- AC_CHECK_PROGS(XML2_CONFIG, xml2-config)
24- if test -n "$XML2_CONFIG"; then
25- for pgac_option in `$XML2_CONFIG --cflags`; do
26- case $pgac_option in
27- -I*|-D*) CPPFLAGS="$CPPFLAGS $pgac_option";;
28- esac
29- done
30- for pgac_option in `$XML2_CONFIG --libs`; do
31- case $pgac_option in
32- -L*) LDFLAGS="$LDFLAGS $pgac_option";;
33- esac
34- done
35- fi
36+ CPPFLAGS="$CPPFLAGS `pkg-config --short-errors --print-errors --cflags "libxml-2.0" 2>&1`"
37+ LIBS="`pkg-config --short-errors --print-errors --libs "libxml-2.0" 2>&1` $LIBS"
38 fi
39
40 AC_SUBST(with_libxml)
41--
421.8.3.1
43
diff --git a/meta-oe/recipes-support/postgresql/files/0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch b/meta-oe/recipes-support/postgresql/files/0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch
new file mode 100644
index 000000000..c8b4c80aa
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch
@@ -0,0 +1,605 @@
1From 12bbce15d93d7692ddff1405aa04b67f8a327f57 Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Mon, 17 Feb 2014 09:33:31 -0500
4Subject: [PATCH] Predict integer overflow to avoid buffer overruns.
5
6commit 12bbce15d93d7692ddff1405aa04b67f8a327f57 REL9_2_STABLE
7
8Several functions, mostly type input functions, calculated an allocation
9size such that the calculation wrapped to a small positive value when
10arguments implied a sufficiently-large requirement. Writes past the end
11of the inadvertent small allocation followed shortly thereafter.
12Coverity identified the path_in() vulnerability; code inspection led to
13the rest. In passing, add check_stack_depth() to prevent stack overflow
14in related functions.
15
16Back-patch to 8.4 (all supported versions). The non-comment hstore
17changes touch code that did not exist in 8.4, so that part stops at 9.0.
18
19Noah Misch and Heikki Linnakangas, reviewed by Tom Lane.
20
21Security: CVE-2014-0064
22
23Upstream-Status: Backport
24
25Signed-off-by: Kai Kang <kai.kang@windriver.com>
26---
27 contrib/hstore/hstore.h | 15 ++++++++++++---
28 contrib/hstore/hstore_io.c | 21 +++++++++++++++++++++
29 contrib/hstore/hstore_op.c | 15 +++++++++++++++
30 contrib/intarray/_int.h | 2 ++
31 contrib/intarray/_int_bool.c | 9 +++++++++
32 contrib/ltree/ltree.h | 3 +++
33 contrib/ltree/ltree_io.c | 11 +++++++++++
34 contrib/ltree/ltxtquery_io.c | 13 ++++++++++++-
35 src/backend/utils/adt/geo_ops.c | 30 ++++++++++++++++++++++++++++--
36 src/backend/utils/adt/tsquery.c | 7 ++++++-
37 src/backend/utils/adt/tsquery_util.c | 5 +++++
38 src/backend/utils/adt/txid.c | 15 +++++----------
39 src/backend/utils/adt/varbit.c | 32 ++++++++++++++++++++++++++++++--
40 src/include/tsearch/ts_type.h | 3 +++
41 src/include/utils/varbit.h | 7 +++++++
42 15 files changed, 169 insertions(+), 19 deletions(-)
43
44diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
45index 8906397..4e55f6e 100644
46--- a/contrib/hstore/hstore.h
47+++ b/contrib/hstore/hstore.h
48@@ -49,9 +49,12 @@ typedef struct
49 } HStore;
50
51 /*
52- * it's not possible to get more than 2^28 items into an hstore,
53- * so we reserve the top few bits of the size field. See hstore_compat.c
54- * for one reason why. Some bits are left for future use here.
55+ * It's not possible to get more than 2^28 items into an hstore, so we reserve
56+ * the top few bits of the size field. See hstore_compat.c for one reason
57+ * why. Some bits are left for future use here. MaxAllocSize makes the
58+ * practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the
59+ * limit for an hstore full of 4-byte keys and null values. Therefore, we
60+ * don't explicitly check the format-imposed limit.
61 */
62 #define HS_FLAG_NEWVERSION 0x80000000
63
64@@ -59,6 +62,12 @@ typedef struct
65 #define HS_SETCOUNT(hsp_,c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
66
67
68+/*
69+ * "x" comes from an existing HS_COUNT() (as discussed, <= INT_MAX/24) or a
70+ * Pairs array length (due to MaxAllocSize, <= INT_MAX/40). "lenstr" is no
71+ * more than INT_MAX, that extreme case arising in hstore_from_arrays().
72+ * Therefore, this calculation is limited to about INT_MAX / 5 + INT_MAX.
73+ */
74 #define HSHRDSIZE (sizeof(HStore))
75 #define CALCDATASIZE(x, lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
76
77diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
78index dde6c4b..5bcdc95 100644
79--- a/contrib/hstore/hstore_io.c
80+++ b/contrib/hstore/hstore_io.c
81@@ -9,6 +9,7 @@
82 #include "funcapi.h"
83 #include "libpq/pqformat.h"
84 #include "utils/lsyscache.h"
85+#include "utils/memutils.h"
86 #include "utils/typcache.h"
87
88 #include "hstore.h"
89@@ -437,6 +438,11 @@ hstore_recv(PG_FUNCTION_ARGS)
90 PG_RETURN_POINTER(out);
91 }
92
93+ if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
94+ ereport(ERROR,
95+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
96+ errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
97+ pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
98 pairs = palloc(pcount * sizeof(Pairs));
99
100 for (i = 0; i < pcount; ++i)
101@@ -552,6 +558,13 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
102 TEXTOID, -1, false, 'i',
103 &key_datums, &key_nulls, &key_count);
104
105+ /* see discussion in hstoreArrayToPairs() */
106+ if (key_count > MaxAllocSize / sizeof(Pairs))
107+ ereport(ERROR,
108+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
109+ errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
110+ key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
111+
112 /* value_array might be NULL */
113
114 if (PG_ARGISNULL(1))
115@@ -674,6 +687,13 @@ hstore_from_array(PG_FUNCTION_ARGS)
116
117 count = in_count / 2;
118
119+ /* see discussion in hstoreArrayToPairs() */
120+ if (count > MaxAllocSize / sizeof(Pairs))
121+ ereport(ERROR,
122+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
123+ errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
124+ count, (int) (MaxAllocSize / sizeof(Pairs)))));
125+
126 pairs = palloc(count * sizeof(Pairs));
127
128 for (i = 0; i < count; ++i)
129@@ -805,6 +825,7 @@ hstore_from_record(PG_FUNCTION_ARGS)
130 my_extra->ncolumns = ncolumns;
131 }
132
133+ Assert(ncolumns <= MaxTupleAttributeNumber); /* thus, no overflow */
134 pairs = palloc(ncolumns * sizeof(Pairs));
135
136 if (rec)
137diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
138index fee2c3c..8de175a 100644
139--- a/contrib/hstore/hstore_op.c
140+++ b/contrib/hstore/hstore_op.c
141@@ -7,6 +7,7 @@
142 #include "catalog/pg_type.h"
143 #include "funcapi.h"
144 #include "utils/builtins.h"
145+#include "utils/memutils.h"
146
147 #include "hstore.h"
148
149@@ -89,6 +90,19 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
150 return NULL;
151 }
152
153+ /*
154+ * A text array uses at least eight bytes per element, so any overflow in
155+ * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
156+ * However, credible improvements to the array format could invalidate
157+ * that assumption. Therefore, use an explicit check rather than relying
158+ * on palloc() to complain.
159+ */
160+ if (key_count > MaxAllocSize / sizeof(Pairs))
161+ ereport(ERROR,
162+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
163+ errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
164+ key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
165+
166 key_pairs = palloc(sizeof(Pairs) * key_count);
167
168 for (i = 0, j = 0; i < key_count; i++)
169@@ -647,6 +661,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
170 PG_RETURN_POINTER(out);
171 }
172
173+ /* hstoreArrayToPairs() checked overflow */
174 out_pairs = palloc(sizeof(Pairs) * nkeys);
175 bufsiz = 0;
176
177diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
178index 11c0698..755cd9e 100644
179--- a/contrib/intarray/_int.h
180+++ b/contrib/intarray/_int.h
181@@ -5,6 +5,7 @@
182 #define ___INT_H__
183
184 #include "utils/array.h"
185+#include "utils/memutils.h"
186
187 /* number ranges for compression */
188 #define MAXNUMRANGE 100
189@@ -137,6 +138,7 @@ typedef struct QUERYTYPE
190
191 #define HDRSIZEQT offsetof(QUERYTYPE, items)
192 #define COMPUTESIZE(size) ( HDRSIZEQT + (size) * sizeof(ITEM) )
193+#define QUERYTYPEMAXITEMS ((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
194 #define GETQUERY(x) ( (x)->items )
195
196 /* "type" codes for ITEM */
197diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
198index 4e63f6d..62294d1 100644
199--- a/contrib/intarray/_int_bool.c
200+++ b/contrib/intarray/_int_bool.c
201@@ -451,6 +451,9 @@ boolop(PG_FUNCTION_ARGS)
202 static void
203 findoprnd(ITEM *ptr, int4 *pos)
204 {
205+ /* since this function recurses, it could be driven to stack overflow. */
206+ check_stack_depth();
207+
208 #ifdef BS_DEBUG
209 elog(DEBUG3, (ptr[*pos].type == OPR) ?
210 "%d %c" : "%d %d", *pos, ptr[*pos].val);
211@@ -511,7 +514,13 @@ bqarr_in(PG_FUNCTION_ARGS)
212 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
213 errmsg("empty query")));
214
215+ if (state.num > QUERYTYPEMAXITEMS)
216+ ereport(ERROR,
217+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
218+ errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
219+ state.num, (int) QUERYTYPEMAXITEMS)));
220 commonlen = COMPUTESIZE(state.num);
221+
222 query = (QUERYTYPE *) palloc(commonlen);
223 SET_VARSIZE(query, commonlen);
224 query->size = state.num;
225diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
226index aec4458..49e9907 100644
227--- a/contrib/ltree/ltree.h
228+++ b/contrib/ltree/ltree.h
229@@ -5,6 +5,7 @@
230
231 #include "fmgr.h"
232 #include "tsearch/ts_locale.h"
233+#include "utils/memutils.h"
234
235 typedef struct
236 {
237@@ -111,6 +112,8 @@ typedef struct
238
239 #define HDRSIZEQT MAXALIGN(VARHDRSZ + sizeof(int4))
240 #define COMPUTESIZE(size,lenofoperand) ( HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand) )
241+#define LTXTQUERY_TOO_BIG(size,lenofoperand) \
242+ ((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM))
243 #define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
244 #define GETOPERAND(x) ( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
245
246diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
247index 3e88b81..d64debb 100644
248--- a/contrib/ltree/ltree_io.c
249+++ b/contrib/ltree/ltree_io.c
250@@ -8,6 +8,7 @@
251 #include <ctype.h>
252
253 #include "ltree.h"
254+#include "utils/memutils.h"
255 #include "crc32.h"
256
257 PG_FUNCTION_INFO_V1(ltree_in);
258@@ -64,6 +65,11 @@ ltree_in(PG_FUNCTION_ARGS)
259 ptr += charlen;
260 }
261
262+ if (num + 1 > MaxAllocSize / sizeof(nodeitem))
263+ ereport(ERROR,
264+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
265+ errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
266+ num + 1, (int) (MaxAllocSize / sizeof(nodeitem)))));
267 list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
268 ptr = buf;
269 while (*ptr)
270@@ -228,6 +234,11 @@ lquery_in(PG_FUNCTION_ARGS)
271 }
272
273 num++;
274+ if (num > MaxAllocSize / ITEMSIZE)
275+ ereport(ERROR,
276+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
277+ errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
278+ num, (int) (MaxAllocSize / ITEMSIZE))));
279 curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
280 ptr = buf;
281 while (*ptr)
282diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
283index 826f4e1..13ea58d 100644
284--- a/contrib/ltree/ltxtquery_io.c
285+++ b/contrib/ltree/ltxtquery_io.c
286@@ -9,6 +9,7 @@
287
288 #include "crc32.h"
289 #include "ltree.h"
290+#include "miscadmin.h"
291
292 PG_FUNCTION_INFO_V1(ltxtq_in);
293 Datum ltxtq_in(PG_FUNCTION_ARGS);
294@@ -213,6 +214,9 @@ makepol(QPRS_STATE *state)
295 int4 lenstack = 0;
296 uint16 flag = 0;
297
298+ /* since this function recurses, it could be driven to stack overflow */
299+ check_stack_depth();
300+
301 while ((type = gettoken_query(state, &val, &lenval, &strval, &flag)) != END)
302 {
303 switch (type)
304@@ -277,6 +281,9 @@ makepol(QPRS_STATE *state)
305 static void
306 findoprnd(ITEM *ptr, int4 *pos)
307 {
308+ /* since this function recurses, it could be driven to stack overflow. */
309+ check_stack_depth();
310+
311 if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE)
312 {
313 ptr[*pos].left = 0;
314@@ -341,8 +348,12 @@ queryin(char *buf)
315 errmsg("syntax error"),
316 errdetail("Empty query.")));
317
318- /* make finish struct */
319+ if (LTXTQUERY_TOO_BIG(state.num, state.sumlen))
320+ ereport(ERROR,
321+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
322+ errmsg("ltxtquery is too large")));
323 commonlen = COMPUTESIZE(state.num, state.sumlen);
324+
325 query = (ltxtquery *) palloc(commonlen);
326 SET_VARSIZE(query, commonlen);
327 query->size = state.num;
328diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
329index ac7b4b8..7ebcaaa 100644
330--- a/src/backend/utils/adt/geo_ops.c
331+++ b/src/backend/utils/adt/geo_ops.c
332@@ -1403,6 +1403,7 @@ path_in(PG_FUNCTION_ARGS)
333 char *s;
334 int npts;
335 int size;
336+ int base_size;
337 int depth = 0;
338
339 if ((npts = pair_count(str, ',')) <= 0)
340@@ -1421,7 +1422,15 @@ path_in(PG_FUNCTION_ARGS)
341 depth++;
342 }
343
344- size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
345+ base_size = sizeof(path->p[0]) * npts;
346+ size = offsetof(PATH, p[0]) + base_size;
347+
348+ /* Check for integer overflow */
349+ if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
350+ ereport(ERROR,
351+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
352+ errmsg("too many points requested")));
353+
354 path = (PATH *) palloc(size);
355
356 SET_VARSIZE(path, size);
357@@ -3465,6 +3474,7 @@ poly_in(PG_FUNCTION_ARGS)
358 POLYGON *poly;
359 int npts;
360 int size;
361+ int base_size;
362 int isopen;
363 char *s;
364
365@@ -3473,7 +3483,15 @@ poly_in(PG_FUNCTION_ARGS)
366 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
367 errmsg("invalid input syntax for type polygon: \"%s\"", str)));
368
369- size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
370+ base_size = sizeof(poly->p[0]) * npts;
371+ size = offsetof(POLYGON, p[0]) + base_size;
372+
373+ /* Check for integer overflow */
374+ if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
375+ ereport(ERROR,
376+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
377+ errmsg("too many points requested")));
378+
379 poly = (POLYGON *) palloc0(size); /* zero any holes */
380
381 SET_VARSIZE(poly, size);
382@@ -4379,6 +4397,10 @@ path_poly(PG_FUNCTION_ARGS)
383 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
384 errmsg("open path cannot be converted to polygon")));
385
386+ /*
387+ * Never overflows: the old size fit in MaxAllocSize, and the new size is
388+ * just a small constant larger.
389+ */
390 size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * path->npts;
391 poly = (POLYGON *) palloc(size);
392
393@@ -4484,6 +4506,10 @@ poly_path(PG_FUNCTION_ARGS)
394 int size;
395 int i;
396
397+ /*
398+ * Never overflows: the old size fit in MaxAllocSize, and the new size is
399+ * smaller by a small constant.
400+ */
401 size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * poly->npts;
402 path = (PATH *) palloc(size);
403
404diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
405index 6e1f8cf..1322b5e 100644
406--- a/src/backend/utils/adt/tsquery.c
407+++ b/src/backend/utils/adt/tsquery.c
408@@ -515,8 +515,13 @@ parse_tsquery(char *buf,
409 return query;
410 }
411
412- /* Pack the QueryItems in the final TSQuery struct to return to caller */
413+ if (TSQUERY_TOO_BIG(list_length(state.polstr), state.sumlen))
414+ ereport(ERROR,
415+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
416+ errmsg("tsquery is too large")));
417 commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen);
418+
419+ /* Pack the QueryItems in the final TSQuery struct to return to caller */
420 query = (TSQuery) palloc0(commonlen);
421 SET_VARSIZE(query, commonlen);
422 query->size = list_length(state.polstr);
423diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c
424index 0724d33..9003702 100644
425--- a/src/backend/utils/adt/tsquery_util.c
426+++ b/src/backend/utils/adt/tsquery_util.c
427@@ -333,6 +333,11 @@ QTN2QT(QTNode *in)
428 QTN2QTState state;
429
430 cntsize(in, &sumlen, &nnode);
431+
432+ if (TSQUERY_TOO_BIG(nnode, sumlen))
433+ ereport(ERROR,
434+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
435+ errmsg("tsquery is too large")));
436 len = COMPUTESIZE(nnode, sumlen);
437
438 out = (TSQuery) palloc0(len);
439diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
440index 08a8c89..c71daaf 100644
441--- a/src/backend/utils/adt/txid.c
442+++ b/src/backend/utils/adt/txid.c
443@@ -27,6 +27,7 @@
444 #include "miscadmin.h"
445 #include "libpq/pqformat.h"
446 #include "utils/builtins.h"
447+#include "utils/memutils.h"
448 #include "utils/snapmgr.h"
449
450
451@@ -66,6 +67,8 @@ typedef struct
452
453 #define TXID_SNAPSHOT_SIZE(nxip) \
454 (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))
455+#define TXID_SNAPSHOT_MAX_NXIP \
456+ ((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))
457
458 /*
459 * Epoch values from xact.c
460@@ -445,20 +448,12 @@ txid_snapshot_recv(PG_FUNCTION_ARGS)
461 txid last = 0;
462 int nxip;
463 int i;
464- int avail;
465- int expect;
466 txid xmin,
467 xmax;
468
469- /*
470- * load nxip and check for nonsense.
471- *
472- * (nxip > avail) check is against int overflows in 'expect'.
473- */
474+ /* load and validate nxip */
475 nxip = pq_getmsgint(buf, 4);
476- avail = buf->len - buf->cursor;
477- expect = 8 + 8 + nxip * 8;
478- if (nxip < 0 || nxip > avail || expect > avail)
479+ if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP)
480 goto bad_format;
481
482 xmin = pq_getmsgint64(buf);
483diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
484index 2bcf5b8..0deefda 100644
485--- a/src/backend/utils/adt/varbit.c
486+++ b/src/backend/utils/adt/varbit.c
487@@ -148,12 +148,22 @@ bit_in(PG_FUNCTION_ARGS)
488 sp = input_string;
489 }
490
491+ /*
492+ * Determine bitlength from input string. MaxAllocSize ensures a regular
493+ * input is small enough, but we must check hex input.
494+ */
495 slen = strlen(sp);
496- /* Determine bitlength from input string */
497 if (bit_not_hex)
498 bitlen = slen;
499 else
500+ {
501+ if (slen > VARBITMAXLEN / 4)
502+ ereport(ERROR,
503+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
504+ errmsg("bit string length exceeds the maximum allowed (%d)",
505+ VARBITMAXLEN)));
506 bitlen = slen * 4;
507+ }
508
509 /*
510 * Sometimes atttypmod is not supplied. If it is supplied we need to make
511@@ -450,12 +460,22 @@ varbit_in(PG_FUNCTION_ARGS)
512 sp = input_string;
513 }
514
515+ /*
516+ * Determine bitlength from input string. MaxAllocSize ensures a regular
517+ * input is small enough, but we must check hex input.
518+ */
519 slen = strlen(sp);
520- /* Determine bitlength from input string */
521 if (bit_not_hex)
522 bitlen = slen;
523 else
524+ {
525+ if (slen > VARBITMAXLEN / 4)
526+ ereport(ERROR,
527+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
528+ errmsg("bit string length exceeds the maximum allowed (%d)",
529+ VARBITMAXLEN)));
530 bitlen = slen * 4;
531+ }
532
533 /*
534 * Sometimes atttypmod is not supplied. If it is supplied we need to make
535@@ -535,6 +555,9 @@ varbit_in(PG_FUNCTION_ARGS)
536 /*
537 * varbit_out -
538 * Prints the string as bits to preserve length accurately
539+ *
540+ * XXX varbit_recv() and hex input to varbit_in() can load a value that this
541+ * cannot emit. Consider using hex output for such values.
542 */
543 Datum
544 varbit_out(PG_FUNCTION_ARGS)
545@@ -944,6 +967,11 @@ bit_catenate(VarBit *arg1, VarBit *arg2)
546 bitlen1 = VARBITLEN(arg1);
547 bitlen2 = VARBITLEN(arg2);
548
549+ if (bitlen1 > VARBITMAXLEN - bitlen2)
550+ ereport(ERROR,
551+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
552+ errmsg("bit string length exceeds the maximum allowed (%d)",
553+ VARBITMAXLEN)));
554 bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
555
556 result = (VarBit *) palloc(bytelen);
557diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h
558index 3adc336..9ee5610 100644
559--- a/src/include/tsearch/ts_type.h
560+++ b/src/include/tsearch/ts_type.h
561@@ -13,6 +13,7 @@
562 #define _PG_TSTYPE_H_
563
564 #include "fmgr.h"
565+#include "utils/memutils.h"
566 #include "utils/pg_crc.h"
567
568
569@@ -244,6 +245,8 @@ typedef TSQueryData *TSQuery;
570 * QueryItems, and lenofoperand is the total length of all operands
571 */
572 #define COMPUTESIZE(size, lenofoperand) ( HDRSIZETQ + (size) * sizeof(QueryItem) + (lenofoperand) )
573+#define TSQUERY_TOO_BIG(size, lenofoperand) \
574+ ((size) > (MaxAllocSize - HDRSIZETQ - (lenofoperand)) / sizeof(QueryItem))
575
576 /* Returns a pointer to the first QueryItem in a TSQuery */
577 #define GETQUERY(x) ((QueryItem*)( (char*)(x)+HDRSIZETQ ))
578diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
579index 52dca8b..61531a8 100644
580--- a/src/include/utils/varbit.h
581+++ b/src/include/utils/varbit.h
582@@ -15,6 +15,8 @@
583 #ifndef VARBIT_H
584 #define VARBIT_H
585
586+#include <limits.h>
587+
588 #include "fmgr.h"
589
590 /*
591@@ -53,6 +55,11 @@ typedef struct
592 /* Number of bytes needed to store a bit string of a given length */
593 #define VARBITTOTALLEN(BITLEN) (((BITLEN) + BITS_PER_BYTE-1)/BITS_PER_BYTE + \
594 VARHDRSZ + VARBITHDRSZ)
595+/*
596+ * Maximum number of bits. Several code sites assume no overflow from
597+ * computing bitlen + X; VARBITTOTALLEN() has the largest such X.
598+ */
599+#define VARBITMAXLEN (INT_MAX - BITS_PER_BYTE + 1)
600 /* pointer beyond the end of the bit string (like end() in STL containers) */
601 #define VARBITEND(PTR) (((bits8 *) (PTR)) + VARSIZE(PTR))
602 /* Mask that will cover exactly one byte, i.e. BITS_PER_BYTE bits */
603--
6041.7.5.4
605
diff --git a/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch b/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch
new file mode 100644
index 000000000..abbe14249
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0003-Shore-up-ADMIN-OPTION-restrictions.patch
@@ -0,0 +1,273 @@
1From 15a8f97b9d16aaf659f58c981242b9da591cf24c Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Mon, 17 Feb 2014 09:33:31 -0500
4Subject: [PATCH] Shore up ADMIN OPTION restrictions.
5
6commit 15a8f97b9d16aaf659f58c981242b9da591cf24c REL9_2_STABLE
7
8Granting a role without ADMIN OPTION is supposed to prevent the grantee
9from adding or removing members from the granted role. Issuing SET ROLE
10before the GRANT bypassed that, because the role itself had an implicit
11right to add or remove members. Plug that hole by recognizing that
12implicit right only when the session user matches the current role.
13Additionally, do not recognize it during a security-restricted operation
14or during execution of a SECURITY DEFINER function. The restriction on
15SECURITY DEFINER is not security-critical. However, it seems best for a
16user testing his own SECURITY DEFINER function to see the same behavior
17others will see. Back-patch to 8.4 (all supported versions).
18
19The SQL standards do not conflate roles and users as PostgreSQL does;
20only SQL roles have members, and only SQL users initiate sessions. An
21application using PostgreSQL users and roles as SQL users and roles will
22never attempt to grant membership in the role that is the session user,
23so the implicit right to add or remove members will never arise.
24
25The security impact was mostly that a role member could revoke access
26from others, contrary to the wishes of his own grantor. Unapproved role
27member additions are less notable, because the member can still largely
28achieve that by creating a view or a SECURITY DEFINER function.
29
30Reviewed by Andres Freund and Tom Lane. Reported, independently, by
31Jonas Sundman and Noah Misch.
32
33Security: CVE-2014-0060
34
35
36Upstream-Status: Backport
37
38Signed-off-by: Kai Kang <kai.kang@windriver.com>
39---
40 doc/src/sgml/ref/grant.sgml | 12 ++++---
41 src/backend/commands/user.c | 11 ++++++-
42 src/backend/utils/adt/acl.c | 50 ++++++++++++++++++++++++------
43 src/test/regress/expected/privileges.out | 36 +++++++++++++++++++++-
44 src/test/regress/sql/privileges.sql | 29 ++++++++++++++++-
45 5 files changed, 120 insertions(+), 18 deletions(-)
46
47diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
48index fb81af4..2b5a843 100644
49--- a/doc/src/sgml/ref/grant.sgml
50+++ b/doc/src/sgml/ref/grant.sgml
51@@ -396,11 +396,13 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
52 <para>
53 If <literal>WITH ADMIN OPTION</literal> is specified, the member can
54 in turn grant membership in the role to others, and revoke membership
55- in the role as well. Without the admin option, ordinary users cannot do
56- that. However,
57- database superusers can grant or revoke membership in any role to anyone.
58- Roles having <literal>CREATEROLE</> privilege can grant or revoke
59- membership in any role that is not a superuser.
60+ in the role as well. Without the admin option, ordinary users cannot
61+ do that. A role is not considered to hold <literal>WITH ADMIN
62+ OPTION</literal> on itself, but it may grant or revoke membership in
63+ itself from a database session where the session user matches the
64+ role. Database superusers can grant or revoke membership in any role
65+ to anyone. Roles having <literal>CREATEROLE</> privilege can grant
66+ or revoke membership in any role that is not a superuser.
67 </para>
68
69 <para>
70diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
71index a22092c..39bf172 100644
72--- a/src/backend/commands/user.c
73+++ b/src/backend/commands/user.c
74@@ -1334,7 +1334,16 @@ AddRoleMems(const char *rolename, Oid roleid,
75 rolename)));
76 }
77
78- /* XXX not sure about this check */
79+ /*
80+ * The role membership grantor of record has little significance at
81+ * present. Nonetheless, inasmuch as users might look to it for a crude
82+ * audit trail, let only superusers impute the grant to a third party.
83+ *
84+ * Before lifting this restriction, give the member == role case of
85+ * is_admin_of_role() a fresh look. Ensure that the current role cannot
86+ * use an explicit grantor specification to take advantage of the session
87+ * user's self-admin right.
88+ */
89 if (grantorId != GetUserId() && !superuser())
90 ereport(ERROR,
91 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
92diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
93index 1d6ae8b..9a52edb 100644
94--- a/src/backend/utils/adt/acl.c
95+++ b/src/backend/utils/adt/acl.c
96@@ -4580,6 +4580,11 @@ pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
97 {
98 if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE))
99 {
100+ /*
101+ * XXX For roleid == role_oid, is_admin_of_role() also examines the
102+ * session and call stack. That suits two-argument pg_has_role(), but
103+ * it gives the three-argument version a lamentable whimsy.
104+ */
105 if (is_admin_of_role(roleid, role_oid))
106 return ACLCHECK_OK;
107 }
108@@ -4897,11 +4902,9 @@ is_member_of_role_nosuper(Oid member, Oid role)
109
110
111 /*
112- * Is member an admin of role (directly or indirectly)? That is, is it
113- * a member WITH ADMIN OPTION?
114- *
115- * We could cache the result as for is_member_of_role, but currently this
116- * is not used in any performance-critical paths, so we don't.
117+ * Is member an admin of role? That is, is member the role itself (subject to
118+ * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
119+ * or a superuser?
120 */
121 bool
122 is_admin_of_role(Oid member, Oid role)
123@@ -4910,14 +4913,41 @@ is_admin_of_role(Oid member, Oid role)
124 List *roles_list;
125 ListCell *l;
126
127- /* Fast path for simple case */
128- if (member == role)
129- return true;
130-
131- /* Superusers have every privilege, so are part of every role */
132 if (superuser_arg(member))
133 return true;
134
135+ if (member == role)
136+ /*
137+ * A role can admin itself when it matches the session user and we're
138+ * outside any security-restricted operation, SECURITY DEFINER or
139+ * similar context. SQL-standard roles cannot self-admin. However,
140+ * SQL-standard users are distinct from roles, and they are not
141+ * grantable like roles: PostgreSQL's role-user duality extends the
142+ * standard. Checking for a session user match has the effect of
143+ * letting a role self-admin only when it's conspicuously behaving
144+ * like a user. Note that allowing self-admin under a mere SET ROLE
145+ * would make WITH ADMIN OPTION largely irrelevant; any member could
146+ * SET ROLE to issue the otherwise-forbidden command.
147+ *
148+ * Withholding self-admin in a security-restricted operation prevents
149+ * object owners from harnessing the session user identity during
150+ * administrative maintenance. Suppose Alice owns a database, has
151+ * issued "GRANT alice TO bob", and runs a daily ANALYZE. Bob creates
152+ * an alice-owned SECURITY DEFINER function that issues "REVOKE alice
153+ * FROM carol". If he creates an expression index calling that
154+ * function, Alice will attempt the REVOKE during each ANALYZE.
155+ * Checking InSecurityRestrictedOperation() thwarts that attack.
156+ *
157+ * Withholding self-admin in SECURITY DEFINER functions makes their
158+ * behavior independent of the calling user. There's no security or
159+ * SQL-standard-conformance need for that restriction, though.
160+ *
161+ * A role cannot have actual WITH ADMIN OPTION on itself, because that
162+ * would imply a membership loop. Therefore, we're done either way.
163+ */
164+ return member == GetSessionUserId() &&
165+ !InLocalUserIdChange() && !InSecurityRestrictedOperation();
166+
167 /*
168 * Find all the roles that member is a member of, including multi-level
169 * recursion. We build a list in the same way that is_member_of_role does
170diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
171index e8930cb..bc6d731 100644
172--- a/src/test/regress/expected/privileges.out
173+++ b/src/test/regress/expected/privileges.out
174@@ -32,7 +32,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4;
175 ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate
176 NOTICE: role "regressuser2" is already a member of role "regressgroup2"
177 ALTER GROUP regressgroup2 DROP USER regressuser2;
178-ALTER GROUP regressgroup2 ADD USER regressuser4;
179+GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION;
180 -- test owner privileges
181 SET SESSION AUTHORIZATION regressuser1;
182 SELECT session_user, current_user;
183@@ -929,6 +929,40 @@ SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION')
184 t
185 (1 row)
186
187+-- Admin options
188+SET SESSION AUTHORIZATION regressuser4;
189+CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS
190+ 'GRANT regressgroup2 TO regressuser5';
191+GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION
192+SET ROLE regressgroup2;
193+GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege
194+ERROR: must have admin option on role "regressgroup2"
195+SET SESSION AUTHORIZATION regressuser1;
196+GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION
197+ERROR: must have admin option on role "regressgroup2"
198+SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN
199+NOTICE: role "regressuser5" is already a member of role "regressgroup2"
200+CONTEXT: SQL function "dogrant_ok" statement 1
201+ dogrant_ok
202+------------
203+
204+(1 row)
205+
206+SET ROLE regressgroup2;
207+GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help
208+ERROR: must have admin option on role "regressgroup2"
209+SET SESSION AUTHORIZATION regressgroup2;
210+GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin
211+NOTICE: role "regressuser5" is already a member of role "regressgroup2"
212+CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS
213+ 'GRANT regressgroup2 TO regressuser5';
214+SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER
215+ERROR: must have admin option on role "regressgroup2"
216+CONTEXT: SQL function "dogrant_fails" statement 1
217+DROP FUNCTION dogrant_fails();
218+SET SESSION AUTHORIZATION regressuser4;
219+DROP FUNCTION dogrant_ok();
220+REVOKE regressgroup2 FROM regressuser5;
221 -- has_sequence_privilege tests
222 \c -
223 CREATE SEQUENCE x_seq;
224diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
225index d4d328e..5f1018a 100644
226--- a/src/test/regress/sql/privileges.sql
227+++ b/src/test/regress/sql/privileges.sql
228@@ -37,7 +37,7 @@ ALTER GROUP regressgroup1 ADD USER regressuser4;
229
230 ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate
231 ALTER GROUP regressgroup2 DROP USER regressuser2;
232-ALTER GROUP regressgroup2 ADD USER regressuser4;
233+GRANT regressgroup2 TO regressuser4 WITH ADMIN OPTION;
234
235 -- test owner privileges
236
237@@ -581,6 +581,33 @@ SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- false
238 SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true
239
240
241+-- Admin options
242+
243+SET SESSION AUTHORIZATION regressuser4;
244+CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS
245+ 'GRANT regressgroup2 TO regressuser5';
246+GRANT regressgroup2 TO regressuser5; -- ok: had ADMIN OPTION
247+SET ROLE regressgroup2;
248+GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE suspended privilege
249+
250+SET SESSION AUTHORIZATION regressuser1;
251+GRANT regressgroup2 TO regressuser5; -- fails: no ADMIN OPTION
252+SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN
253+SET ROLE regressgroup2;
254+GRANT regressgroup2 TO regressuser5; -- fails: SET ROLE did not help
255+
256+SET SESSION AUTHORIZATION regressgroup2;
257+GRANT regressgroup2 TO regressuser5; -- ok: a role can self-admin
258+CREATE FUNCTION dogrant_fails() RETURNS void LANGUAGE sql SECURITY DEFINER AS
259+ 'GRANT regressgroup2 TO regressuser5';
260+SELECT dogrant_fails(); -- fails: no self-admin in SECURITY DEFINER
261+DROP FUNCTION dogrant_fails();
262+
263+SET SESSION AUTHORIZATION regressuser4;
264+DROP FUNCTION dogrant_ok();
265+REVOKE regressgroup2 FROM regressuser5;
266+
267+
268 -- has_sequence_privilege tests
269 \c -
270
271--
2721.7.5.4
273
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 @@
1From 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Mon, 17 Feb 2014 09:33:31 -0500
4Subject: [PATCH] Prevent privilege escalation in explicit calls to PL
5 validators.
6
7commit 1d701d28a796ea2d1a4d2be9e9ee06209eaea040 REL9_2_STABLE
8
9The primary role of PL validators is to be called implicitly during
10CREATE FUNCTION, but they are also normal functions that a user can call
11explicitly. Add a permissions check to each validator to ensure that a
12user cannot use explicit validator calls to achieve things he could not
13otherwise achieve. Back-patch to 8.4 (all supported versions).
14Non-core procedural language extensions ought to make the same two-line
15change to their own validators.
16
17Andres Freund, reviewed by Tom Lane and Noah Misch.
18
19Security: CVE-2014-0061
20
21Upstream-Status: Backport
22Signed-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
34diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml
35index 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,
50diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
51index 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);
84diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
85index 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 *
96diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
97index 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+}
195diff --git a/src/include/fmgr.h b/src/include/fmgr.h
196index 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
207diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
208index 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
229diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
230index 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))
243diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
244index 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--
2661.7.5.4
267
diff --git a/meta-oe/recipes-support/postgresql/files/0005-Avoid-repeated-name-lookups-during-table-and-index-D.patch b/meta-oe/recipes-support/postgresql/files/0005-Avoid-repeated-name-lookups-during-table-and-index-D.patch
new file mode 100644
index 000000000..f1aa21250
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0005-Avoid-repeated-name-lookups-during-table-and-index-D.patch
@@ -0,0 +1,1082 @@
1From 820ab11fbfd508fc75a39c43ad2c1b3e79c4982b Mon Sep 17 00:00:00 2001
2From: Robert Haas <rhaas@postgresql.org>
3Date: Mon, 17 Feb 2014 09:33:31 -0500
4Subject: [PATCH] Avoid repeated name lookups during table and index DDL.
5
6commit 820ab11fbfd508fc75a39c43ad2c1b3e79c4982b REL9_2_STABLE
7
8If the name lookups come to different conclusions due to concurrent
9activity, we might perform some parts of the DDL on a different table
10than other parts. At least in the case of CREATE INDEX, this can be
11used to cause the permissions checks to be performed against a
12different table than the index creation, allowing for a privilege
13escalation attack.
14
15This changes the calling convention for DefineIndex, CreateTrigger,
16transformIndexStmt, transformAlterTableStmt, CheckIndexCompatible
17(in 9.2 and newer), and AlterTable (in 9.1 and older). In addition,
18CheckRelationOwnership is removed in 9.2 and newer and the calling
19convention is changed in older branches. A field has also been added
20to the Constraint node (FkConstraint in 8.4). Third-party code calling
21these functions or using the Constraint node will require updating.
22
23Report by Andres Freund. Patch by Robert Haas and Andres Freund,
24reviewed by Tom Lane.
25
26Security: CVE-2014-0062
27
28Upstream-Status: Backport
29
30Signed-off-by: Kai Kang <kai.kang@windriver.com>
31---
32 src/backend/bootstrap/bootparse.y | 17 ++++-
33 src/backend/catalog/index.c | 10 +--
34 src/backend/catalog/pg_constraint.c | 19 +++++
35 src/backend/commands/indexcmds.c | 22 ++++--
36 src/backend/commands/tablecmds.c | 137 +++++++++++++++++++++++++----------
37 src/backend/commands/trigger.c | 28 ++++++--
38 src/backend/nodes/copyfuncs.c | 1 +
39 src/backend/nodes/equalfuncs.c | 1 +
40 src/backend/nodes/outfuncs.c | 1 +
41 src/backend/parser/parse_utilcmd.c | 64 ++++++-----------
42 src/backend/tcop/utility.c | 73 +++++++------------
43 src/include/catalog/pg_constraint.h | 1 +
44 src/include/commands/defrem.h | 4 +-
45 src/include/commands/tablecmds.h | 2 +
46 src/include/commands/trigger.h | 2 +-
47 src/include/nodes/parsenodes.h | 2 +
48 src/include/parser/parse_utilcmd.h | 5 +-
49 src/include/tcop/utility.h | 2 -
50 18 files changed, 234 insertions(+), 157 deletions(-)
51
52diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
53index f4a1b8f..eeffb0f 100644
54--- a/src/backend/bootstrap/bootparse.y
55+++ b/src/backend/bootstrap/bootparse.y
56@@ -27,6 +27,7 @@
57 #include "bootstrap/bootstrap.h"
58 #include "catalog/catalog.h"
59 #include "catalog/heap.h"
60+#include "catalog/namespace.h"
61 #include "catalog/pg_am.h"
62 #include "catalog/pg_attribute.h"
63 #include "catalog/pg_authid.h"
64@@ -281,6 +282,7 @@ Boot_DeclareIndexStmt:
65 XDECLARE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
66 {
67 IndexStmt *stmt = makeNode(IndexStmt);
68+ Oid relationId;
69
70 do_start();
71
72@@ -302,7 +304,12 @@ Boot_DeclareIndexStmt:
73 stmt->initdeferred = false;
74 stmt->concurrent = false;
75
76- DefineIndex(stmt,
77+ /* locks and races need not concern us in bootstrap mode */
78+ relationId = RangeVarGetRelid(stmt->relation, NoLock,
79+ false);
80+
81+ DefineIndex(relationId,
82+ stmt,
83 $4,
84 false,
85 false,
86@@ -316,6 +323,7 @@ Boot_DeclareUniqueIndexStmt:
87 XDECLARE UNIQUE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
88 {
89 IndexStmt *stmt = makeNode(IndexStmt);
90+ Oid relationId;
91
92 do_start();
93
94@@ -337,7 +345,12 @@ Boot_DeclareUniqueIndexStmt:
95 stmt->initdeferred = false;
96 stmt->concurrent = false;
97
98- DefineIndex(stmt,
99+ /* locks and races need not concern us in bootstrap mode */
100+ relationId = RangeVarGetRelid(stmt->relation, NoLock,
101+ false);
102+
103+ DefineIndex(relationId,
104+ stmt,
105 $5,
106 false,
107 false,
108diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
109index 7d6346a..ca8acf3 100644
110--- a/src/backend/catalog/index.c
111+++ b/src/backend/catalog/index.c
112@@ -1202,18 +1202,13 @@ index_constraint_create(Relation heapRelation,
113 */
114 if (deferrable)
115 {
116- RangeVar *heapRel;
117 CreateTrigStmt *trigger;
118
119- heapRel = makeRangeVar(get_namespace_name(namespaceId),
120- pstrdup(RelationGetRelationName(heapRelation)),
121- -1);
122-
123 trigger = makeNode(CreateTrigStmt);
124 trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
125 "PK_ConstraintTrigger" :
126 "Unique_ConstraintTrigger";
127- trigger->relation = heapRel;
128+ trigger->relation = NULL;
129 trigger->funcname = SystemFuncName("unique_key_recheck");
130 trigger->args = NIL;
131 trigger->row = true;
132@@ -1226,7 +1221,8 @@ index_constraint_create(Relation heapRelation,
133 trigger->initdeferred = initdeferred;
134 trigger->constrrel = NULL;
135
136- (void) CreateTrigger(trigger, NULL, conOid, indexRelationId, true);
137+ (void) CreateTrigger(trigger, NULL, RelationGetRelid(heapRelation),
138+ InvalidOid, conOid, indexRelationId, true);
139 }
140
141 /*
142diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
143index 107a780..08a94cf 100644
144--- a/src/backend/catalog/pg_constraint.c
145+++ b/src/backend/catalog/pg_constraint.c
146@@ -746,6 +746,25 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
147 }
148
149 /*
150+ * get_constraint_relation_oids
151+ * Find the IDs of the relations to which a constraint refers.
152+ */
153+void
154+get_constraint_relation_oids(Oid constraint_oid, Oid *conrelid, Oid *confrelid)
155+{
156+ HeapTuple tup;
157+ Form_pg_constraint con;
158+
159+ tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraint_oid));
160+ if (!HeapTupleIsValid(tup)) /* should not happen */
161+ elog(ERROR, "cache lookup failed for constraint %u", constraint_oid);
162+ con = (Form_pg_constraint) GETSTRUCT(tup);
163+ *conrelid = con->conrelid;
164+ *confrelid = con->confrelid;
165+ ReleaseSysCache(tup);
166+}
167+
168+/*
169 * get_relation_constraint_oid
170 * Find a constraint on the specified relation with the specified name.
171 * Returns constraint's OID.
172diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
173index f3ee278..ec5fb0d 100644
174--- a/src/backend/commands/indexcmds.c
175+++ b/src/backend/commands/indexcmds.c
176@@ -111,7 +111,6 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
177 */
178 bool
179 CheckIndexCompatible(Oid oldId,
180- RangeVar *heapRelation,
181 char *accessMethodName,
182 List *attributeList,
183 List *exclusionOpNames)
184@@ -139,7 +138,7 @@ CheckIndexCompatible(Oid oldId,
185 Datum d;
186
187 /* Caller should already have the relation locked in some way. */
188- relationId = RangeVarGetRelid(heapRelation, NoLock, false);
189+ relationId = IndexGetRelation(oldId, false);
190
191 /*
192 * We can pretend isconstraint = false unconditionally. It only serves to
193@@ -279,6 +278,8 @@ CheckIndexCompatible(Oid oldId,
194 * DefineIndex
195 * Creates a new index.
196 *
197+ * 'relationId': the OID of the heap relation on which the index is to be
198+ * created
199 * 'stmt': IndexStmt describing the properties of the new index.
200 * 'indexRelationId': normally InvalidOid, but during bootstrap can be
201 * nonzero to specify a preselected OID for the index.
202@@ -292,7 +293,8 @@ CheckIndexCompatible(Oid oldId,
203 * Returns the OID of the created index.
204 */
205 Oid
206-DefineIndex(IndexStmt *stmt,
207+DefineIndex(Oid relationId,
208+ IndexStmt *stmt,
209 Oid indexRelationId,
210 bool is_alter_table,
211 bool check_rights,
212@@ -305,7 +307,6 @@ DefineIndex(IndexStmt *stmt,
213 Oid *collationObjectId;
214 Oid *classObjectId;
215 Oid accessMethodId;
216- Oid relationId;
217 Oid namespaceId;
218 Oid tablespaceId;
219 List *indexColNames;
220@@ -325,6 +326,7 @@ DefineIndex(IndexStmt *stmt,
221 int n_old_snapshots;
222 LockRelId heaprelid;
223 LOCKTAG heaplocktag;
224+ LOCKMODE lockmode;
225 Snapshot snapshot;
226 int i;
227
228@@ -343,14 +345,18 @@ DefineIndex(IndexStmt *stmt,
229 INDEX_MAX_KEYS)));
230
231 /*
232- * Open heap relation, acquire a suitable lock on it, remember its OID
233- *
234 * Only SELECT ... FOR UPDATE/SHARE are allowed while doing a standard
235 * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE
236 * (but not VACUUM).
237+ *
238+ * NB: Caller is responsible for making sure that relationId refers
239+ * to the relation on which the index should be built; except in bootstrap
240+ * mode, this will typically require the caller to have already locked
241+ * the relation. To avoid lock upgrade hazards, that lock should be at
242+ * least as strong as the one we take here.
243 */
244- rel = heap_openrv(stmt->relation,
245- (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock));
246+ lockmode = stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock;
247+ rel = heap_open(relationId, lockmode);
248
249 relationId = RelationGetRelid(rel);
250 namespaceId = RelationGetNamespace(rel);
251diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
252index 7c1f779..bcb81ea 100644
253--- a/src/backend/commands/tablecmds.c
254+++ b/src/backend/commands/tablecmds.c
255@@ -283,7 +283,8 @@ static void validateCheckConstraint(Relation rel, HeapTuple constrtup);
256 static void validateForeignKeyConstraint(char *conname,
257 Relation rel, Relation pkrel,
258 Oid pkindOid, Oid constraintOid);
259-static void createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
260+static void createForeignKeyTriggers(Relation rel, Oid refRelOid,
261+ Constraint *fkconstraint,
262 Oid constraintOid, Oid indexOid);
263 static void ATController(Relation rel, List *cmds, bool recurse, LOCKMODE lockmode);
264 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
265@@ -360,8 +361,9 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
266 static void ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
267 List *options, LOCKMODE lockmode);
268 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode);
269-static void ATPostAlterTypeParse(Oid oldId, char *cmd,
270- List **wqueue, LOCKMODE lockmode, bool rewrite);
271+static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
272+ char *cmd, List **wqueue, LOCKMODE lockmode,
273+ bool rewrite);
274 static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
275 static void TryReuseForeignKey(Oid oldId, Constraint *con);
276 static void change_owner_fix_column_acls(Oid relationOid,
277@@ -5406,7 +5408,8 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
278
279 /* The IndexStmt has already been through transformIndexStmt */
280
281- new_index = DefineIndex(stmt,
282+ new_index = DefineIndex(RelationGetRelid(rel),
283+ stmt,
284 InvalidOid, /* no predefined OID */
285 true, /* is_alter_table */
286 check_rights,
287@@ -5728,7 +5731,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
288 * table; trying to start with a lesser lock will just create a risk of
289 * deadlock.)
290 */
291- pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
292+ if (OidIsValid(fkconstraint->old_pktable_oid))
293+ pkrel = heap_open(fkconstraint->old_pktable_oid, AccessExclusiveLock);
294+ else
295+ pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
296
297 /*
298 * Validity checks (permission checks wait till we have the column
299@@ -6066,7 +6072,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
300 /*
301 * Create the triggers that will enforce the constraint.
302 */
303- createForeignKeyTriggers(rel, fkconstraint, constrOid, indexOid);
304+ createForeignKeyTriggers(rel, RelationGetRelid(pkrel), fkconstraint,
305+ constrOid, indexOid);
306
307 /*
308 * Tell Phase 3 to check that the constraint is satisfied by existing
309@@ -6736,7 +6743,7 @@ validateForeignKeyConstraint(char *conname,
310 }
311
312 static void
313-CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
314+CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint,
315 Oid constraintOid, Oid indexOid, bool on_insert)
316 {
317 CreateTrigStmt *fk_trigger;
318@@ -6752,7 +6759,7 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
319 */
320 fk_trigger = makeNode(CreateTrigStmt);
321 fk_trigger->trigname = "RI_ConstraintTrigger_c";
322- fk_trigger->relation = myRel;
323+ fk_trigger->relation = NULL;
324 fk_trigger->row = true;
325 fk_trigger->timing = TRIGGER_TYPE_AFTER;
326
327@@ -6773,10 +6780,11 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
328 fk_trigger->isconstraint = true;
329 fk_trigger->deferrable = fkconstraint->deferrable;
330 fk_trigger->initdeferred = fkconstraint->initdeferred;
331- fk_trigger->constrrel = fkconstraint->pktable;
332+ fk_trigger->constrrel = NULL;
333 fk_trigger->args = NIL;
334
335- (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
336+ (void) CreateTrigger(fk_trigger, NULL, myRelOid, refRelOid, constraintOid,
337+ indexOid, true);
338
339 /* Make changes-so-far visible */
340 CommandCounterIncrement();
341@@ -6786,18 +6794,13 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
342 * Create the triggers that implement an FK constraint.
343 */
344 static void
345-createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
346+createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
347 Oid constraintOid, Oid indexOid)
348 {
349- RangeVar *myRel;
350+ Oid myRelOid;
351 CreateTrigStmt *fk_trigger;
352
353- /*
354- * Reconstruct a RangeVar for my relation (not passed in, unfortunately).
355- */
356- myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
357- pstrdup(RelationGetRelationName(rel)),
358- -1);
359+ myRelOid = RelationGetRelid(rel);
360
361 /* Make changes-so-far visible */
362 CommandCounterIncrement();
363@@ -6808,14 +6811,14 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
364 */
365 fk_trigger = makeNode(CreateTrigStmt);
366 fk_trigger->trigname = "RI_ConstraintTrigger_a";
367- fk_trigger->relation = fkconstraint->pktable;
368+ fk_trigger->relation = NULL;
369 fk_trigger->row = true;
370 fk_trigger->timing = TRIGGER_TYPE_AFTER;
371 fk_trigger->events = TRIGGER_TYPE_DELETE;
372 fk_trigger->columns = NIL;
373 fk_trigger->whenClause = NULL;
374 fk_trigger->isconstraint = true;
375- fk_trigger->constrrel = myRel;
376+ fk_trigger->constrrel = NULL;
377 switch (fkconstraint->fk_del_action)
378 {
379 case FKCONSTR_ACTION_NOACTION:
380@@ -6850,7 +6853,8 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
381 }
382 fk_trigger->args = NIL;
383
384- (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
385+ (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
386+ indexOid, true);
387
388 /* Make changes-so-far visible */
389 CommandCounterIncrement();
390@@ -6861,14 +6865,14 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
391 */
392 fk_trigger = makeNode(CreateTrigStmt);
393 fk_trigger->trigname = "RI_ConstraintTrigger_a";
394- fk_trigger->relation = fkconstraint->pktable;
395+ fk_trigger->relation = NULL;
396 fk_trigger->row = true;
397 fk_trigger->timing = TRIGGER_TYPE_AFTER;
398 fk_trigger->events = TRIGGER_TYPE_UPDATE;
399 fk_trigger->columns = NIL;
400 fk_trigger->whenClause = NULL;
401 fk_trigger->isconstraint = true;
402- fk_trigger->constrrel = myRel;
403+ fk_trigger->constrrel = NULL;
404 switch (fkconstraint->fk_upd_action)
405 {
406 case FKCONSTR_ACTION_NOACTION:
407@@ -6903,7 +6907,8 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
408 }
409 fk_trigger->args = NIL;
410
411- (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
412+ (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
413+ indexOid, true);
414
415 /* Make changes-so-far visible */
416 CommandCounterIncrement();
417@@ -6912,8 +6917,10 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
418 * Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK
419 * action for both INSERTs and UPDATEs on the referencing table.
420 */
421- CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, true);
422- CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, false);
423+ CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
424+ indexOid, true);
425+ CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
426+ indexOid, false);
427 }
428
429 /*
430@@ -7832,15 +7839,36 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
431 * lock on the table the constraint is attached to, and we need to get
432 * that before dropping. It's safe because the parser won't actually look
433 * at the catalogs to detect the existing entry.
434+ *
435+ * We can't rely on the output of deparsing to tell us which relation
436+ * to operate on, because concurrent activity might have made the name
437+ * resolve differently. Instead, we've got to use the OID of the
438+ * constraint or index we're processing to figure out which relation
439+ * to operate on.
440 */
441 forboth(oid_item, tab->changedConstraintOids,
442 def_item, tab->changedConstraintDefs)
443- ATPostAlterTypeParse(lfirst_oid(oid_item), (char *) lfirst(def_item),
444+ {
445+ Oid oldId = lfirst_oid(oid_item);
446+ Oid relid;
447+ Oid confrelid;
448+
449+ get_constraint_relation_oids(oldId, &relid, &confrelid);
450+ ATPostAlterTypeParse(oldId, relid, confrelid,
451+ (char *) lfirst(def_item),
452 wqueue, lockmode, tab->rewrite);
453+ }
454 forboth(oid_item, tab->changedIndexOids,
455 def_item, tab->changedIndexDefs)
456- ATPostAlterTypeParse(lfirst_oid(oid_item), (char *) lfirst(def_item),
457+ {
458+ Oid oldId = lfirst_oid(oid_item);
459+ Oid relid;
460+
461+ relid = IndexGetRelation(oldId, false);
462+ ATPostAlterTypeParse(oldId, relid, InvalidOid,
463+ (char *) lfirst(def_item),
464 wqueue, lockmode, tab->rewrite);
465+ }
466
467 /*
468 * Now we can drop the existing constraints and indexes --- constraints
469@@ -7873,12 +7901,13 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
470 }
471
472 static void
473-ATPostAlterTypeParse(Oid oldId, char *cmd,
474+ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
475 List **wqueue, LOCKMODE lockmode, bool rewrite)
476 {
477 List *raw_parsetree_list;
478 List *querytree_list;
479 ListCell *list_item;
480+ Relation rel;
481
482 /*
483 * We expect that we will get only ALTER TABLE and CREATE INDEX
484@@ -7894,16 +7923,21 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
485
486 if (IsA(stmt, IndexStmt))
487 querytree_list = lappend(querytree_list,
488- transformIndexStmt((IndexStmt *) stmt,
489+ transformIndexStmt(oldRelId,
490+ (IndexStmt *) stmt,
491 cmd));
492 else if (IsA(stmt, AlterTableStmt))
493 querytree_list = list_concat(querytree_list,
494- transformAlterTableStmt((AlterTableStmt *) stmt,
495+ transformAlterTableStmt(oldRelId,
496+ (AlterTableStmt *) stmt,
497 cmd));
498 else
499 querytree_list = lappend(querytree_list, stmt);
500 }
501
502+ /* Caller should already have acquired whatever lock we need. */
503+ rel = relation_open(oldRelId, NoLock);
504+
505 /*
506 * Attach each generated command to the proper place in the work queue.
507 * Note this could result in creation of entirely new work-queue entries.
508@@ -7915,7 +7949,6 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
509 foreach(list_item, querytree_list)
510 {
511 Node *stm = (Node *) lfirst(list_item);
512- Relation rel;
513 AlteredTableInfo *tab;
514
515 switch (nodeTag(stm))
516@@ -7928,14 +7961,12 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
517 if (!rewrite)
518 TryReuseIndex(oldId, stmt);
519
520- rel = relation_openrv(stmt->relation, lockmode);
521 tab = ATGetQueueEntry(wqueue, rel);
522 newcmd = makeNode(AlterTableCmd);
523 newcmd->subtype = AT_ReAddIndex;
524 newcmd->def = (Node *) stmt;
525 tab->subcmds[AT_PASS_OLD_INDEX] =
526 lappend(tab->subcmds[AT_PASS_OLD_INDEX], newcmd);
527- relation_close(rel, NoLock);
528 break;
529 }
530 case T_AlterTableStmt:
531@@ -7943,7 +7974,6 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
532 AlterTableStmt *stmt = (AlterTableStmt *) stm;
533 ListCell *lcmd;
534
535- rel = relation_openrv(stmt->relation, lockmode);
536 tab = ATGetQueueEntry(wqueue, rel);
537 foreach(lcmd, stmt->cmds)
538 {
539@@ -7964,6 +7994,7 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
540 case AT_AddConstraint:
541 Assert(IsA(cmd->def, Constraint));
542 con = (Constraint *) cmd->def;
543+ con->old_pktable_oid = refRelId;
544 /* rewriting neither side of a FK */
545 if (con->contype == CONSTR_FOREIGN &&
546 !rewrite && !tab->rewrite)
547@@ -7977,7 +8008,6 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
548 (int) cmd->subtype);
549 }
550 }
551- relation_close(rel, NoLock);
552 break;
553 }
554 default:
555@@ -7985,6 +8015,8 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
556 (int) nodeTag(stm));
557 }
558 }
559+
560+ relation_close(rel, NoLock);
561 }
562
563 /*
564@@ -7995,7 +8027,6 @@ static void
565 TryReuseIndex(Oid oldId, IndexStmt *stmt)
566 {
567 if (CheckIndexCompatible(oldId,
568- stmt->relation,
569 stmt->accessMethod,
570 stmt->indexParams,
571 stmt->excludeOpNames))
572@@ -10291,6 +10322,38 @@ RangeVarCallbackOwnsTable(const RangeVar *relation,
573 }
574
575 /*
576+ * Callback to RangeVarGetRelidExtended(), similar to
577+ * RangeVarCallbackOwnsTable() but without checks on the type of the relation.
578+ */
579+void
580+RangeVarCallbackOwnsRelation(const RangeVar *relation,
581+ Oid relId, Oid oldRelId, void *arg)
582+{
583+ HeapTuple tuple;
584+
585+ /* Nothing to do if the relation was not found. */
586+ if (!OidIsValid(relId))
587+ return;
588+
589+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
590+ if (!HeapTupleIsValid(tuple)) /* should not happen */
591+ elog(ERROR, "cache lookup failed for relation %u", relId);
592+
593+ if (!pg_class_ownercheck(relId, GetUserId()))
594+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
595+ relation->relname);
596+
597+ if (!allowSystemTableMods &&
598+ IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
599+ ereport(ERROR,
600+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
601+ errmsg("permission denied: \"%s\" is a system catalog",
602+ relation->relname)));
603+
604+ ReleaseSysCache(tuple);
605+}
606+
607+/*
608 * Common RangeVarGetRelid callback for rename, set schema, and alter table
609 * processing.
610 */
611diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
612index f546d94..9e6c954 100644
613--- a/src/backend/commands/trigger.c
614+++ b/src/backend/commands/trigger.c
615@@ -42,6 +42,7 @@
616 #include "pgstat.h"
617 #include "rewrite/rewriteManip.h"
618 #include "storage/bufmgr.h"
619+#include "storage/lmgr.h"
620 #include "tcop/utility.h"
621 #include "utils/acl.h"
622 #include "utils/builtins.h"
623@@ -94,6 +95,13 @@ static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
624 * queryString is the source text of the CREATE TRIGGER command.
625 * This must be supplied if a whenClause is specified, else it can be NULL.
626 *
627+ * relOid, if nonzero, is the relation on which the trigger should be
628+ * created. If zero, the name provided in the statement will be looked up.
629+ *
630+ * refRelOid, if nonzero, is the relation to which the constraint trigger
631+ * refers. If zero, the constraint relation name provided in the statement
632+ * will be looked up as needed.
633+ *
634 * constraintOid, if nonzero, says that this trigger is being created
635 * internally to implement that constraint. A suitable pg_depend entry will
636 * be made to link the trigger to that constraint. constraintOid is zero when
637@@ -116,7 +124,7 @@ static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
638 */
639 Oid
640 CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
641- Oid constraintOid, Oid indexOid,
642+ Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
643 bool isInternal)
644 {
645 int16 tgtype;
646@@ -145,7 +153,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
647 ObjectAddress myself,
648 referenced;
649
650- rel = heap_openrv(stmt->relation, AccessExclusiveLock);
651+ if (OidIsValid(relOid))
652+ rel = heap_open(relOid, AccessExclusiveLock);
653+ else
654+ rel = heap_openrv(stmt->relation, AccessExclusiveLock);
655
656 /*
657 * Triggers must be on tables or views, and there are additional
658@@ -194,7 +205,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
659 errmsg("permission denied: \"%s\" is a system catalog",
660 RelationGetRelationName(rel))));
661
662- if (stmt->isconstraint && stmt->constrrel != NULL)
663+ if (stmt->isconstraint)
664 {
665 /*
666 * We must take a lock on the target relation to protect against
667@@ -203,7 +214,14 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
668 * might end up creating a pg_constraint entry referencing a
669 * nonexistent table.
670 */
671- constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock, false);
672+ if (OidIsValid(refRelOid))
673+ {
674+ LockRelationOid(refRelOid, AccessShareLock);
675+ constrrelid = refRelOid;
676+ }
677+ else if (stmt->constrrel != NULL)
678+ constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock,
679+ false);
680 }
681
682 /* permission checks */
683@@ -513,7 +531,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
684 ereport(ERROR,
685 (errcode(ERRCODE_DUPLICATE_OBJECT),
686 errmsg("trigger \"%s\" for relation \"%s\" already exists",
687- trigname, stmt->relation->relname)));
688+ trigname, RelationGetRelationName(rel))));
689 }
690 systable_endscan(tgscan);
691 }
692diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
693index 9bac994..dbe0f6a 100644
694--- a/src/backend/nodes/copyfuncs.c
695+++ b/src/backend/nodes/copyfuncs.c
696@@ -2357,6 +2357,7 @@ _copyConstraint(const Constraint *from)
697 COPY_SCALAR_FIELD(fk_upd_action);
698 COPY_SCALAR_FIELD(fk_del_action);
699 COPY_NODE_FIELD(old_conpfeqop);
700+ COPY_SCALAR_FIELD(old_pktable_oid);
701 COPY_SCALAR_FIELD(skip_validation);
702 COPY_SCALAR_FIELD(initially_valid);
703
704diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
705index d185654..f8770b0 100644
706--- a/src/backend/nodes/equalfuncs.c
707+++ b/src/backend/nodes/equalfuncs.c
708@@ -2143,6 +2143,7 @@ _equalConstraint(const Constraint *a, const Constraint *b)
709 COMPARE_SCALAR_FIELD(fk_upd_action);
710 COMPARE_SCALAR_FIELD(fk_del_action);
711 COMPARE_NODE_FIELD(old_conpfeqop);
712+ COMPARE_SCALAR_FIELD(old_pktable_oid);
713 COMPARE_SCALAR_FIELD(skip_validation);
714 COMPARE_SCALAR_FIELD(initially_valid);
715
716diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
717index 1df71f6..888ffd2 100644
718--- a/src/backend/nodes/outfuncs.c
719+++ b/src/backend/nodes/outfuncs.c
720@@ -2653,6 +2653,7 @@ _outConstraint(StringInfo str, const Constraint *node)
721 WRITE_CHAR_FIELD(fk_upd_action);
722 WRITE_CHAR_FIELD(fk_del_action);
723 WRITE_NODE_FIELD(old_conpfeqop);
724+ WRITE_OID_FIELD(old_pktable_oid);
725 WRITE_BOOL_FIELD(skip_validation);
726 WRITE_BOOL_FIELD(initially_valid);
727 break;
728diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
729index e3f9c62..5df939a 100644
730--- a/src/backend/parser/parse_utilcmd.c
731+++ b/src/backend/parser/parse_utilcmd.c
732@@ -1867,14 +1867,18 @@ transformFKConstraints(CreateStmtContext *cxt,
733 * a predicate expression. There are several code paths that create indexes
734 * without bothering to call this, because they know they don't have any
735 * such expressions to deal with.
736+ *
737+ * To avoid race conditions, it's important that this function rely only on
738+ * the passed-in relid (and not on stmt->relation) to determine the target
739+ * relation.
740 */
741 IndexStmt *
742-transformIndexStmt(IndexStmt *stmt, const char *queryString)
743+transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
744 {
745- Relation rel;
746 ParseState *pstate;
747 RangeTblEntry *rte;
748 ListCell *l;
749+ Relation rel;
750
751 /*
752 * We must not scribble on the passed-in IndexStmt, so copy it. (This is
753@@ -1882,26 +1886,17 @@ transformIndexStmt(IndexStmt *stmt, const char *queryString)
754 */
755 stmt = (IndexStmt *) copyObject(stmt);
756
757- /*
758- * Open the parent table with appropriate locking. We must do this
759- * because addRangeTableEntry() would acquire only AccessShareLock,
760- * leaving DefineIndex() needing to do a lock upgrade with consequent risk
761- * of deadlock. Make sure this stays in sync with the type of lock
762- * DefineIndex() wants. If we are being called by ALTER TABLE, we will
763- * already hold a higher lock.
764- */
765- rel = heap_openrv(stmt->relation,
766- (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock));
767-
768 /* Set up pstate */
769 pstate = make_parsestate(NULL);
770 pstate->p_sourcetext = queryString;
771
772 /*
773 * Put the parent table into the rtable so that the expressions can refer
774- * to its fields without qualification.
775+ * to its fields without qualification. Caller is responsible for locking
776+ * relation, but we still need to open it.
777 */
778- rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true);
779+ rel = relation_open(relid, NoLock);
780+ rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true);
781
782 /* no to join list, yes to namespaces */
783 addRTEtoQuery(pstate, rte, false, true, true);
784@@ -1955,7 +1950,7 @@ transformIndexStmt(IndexStmt *stmt, const char *queryString)
785
786 free_parsestate(pstate);
787
788- /* Close relation, but keep the lock */
789+ /* Close relation */
790 heap_close(rel, NoLock);
791
792 return stmt;
793@@ -2277,9 +2272,14 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
794 * Returns a List of utility commands to be done in sequence. One of these
795 * will be the transformed AlterTableStmt, but there may be additional actions
796 * to be done before and after the actual AlterTable() call.
797+ *
798+ * To avoid race conditions, it's important that this function rely only on
799+ * the passed-in relid (and not on stmt->relation) to determine the target
800+ * relation.
801 */
802 List *
803-transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
804+transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
805+ const char *queryString)
806 {
807 Relation rel;
808 ParseState *pstate;
809@@ -2291,7 +2291,6 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
810 List *newcmds = NIL;
811 bool skipValidation = true;
812 AlterTableCmd *newcmd;
813- LOCKMODE lockmode;
814
815 /*
816 * We must not scribble on the passed-in AlterTableStmt, so copy it. (This
817@@ -2299,29 +2298,8 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
818 */
819 stmt = (AlterTableStmt *) copyObject(stmt);
820
821- /*
822- * Determine the appropriate lock level for this list of subcommands.
823- */
824- lockmode = AlterTableGetLockLevel(stmt->cmds);
825-
826- /*
827- * Acquire appropriate lock on the target relation, which will be held
828- * until end of transaction. This ensures any decisions we make here
829- * based on the state of the relation will still be good at execution. We
830- * must get lock now because execution will later require it; taking a
831- * lower grade lock now and trying to upgrade later risks deadlock. Any
832- * new commands we add after this must not upgrade the lock level
833- * requested here.
834- */
835- rel = relation_openrv_extended(stmt->relation, lockmode, stmt->missing_ok);
836- if (rel == NULL)
837- {
838- /* this message is consistent with relation_openrv */
839- ereport(NOTICE,
840- (errmsg("relation \"%s\" does not exist, skipping",
841- stmt->relation->relname)));
842- return NIL;
843- }
844+ /* Caller is responsible for locking the relation */
845+ rel = relation_open(relid, NoLock);
846
847 /* Set up pstate and CreateStmtContext */
848 pstate = make_parsestate(NULL);
849@@ -2434,7 +2412,7 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
850 IndexStmt *idxstmt = (IndexStmt *) lfirst(l);
851
852 Assert(IsA(idxstmt, IndexStmt));
853- idxstmt = transformIndexStmt(idxstmt, queryString);
854+ idxstmt = transformIndexStmt(relid, idxstmt, queryString);
855 newcmd = makeNode(AlterTableCmd);
856 newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
857 newcmd->def = (Node *) idxstmt;
858@@ -2458,7 +2436,7 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
859 newcmds = lappend(newcmds, newcmd);
860 }
861
862- /* Close rel but keep lock */
863+ /* Close rel */
864 relation_close(rel, NoLock);
865
866 /*
867diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
868index 509bf4d..7903e03 100644
869--- a/src/backend/tcop/utility.c
870+++ b/src/backend/tcop/utility.c
871@@ -67,49 +67,6 @@ ProcessUtility_hook_type ProcessUtility_hook = NULL;
872
873
874 /*
875- * Verify user has ownership of specified relation, else ereport.
876- *
877- * If noCatalogs is true then we also deny access to system catalogs,
878- * except when allowSystemTableMods is true.
879- */
880-void
881-CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
882-{
883- Oid relOid;
884- HeapTuple tuple;
885-
886- /*
887- * XXX: This is unsafe in the presence of concurrent DDL, since it is
888- * called before acquiring any lock on the target relation. However,
889- * locking the target relation (especially using something like
890- * AccessExclusiveLock) before verifying that the user has permissions is
891- * not appealing either.
892- */
893- relOid = RangeVarGetRelid(rel, NoLock, false);
894-
895- tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
896- if (!HeapTupleIsValid(tuple)) /* should not happen */
897- elog(ERROR, "cache lookup failed for relation %u", relOid);
898-
899- if (!pg_class_ownercheck(relOid, GetUserId()))
900- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
901- rel->relname);
902-
903- if (noCatalogs)
904- {
905- if (!allowSystemTableMods &&
906- IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
907- ereport(ERROR,
908- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
909- errmsg("permission denied: \"%s\" is a system catalog",
910- rel->relname)));
911- }
912-
913- ReleaseSysCache(tuple);
914-}
915-
916-
917-/*
918 * CommandIsReadOnly: is an executable query read-only?
919 *
920 * This is a much stricter test than we apply for XactReadOnly mode;
921@@ -723,7 +680,8 @@ standard_ProcessUtility(Node *parsetree,
922 if (OidIsValid(relid))
923 {
924 /* Run parse analysis ... */
925- stmts = transformAlterTableStmt(atstmt, queryString);
926+ stmts = transformAlterTableStmt(relid, atstmt,
927+ queryString);
928
929 /* ... and do it */
930 foreach(l, stmts)
931@@ -910,18 +868,36 @@ standard_ProcessUtility(Node *parsetree,
932 case T_IndexStmt: /* CREATE INDEX */
933 {
934 IndexStmt *stmt = (IndexStmt *) parsetree;
935+ Oid relid;
936+ LOCKMODE lockmode;
937
938 if (stmt->concurrent)
939 PreventTransactionChain(isTopLevel,
940 "CREATE INDEX CONCURRENTLY");
941
942- CheckRelationOwnership(stmt->relation, true);
943+ /*
944+ * Look up the relation OID just once, right here at the
945+ * beginning, so that we don't end up repeating the name
946+ * lookup later and latching onto a different relation
947+ * partway through. To avoid lock upgrade hazards, it's
948+ * important that we take the strongest lock that will
949+ * eventually be needed here, so the lockmode calculation
950+ * needs to match what DefineIndex() does.
951+ */
952+ lockmode = stmt->concurrent ? ShareUpdateExclusiveLock
953+ : ShareLock;
954+ relid =
955+ RangeVarGetRelidExtended(stmt->relation, lockmode,
956+ false, false,
957+ RangeVarCallbackOwnsRelation,
958+ NULL);
959
960 /* Run parse analysis ... */
961- stmt = transformIndexStmt(stmt, queryString);
962+ stmt = transformIndexStmt(relid, stmt, queryString);
963
964 /* ... and do it */
965- DefineIndex(stmt,
966+ DefineIndex(relid, /* OID of heap relation */
967+ stmt,
968 InvalidOid, /* no predefined OID */
969 false, /* is_alter_table */
970 true, /* check_rights */
971@@ -1057,7 +1033,8 @@ standard_ProcessUtility(Node *parsetree,
972
973 case T_CreateTrigStmt:
974 (void) CreateTrigger((CreateTrigStmt *) parsetree, queryString,
975- InvalidOid, InvalidOid, false);
976+ InvalidOid, InvalidOid, InvalidOid,
977+ InvalidOid, false);
978 break;
979
980 case T_CreatePLangStmt:
981diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
982index d9d40b2..d8f8da4 100644
983--- a/src/include/catalog/pg_constraint.h
984+++ b/src/include/catalog/pg_constraint.h
985@@ -246,6 +246,7 @@ extern char *ChooseConstraintName(const char *name1, const char *name2,
986
987 extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
988 Oid newNspId, bool isType, ObjectAddresses *objsMoved);
989+extern void get_constraint_relation_oids(Oid constraint_oid, Oid *conrelid, Oid *confrelid);
990 extern Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok);
991 extern Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok);
992
993diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
994index 9b6d57a..a00fd37 100644
995--- a/src/include/commands/defrem.h
996+++ b/src/include/commands/defrem.h
997@@ -20,7 +20,8 @@
998 extern void RemoveObjects(DropStmt *stmt);
999
1000 /* commands/indexcmds.c */
1001-extern Oid DefineIndex(IndexStmt *stmt,
1002+extern Oid DefineIndex(Oid relationId,
1003+ IndexStmt *stmt,
1004 Oid indexRelationId,
1005 bool is_alter_table,
1006 bool check_rights,
1007@@ -35,7 +36,6 @@ extern char *makeObjectName(const char *name1, const char *name2,
1008 extern char *ChooseRelationName(const char *name1, const char *name2,
1009 const char *label, Oid namespaceid);
1010 extern bool CheckIndexCompatible(Oid oldId,
1011- RangeVar *heapRelation,
1012 char *accessMethodName,
1013 List *attributeList,
1014 List *exclusionOpNames);
1015diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
1016index 4f32062..d41f8a1 100644
1017--- a/src/include/commands/tablecmds.h
1018+++ b/src/include/commands/tablecmds.h
1019@@ -78,4 +78,6 @@ extern void AtEOSubXact_on_commit_actions(bool isCommit,
1020 extern void RangeVarCallbackOwnsTable(const RangeVar *relation,
1021 Oid relId, Oid oldRelId, void *arg);
1022
1023+extern void RangeVarCallbackOwnsRelation(const RangeVar *relation,
1024+ Oid relId, Oid oldRelId, void *noCatalogs);
1025 #endif /* TABLECMDS_H */
1026diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
1027index 9303341..0869c0b 100644
1028--- a/src/include/commands/trigger.h
1029+++ b/src/include/commands/trigger.h
1030@@ -109,7 +109,7 @@ extern PGDLLIMPORT int SessionReplicationRole;
1031 #define TRIGGER_DISABLED 'D'
1032
1033 extern Oid CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
1034- Oid constraintOid, Oid indexOid,
1035+ Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
1036 bool isInternal);
1037
1038 extern void RemoveTriggerById(Oid trigOid);
1039diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
1040index 327f7cf..31f5479 100644
1041--- a/src/include/nodes/parsenodes.h
1042+++ b/src/include/nodes/parsenodes.h
1043@@ -1566,6 +1566,8 @@ typedef struct Constraint
1044 /* Fields used for constraints that allow a NOT VALID specification */
1045 bool skip_validation; /* skip validation of existing rows? */
1046 bool initially_valid; /* mark the new constraint as valid? */
1047+
1048+ Oid old_pktable_oid; /* pg_constraint.confrelid of my former self */
1049 } Constraint;
1050
1051 /* ----------------------
1052diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h
1053index 4ad793a..d8b340e 100644
1054--- a/src/include/parser/parse_utilcmd.h
1055+++ b/src/include/parser/parse_utilcmd.h
1056@@ -18,9 +18,10 @@
1057
1058
1059 extern List *transformCreateStmt(CreateStmt *stmt, const char *queryString);
1060-extern List *transformAlterTableStmt(AlterTableStmt *stmt,
1061+extern List *transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
1062 const char *queryString);
1063-extern IndexStmt *transformIndexStmt(IndexStmt *stmt, const char *queryString);
1064+extern IndexStmt *transformIndexStmt(Oid relid, IndexStmt *stmt,
1065+ const char *queryString);
1066 extern void transformRuleStmt(RuleStmt *stmt, const char *queryString,
1067 List **actions, Node **whereClause);
1068 extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt);
1069diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
1070index 54190b2..ae871ca 100644
1071--- a/src/include/tcop/utility.h
1072+++ b/src/include/tcop/utility.h
1073@@ -42,6 +42,4 @@ extern LogStmtLevel GetCommandLogLevel(Node *parsetree);
1074
1075 extern bool CommandIsReadOnly(Node *parsetree);
1076
1077-extern void CheckRelationOwnership(RangeVar *rel, bool noCatalogs);
1078-
1079 #endif /* UTILITY_H */
1080--
10811.7.5.4
1082
diff --git a/meta-oe/recipes-support/postgresql/files/0006-Fix-handling-of-wide-datetime-input-output.patch b/meta-oe/recipes-support/postgresql/files/0006-Fix-handling-of-wide-datetime-input-output.patch
new file mode 100644
index 000000000..fac0a7347
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0006-Fix-handling-of-wide-datetime-input-output.patch
@@ -0,0 +1,465 @@
1From f416622be81d1320417bbc7892fd562cae0dba72 Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Mon, 17 Feb 2014 09:33:31 -0500
4Subject: [PATCH] Fix handling of wide datetime input/output.
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9commit f416622be81d1320417bbc7892fd562cae0dba72 REL9_2_STABLE
10
11Many server functions use the MAXDATELEN constant to size a buffer for
12parsing or displaying a datetime value. It was much too small for the
13longest possible interval output and slightly too small for certain
14valid timestamp input, particularly input with a long timezone name.
15The long input was rejected needlessly; the long output caused
16interval_out() to overrun its buffer. ECPG's pgtypes library has a copy
17of the vulnerable functions, which bore the same vulnerabilities along
18with some of its own. In contrast to the server, certain long inputs
19caused stack overflow rather than failing cleanly. Back-patch to 8.4
20(all supported versions).
21
22Reported by Daniel Schüssler, reviewed by Tom Lane.
23
24Security: CVE-2014-0063
25
26
27Upstream-Status: Backport
28
29Signed-off-by: Kai Kang <kai.kang@windriver.com>
30---
31 src/include/utils/datetime.h | 17 +++++---
32 src/interfaces/ecpg/pgtypeslib/datetime.c | 4 +-
33 src/interfaces/ecpg/pgtypeslib/dt.h | 17 +++++---
34 src/interfaces/ecpg/pgtypeslib/dt_common.c | 44 ++++++++++++++------
35 src/interfaces/ecpg/pgtypeslib/interval.c | 2 +-
36 src/interfaces/ecpg/pgtypeslib/timestamp.c | 2 +-
37 .../ecpg/test/expected/pgtypeslib-dt_test2.c | 22 +++++++---
38 .../ecpg/test/expected/pgtypeslib-dt_test2.stdout | 19 ++++++++
39 src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc | 10 ++++
40 src/test/regress/expected/interval.out | 7 +++
41 src/test/regress/sql/interval.sql | 2 +
42 11 files changed, 111 insertions(+), 35 deletions(-)
43
44diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
45index d73cc8d..4b805b6 100644
46--- a/src/include/utils/datetime.h
47+++ b/src/include/utils/datetime.h
48@@ -188,12 +188,17 @@ struct tzEntry;
49 #define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
50 #define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_ALL_SECS_M)
51
52-#define MAXDATELEN 63 /* maximum possible length of an input date
53- * string (not counting tr. null) */
54-#define MAXDATEFIELDS 25 /* maximum possible number of fields in a date
55- * string */
56-#define TOKMAXLEN 10 /* only this many chars are stored in
57- * datetktbl */
58+/*
59+ * Working buffer size for input and output of interval, timestamp, etc.
60+ * Inputs that need more working space will be rejected early. Longer outputs
61+ * will overrun buffers, so this must suffice for all possible output. As of
62+ * this writing, interval_out() needs the most space at ~90 bytes.
63+ */
64+#define MAXDATELEN 128
65+/* maximum possible number of fields in a date string */
66+#define MAXDATEFIELDS 25
67+/* only this many chars are stored in datetktbl */
68+#define TOKMAXLEN 10
69
70 /* keep this struct small; it gets used a lot */
71 typedef struct
72diff --git a/src/interfaces/ecpg/pgtypeslib/datetime.c b/src/interfaces/ecpg/pgtypeslib/datetime.c
73index 823626f..4adcd1e 100644
74--- a/src/interfaces/ecpg/pgtypeslib/datetime.c
75+++ b/src/interfaces/ecpg/pgtypeslib/datetime.c
76@@ -61,14 +61,14 @@ PGTYPESdate_from_asc(char *str, char **endptr)
77 int nf;
78 char *field[MAXDATEFIELDS];
79 int ftype[MAXDATEFIELDS];
80- char lowstr[MAXDATELEN + 1];
81+ char lowstr[MAXDATELEN + MAXDATEFIELDS];
82 char *realptr;
83 char **ptr = (endptr != NULL) ? endptr : &realptr;
84
85 bool EuroDates = FALSE;
86
87 errno = 0;
88- if (strlen(str) >= sizeof(lowstr))
89+ if (strlen(str) > MAXDATELEN)
90 {
91 errno = PGTYPES_DATE_BAD_DATE;
92 return INT_MIN;
93diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h
94index dfe6f9e..2780593 100644
95--- a/src/interfaces/ecpg/pgtypeslib/dt.h
96+++ b/src/interfaces/ecpg/pgtypeslib/dt.h
97@@ -192,12 +192,17 @@ typedef double fsec_t;
98 #define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
99 #define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
100
101-#define MAXDATELEN 63 /* maximum possible length of an input date
102- * string (not counting tr. null) */
103-#define MAXDATEFIELDS 25 /* maximum possible number of fields in a date
104- * string */
105-#define TOKMAXLEN 10 /* only this many chars are stored in
106- * datetktbl */
107+/*
108+ * Working buffer size for input and output of interval, timestamp, etc.
109+ * Inputs that need more working space will be rejected early. Longer outputs
110+ * will overrun buffers, so this must suffice for all possible output. As of
111+ * this writing, PGTYPESinterval_to_asc() needs the most space at ~90 bytes.
112+ */
113+#define MAXDATELEN 128
114+/* maximum possible number of fields in a date string */
115+#define MAXDATEFIELDS 25
116+/* only this many chars are stored in datetktbl */
117+#define TOKMAXLEN 10
118
119 /* keep this struct small; it gets used a lot */
120 typedef struct
121diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c
122index 6b89e4a..18178dd 100644
123--- a/src/interfaces/ecpg/pgtypeslib/dt_common.c
124+++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c
125@@ -1171,15 +1171,22 @@ DecodeNumberField(int len, char *str, int fmask,
126 if ((cp = strchr(str, '.')) != NULL)
127 {
128 #ifdef HAVE_INT64_TIMESTAMP
129- char fstr[MAXDATELEN + 1];
130+ char fstr[7];
131+ int i;
132+
133+ cp++;
134
135 /*
136 * OK, we have at most six digits to care about. Let's construct a
137- * string and then do the conversion to an integer.
138+ * string with those digits, zero-padded on the right, and then do
139+ * the conversion to an integer.
140+ *
141+ * XXX This truncates the seventh digit, unlike rounding it as do
142+ * the backend and the !HAVE_INT64_TIMESTAMP case.
143 */
144- strcpy(fstr, (cp + 1));
145- strcpy(fstr + strlen(fstr), "000000");
146- *(fstr + 6) = '\0';
147+ for (i = 0; i < 6; i++)
148+ fstr[i] = *cp != '\0' ? *cp++ : '0';
149+ fstr[i] = '\0';
150 *fsec = strtol(fstr, NULL, 10);
151 #else
152 *fsec = strtod(cp, NULL);
153@@ -1531,15 +1538,22 @@ DecodeTime(char *str, int *tmask, struct tm * tm, fsec_t *fsec)
154 else if (*cp == '.')
155 {
156 #ifdef HAVE_INT64_TIMESTAMP
157- char fstr[MAXDATELEN + 1];
158+ char fstr[7];
159+ int i;
160+
161+ cp++;
162
163 /*
164- * OK, we have at most six digits to work with. Let's construct a
165- * string and then do the conversion to an integer.
166+ * OK, we have at most six digits to care about. Let's construct a
167+ * string with those digits, zero-padded on the right, and then do
168+ * the conversion to an integer.
169+ *
170+ * XXX This truncates the seventh digit, unlike rounding it as do
171+ * the backend and the !HAVE_INT64_TIMESTAMP case.
172 */
173- strncpy(fstr, (cp + 1), 7);
174- strcpy(fstr + strlen(fstr), "000000");
175- *(fstr + 6) = '\0';
176+ for (i = 0; i < 6; i++)
177+ fstr[i] = *cp != '\0' ? *cp++ : '0';
178+ fstr[i] = '\0';
179 *fsec = strtol(fstr, &cp, 10);
180 #else
181 str = cp;
182@@ -1665,6 +1679,9 @@ DecodePosixTimezone(char *str, int *tzp)
183 * DTK_NUMBER can hold date fields (yy.ddd)
184 * DTK_STRING can hold months (January) and time zones (PST)
185 * DTK_DATE can hold Posix time zones (GMT-8)
186+ *
187+ * The "lowstr" work buffer must have at least strlen(timestr) + MAXDATEFIELDS
188+ * bytes of space. On output, field[] entries will point into it.
189 */
190 int
191 ParseDateTime(char *timestr, char *lowstr,
192@@ -1677,7 +1694,10 @@ ParseDateTime(char *timestr, char *lowstr,
193 /* outer loop through fields */
194 while (*(*endstr) != '\0')
195 {
196+ /* Record start of current field */
197 field[nf] = lp;
198+ if (nf >= MAXDATEFIELDS)
199+ return -1;
200
201 /* leading digit? then date or time */
202 if (isdigit((unsigned char) *(*endstr)))
203@@ -1818,8 +1838,6 @@ ParseDateTime(char *timestr, char *lowstr,
204 /* force in a delimiter after each field */
205 *lp++ = '\0';
206 nf++;
207- if (nf > MAXDATEFIELDS)
208- return -1;
209 }
210
211 *numfields = nf;
212diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c
213index bcc10ee..fdd8f49 100644
214--- a/src/interfaces/ecpg/pgtypeslib/interval.c
215+++ b/src/interfaces/ecpg/pgtypeslib/interval.c
216@@ -1092,7 +1092,7 @@ PGTYPESinterval_from_asc(char *str, char **endptr)
217 tm->tm_sec = 0;
218 fsec = 0;
219
220- if (strlen(str) >= sizeof(lowstr))
221+ if (strlen(str) > MAXDATELEN)
222 {
223 errno = PGTYPES_INTVL_BAD_INTERVAL;
224 return NULL;
225diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c
226index 7d3f7c8..4f91e63 100644
227--- a/src/interfaces/ecpg/pgtypeslib/timestamp.c
228+++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c
229@@ -297,7 +297,7 @@ PGTYPEStimestamp_from_asc(char *str, char **endptr)
230 char *realptr;
231 char **ptr = (endptr != NULL) ? endptr : &realptr;
232
233- if (strlen(str) >= sizeof(lowstr))
234+ if (strlen(str) > MAXDATELEN)
235 {
236 errno = PGTYPES_TS_BAD_TIMESTAMP;
237 return (noresult);
238diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c
239index d3ebb0e..0ba1936 100644
240--- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c
241+++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c
242@@ -45,6 +45,15 @@ char *dates[] = { "19990108foobar",
243 "1999.008",
244 "J2451187",
245 "January 8, 99 BC",
246+ /*
247+ * Maximize space usage in ParseDateTime() with 25
248+ * (MAXDATEFIELDS) fields and 128 (MAXDATELEN) total length.
249+ */
250+ "........................Xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
251+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
252+ /* 26 fields */
253+ ".........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
254+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
255 NULL };
256
257 /* do not conflict with libc "times" symbol */
258@@ -52,6 +61,7 @@ static char *times[] = { "0:04",
259 "1:59 PDT",
260 "13:24:40 -8:00",
261 "13:24:40.495+3",
262+ "13:24:40.123456789+3",
263 NULL };
264
265 char *intervals[] = { "1 minute",
266@@ -73,22 +83,22 @@ main(void)
267
268
269
270-#line 52 "dt_test2.pgc"
271+#line 62 "dt_test2.pgc"
272 date date1 ;
273
274-#line 53 "dt_test2.pgc"
275+#line 63 "dt_test2.pgc"
276 timestamp ts1 , ts2 ;
277
278-#line 54 "dt_test2.pgc"
279+#line 64 "dt_test2.pgc"
280 char * text ;
281
282-#line 55 "dt_test2.pgc"
283+#line 65 "dt_test2.pgc"
284 interval * i1 ;
285
286-#line 56 "dt_test2.pgc"
287+#line 66 "dt_test2.pgc"
288 date * dc ;
289 /* exec sql end declare section */
290-#line 57 "dt_test2.pgc"
291+#line 67 "dt_test2.pgc"
292
293
294 int i, j;
295diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.stdout b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.stdout
296index 24e9d26..9a4587b 100644
297--- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.stdout
298+++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.stdout
299@@ -8,85 +8,104 @@ TS[3,0]: 1999-01-08 00:04:00
300 TS[3,1]: 1999-01-08 01:59:00
301 TS[3,2]: 1999-01-08 13:24:40
302 TS[3,3]: 1999-01-08 13:24:40.495
303+TS[3,4]: 1999-01-08 13:24:40.123456
304 Date[4]: 1999-01-08 (N - F)
305 TS[4,0]: 1999-01-08 00:04:00
306 TS[4,1]: 1999-01-08 01:59:00
307 TS[4,2]: 1999-01-08 13:24:40
308 TS[4,3]: 1999-01-08 13:24:40.495
309+TS[4,4]: 1999-01-08 13:24:40.123456
310 Date[5]: 1999-01-08 (N - F)
311 TS[5,0]: 1999-01-08 00:04:00
312 TS[5,1]: 1999-01-08 01:59:00
313 TS[5,2]: 1999-01-08 13:24:40
314 TS[5,3]: 1999-01-08 13:24:40.495
315+TS[5,4]: 1999-01-08 13:24:40.123456
316 Date[6]: 1999-01-18 (N - F)
317 TS[6,0]: 1999-01-18 00:04:00
318 TS[6,1]: 1999-01-18 01:59:00
319 TS[6,2]: 1999-01-18 13:24:40
320 TS[6,3]: 1999-01-18 13:24:40.495
321+TS[6,4]: 1999-01-18 13:24:40.123456
322 Date[7]: 2003-01-02 (N - F)
323 TS[7,0]: 2003-01-02 00:04:00
324 TS[7,1]: 2003-01-02 01:59:00
325 TS[7,2]: 2003-01-02 13:24:40
326 TS[7,3]: 2003-01-02 13:24:40.495
327+TS[7,4]: 2003-01-02 13:24:40.123456
328 Date[8]: 1999-01-08 (N - F)
329 TS[8,0]: 1999-01-08 00:04:00
330 TS[8,1]: 1999-01-08 01:59:00
331 TS[8,2]: 1999-01-08 13:24:40
332 TS[8,3]: 1999-01-08 13:24:40.495
333+TS[8,4]: 1999-01-08 13:24:40.123456
334 Date[9]: 1999-01-08 (N - F)
335 TS[9,0]: 1999-01-08 00:04:00
336 TS[9,1]: 1999-01-08 01:59:00
337 TS[9,2]: 1999-01-08 13:24:40
338 TS[9,3]: 1999-01-08 13:24:40.495
339+TS[9,4]: 1999-01-08 13:24:40.123456
340 Date[10]: 1999-01-08 (N - F)
341 TS[10,0]: 1999-01-08 00:04:00
342 TS[10,1]: 1999-01-08 01:59:00
343 TS[10,2]: 1999-01-08 13:24:40
344 TS[10,3]: 1999-01-08 13:24:40.495
345+TS[10,4]: 1999-01-08 13:24:40.123456
346 Date[11]: 1999-01-08 (N - F)
347 TS[11,0]: 1999-01-08 00:04:00
348 TS[11,1]: 1999-01-08 01:59:00
349 TS[11,2]: 1999-01-08 13:24:40
350 TS[11,3]: 1999-01-08 13:24:40.495
351+TS[11,4]: 1999-01-08 13:24:40.123456
352 Date[12]: 1999-01-08 (N - F)
353 TS[12,0]: 1999-01-08 00:04:00
354 TS[12,1]: 1999-01-08 01:59:00
355 TS[12,2]: 1999-01-08 13:24:40
356 TS[12,3]: 1999-01-08 13:24:40.495
357+TS[12,4]: 1999-01-08 13:24:40.123456
358 Date[13]: 2006-01-08 (N - F)
359 TS[13,0]: 2006-01-08 00:04:00
360 TS[13,1]: 2006-01-08 01:59:00
361 TS[13,2]: 2006-01-08 13:24:40
362 TS[13,3]: 2006-01-08 13:24:40.495
363+TS[13,4]: 2006-01-08 13:24:40.123456
364 Date[14]: 1999-01-08 (N - F)
365 TS[14,0]: 1999-01-08 00:04:00
366 TS[14,1]: 1999-01-08 01:59:00
367 TS[14,2]: 1999-01-08 13:24:40
368 TS[14,3]: 1999-01-08 13:24:40.495
369+TS[14,4]: 1999-01-08 13:24:40.123456
370 Date[15]: 1999-01-08 (N - F)
371 TS[15,0]: 1999-01-08 00:04:00
372 TS[15,1]: 1999-01-08 01:59:00
373 TS[15,2]: 1999-01-08 13:24:40
374 TS[15,3]: 1999-01-08 13:24:40.495
375+TS[15,4]: 1999-01-08 13:24:40.123456
376 Date[16]: 1999-01-08 (N - F)
377 TS[16,0]: 1999-01-08 00:04:00
378 TS[16,1]: 1999-01-08 01:59:00
379 TS[16,2]: 1999-01-08 13:24:40
380 TS[16,3]: 1999-01-08 13:24:40.495
381+TS[16,4]: 1999-01-08 13:24:40.123456
382 Date[17]: 1999-01-08 (N - F)
383 TS[17,0]: 1999-01-08 00:04:00
384 TS[17,1]: 1999-01-08 01:59:00
385 TS[17,2]: 1999-01-08 13:24:40
386 TS[17,3]: 1999-01-08 13:24:40.495
387+TS[17,4]: 1999-01-08 13:24:40.123456
388 Date[18]: 1999-01-08 (N - F)
389 TS[18,0]: 1999-01-08 00:04:00
390 TS[18,1]: 1999-01-08 01:59:00
391 TS[18,2]: 1999-01-08 13:24:40
392 TS[18,3]: 1999-01-08 13:24:40.495
393+TS[18,4]: 1999-01-08 13:24:40.123456
394 Date[19]: 0099-01-08 BC (N - F)
395 TS[19,0]: 0099-01-08 00:04:00 BC
396 TS[19,1]: 0099-01-08 01:59:00 BC
397 TS[19,2]: 0099-01-08 13:24:40 BC
398+TS[19,4]: 0099-01-08 13:24:40.123456 BC
399+Date[20]: - (N - T)
400+Date[21]: - (N - T)
401 interval[0]: @ 1 min
402 interval_copy[0]: @ 1 min
403 interval[1]: @ 1 day 12 hours 59 mins 10 secs
404diff --git a/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc b/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc
405index 0edf012..a127dd9 100644
406--- a/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc
407+++ b/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc
408@@ -27,6 +27,15 @@ char *dates[] = { "19990108foobar",
409 "1999.008",
410 "J2451187",
411 "January 8, 99 BC",
412+ /*
413+ * Maximize space usage in ParseDateTime() with 25
414+ * (MAXDATEFIELDS) fields and 128 (MAXDATELEN) total length.
415+ */
416+ "........................Xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
417+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
418+ /* 26 fields */
419+ ".........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
420+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
421 NULL };
422
423 /* do not conflict with libc "times" symbol */
424@@ -34,6 +43,7 @@ static char *times[] = { "0:04",
425 "1:59 PDT",
426 "13:24:40 -8:00",
427 "13:24:40.495+3",
428+ "13:24:40.123456789+3",
429 NULL };
430
431 char *intervals[] = { "1 minute",
432diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
433index 3bf2211..99fd0ca 100644
434--- a/src/test/regress/expected/interval.out
435+++ b/src/test/regress/expected/interval.out
436@@ -306,6 +306,13 @@ select '4 millenniums 5 centuries 4 decades 1 year 4 months 4 days 17 minutes 31
437 @ 4541 years 4 mons 4 days 17 mins 31 secs
438 (1 row)
439
440+-- test long interval output
441+select '100000000y 10mon -1000000000d -1000000000h -10min -10.000001s ago'::interval;
442+ interval
443+-------------------------------------------------------------------------------------------
444+ @ 100000000 years 10 mons -1000000000 days -1000000000 hours -10 mins -10.000001 secs ago
445+(1 row)
446+
447 -- test justify_hours() and justify_days()
448 SELECT justify_hours(interval '6 months 3 days 52 hours 3 minutes 2 seconds') as "6 mons 5 days 4 hours 3 mins 2 seconds";
449 6 mons 5 days 4 hours 3 mins 2 seconds
450diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql
451index f1da4c2..7cee286 100644
452--- a/src/test/regress/sql/interval.sql
453+++ b/src/test/regress/sql/interval.sql
454@@ -108,6 +108,8 @@ select avg(f1) from interval_tbl;
455 -- test long interval input
456 select '4 millenniums 5 centuries 4 decades 1 year 4 months 4 days 17 minutes 31 seconds'::interval;
457
458+-- test long interval output
459+select '100000000y 10mon -1000000000d -1000000000h -10min -10.000001s ago'::interval;
460
461 -- test justify_hours() and justify_days()
462
463--
4641.7.5.4
465
diff --git a/meta-oe/recipes-support/postgresql/files/0007-Make-pqsignal-available-to-pg_regress-of-ECPG-and-is.patch b/meta-oe/recipes-support/postgresql/files/0007-Make-pqsignal-available-to-pg_regress-of-ECPG-and-is.patch
new file mode 100644
index 000000000..3cffc0a85
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0007-Make-pqsignal-available-to-pg_regress-of-ECPG-and-is.patch
@@ -0,0 +1,75 @@
1From 0ae841a98c21c53901d5bc9a9323a8cc800364f6 Mon Sep 17 00:00:00 2001
2From: Noah Misch <noah@leadboat.com>
3Date: Sat, 14 Jun 2014 10:52:25 -0400
4Subject: [PATCH] Make pqsignal() available to pg_regress of ECPG and
5 isolation suites.
6
7commit 0ae841a98c21c53901d5bc9a9323a8cc800364f6 REL9_2_STABLE
8
9Commit 453a5d91d49e4d35054f92785d830df4067e10c1 made it available to the
10src/test/regress build of pg_regress, but all pg_regress builds need the
11same treatment. Patch 9.2 through 8.4; in 9.3 and later, pg_regress
12gets pqsignal() via libpgport.
13
14
15Upstream-Status: Backport
16
17Signed-off-by: Kai Kang <kai.kang@windriver.com>
18---
19 src/interfaces/ecpg/test/Makefile | 4 ++--
20 src/test/isolation/Makefile | 12 +++++++-----
21 2 files changed, 9 insertions(+), 7 deletions(-)
22
23diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
24index e9944c6..4bb9525 100644
25--- a/src/interfaces/ecpg/test/Makefile
26+++ b/src/interfaces/ecpg/test/Makefile
27@@ -47,10 +47,10 @@ clean distclean maintainer-clean:
28
29 all: pg_regress$(X)
30
31-pg_regress$(X): pg_regress_ecpg.o $(top_builddir)/src/test/regress/pg_regress.o
32+pg_regress$(X): pg_regress_ecpg.o $(top_builddir)/src/test/regress/pg_regress.o $(top_builddir)/src/test/regress/pqsignal.o
33 $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_EX) $^ $(LIBS) -o $@
34
35-$(top_builddir)/src/test/regress/pg_regress.o:
36+$(top_builddir)/src/test/regress/pg_regress.o $(top_builddir)/src/test/regress/pqsignal.o:
37 $(MAKE) -C $(dir $@) $(notdir $@)
38
39 # dependencies ensure that path changes propagate
40diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile
41index 46ea6f0..e20ba48 100644
42--- a/src/test/isolation/Makefile
43+++ b/src/test/isolation/Makefile
44@@ -15,13 +15,15 @@ OBJS = specparse.o isolationtester.o
45
46 all: isolationtester$(X) pg_isolation_regress$(X)
47
48-submake-regress:
49+pg_regress.o:
50 $(MAKE) -C $(top_builddir)/src/test/regress pg_regress.o
51-
52-pg_regress.o: | submake-regress
53 rm -f $@ && $(LN_S) $(top_builddir)/src/test/regress/pg_regress.o .
54
55-pg_isolation_regress$(X): isolation_main.o pg_regress.o
56+pqsignal.o:
57+ $(MAKE) -C $(top_builddir)/src/test/regress pqsignal.o
58+ rm -f $@ && $(LN_S) $(top_builddir)/src/test/regress/pqsignal.o .
59+
60+pg_isolation_regress$(X): isolation_main.o pg_regress.o pqsignal.o
61 $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@
62
63 isolationtester$(X): $(OBJS) | submake-libpq submake-libpgport
64@@ -59,7 +61,7 @@ endif
65 # so do not clean them here
66 clean distclean:
67 rm -f isolationtester$(X) pg_isolation_regress$(X) $(OBJS) isolation_main.o
68- rm -f pg_regress.o
69+ rm -f pg_regress.o pqsignal.o
70 rm -rf $(pg_regress_clean_files)
71
72 maintainer-clean: distclean
73--
741.7.5.4
75
diff --git a/meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch b/meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch
new file mode 100644
index 000000000..62ec9354d
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch
@@ -0,0 +1,393 @@
1From 655b665f745e2e07cf6936c6063b0250f5caa98f Mon Sep 17 00:00:00 2001
2From: Tom Lane <tgl@sss.pgh.pa.us>
3Date: Mon, 17 Feb 2014 11:20:27 -0500
4Subject: [PATCH] Prevent potential overruns of fixed-size buffers.
5
6commit 655b665f745e2e07cf6936c6063b0250f5caa98f REL9_2_STABLE
7
8Coverity identified a number of places in which it couldn't prove that a
9string being copied into a fixed-size buffer would fit. We believe that
10most, perhaps all of these are in fact safe, or are copying data that is
11coming from a trusted source so that any overrun is not really a security
12issue. Nonetheless it seems prudent to forestall any risk by using
13strlcpy() and similar functions.
14
15Fixes by Peter Eisentraut and Jozef Mlich based on Coverity reports.
16
17In addition, fix a potential null-pointer-dereference crash in
18contrib/chkpass. The crypt(3) function is defined to return NULL on
19failure, but chkpass.c didn't check for that before using the result.
20The main practical case in which this could be an issue is if libc is
21configured to refuse to execute unapproved hashing algorithms (e.g.,
22"FIPS mode"). This ideally should've been a separate commit, but
23since it touches code adjacent to one of the buffer overrun changes,
24I included it in this commit to avoid last-minute merge issues.
25This issue was reported by Honza Horak.
26
27Security: CVE-2014-0065 for buffer overruns, CVE-2014-0066 for crypt()
28
29Upsteam-Status: Backport
30
31Signed-off-by: Kai Kang <kai.kang@windriver.com>
32---
33 contrib/chkpass/chkpass.c | 29 ++++++++++++++++++++++++++---
34 contrib/pg_standby/pg_standby.c | 2 +-
35 src/backend/access/transam/xlog.c | 10 +++++-----
36 src/backend/tsearch/spell.c | 2 +-
37 src/backend/utils/adt/datetime.c | 11 ++++++-----
38 src/bin/initdb/findtimezone.c | 4 ++--
39 src/bin/pg_basebackup/pg_basebackup.c | 8 ++++----
40 src/interfaces/ecpg/preproc/pgc.l | 2 +-
41 src/interfaces/libpq/fe-protocol2.c | 2 +-
42 src/interfaces/libpq/fe-protocol3.c | 2 +-
43 src/port/exec.c | 4 ++--
44 src/test/regress/pg_regress.c | 6 +++---
45 src/timezone/pgtz.c | 2 +-
46 13 files changed, 54 insertions(+), 30 deletions(-)
47
48diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c
49index 0c9fec0..1795b8c 100644
50--- a/contrib/chkpass/chkpass.c
51+++ b/contrib/chkpass/chkpass.c
52@@ -70,6 +70,7 @@ chkpass_in(PG_FUNCTION_ARGS)
53 char *str = PG_GETARG_CSTRING(0);
54 chkpass *result;
55 char mysalt[4];
56+ char *crypt_output;
57 static char salt_chars[] =
58 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
59
60@@ -92,7 +93,15 @@ chkpass_in(PG_FUNCTION_ARGS)
61 mysalt[1] = salt_chars[random() & 0x3f];
62 mysalt[2] = 0; /* technically the terminator is not necessary
63 * but I like to play safe */
64- strcpy(result->password, crypt(str, mysalt));
65+
66+ crypt_output = crypt(str, mysalt);
67+ if (crypt_output == NULL)
68+ ereport(ERROR,
69+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
70+ errmsg("crypt() failed")));
71+
72+ strlcpy(result->password, crypt_output, sizeof(result->password));
73+
74 PG_RETURN_POINTER(result);
75 }
76
77@@ -141,9 +150,16 @@ chkpass_eq(PG_FUNCTION_ARGS)
78 chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0);
79 text *a2 = PG_GETARG_TEXT_PP(1);
80 char str[9];
81+ char *crypt_output;
82
83 text_to_cstring_buffer(a2, str, sizeof(str));
84- PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) == 0);
85+ crypt_output = crypt(str, a1->password);
86+ if (crypt_output == NULL)
87+ ereport(ERROR,
88+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
89+ errmsg("crypt() failed")));
90+
91+ PG_RETURN_BOOL(strcmp(a1->password, crypt_output) == 0);
92 }
93
94 PG_FUNCTION_INFO_V1(chkpass_ne);
95@@ -153,7 +169,14 @@ chkpass_ne(PG_FUNCTION_ARGS)
96 chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0);
97 text *a2 = PG_GETARG_TEXT_PP(1);
98 char str[9];
99+ char *crypt_output;
100
101 text_to_cstring_buffer(a2, str, sizeof(str));
102- PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) != 0);
103+ crypt_output = crypt(str, a1->password);
104+ if (crypt_output == NULL)
105+ ereport(ERROR,
106+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
107+ errmsg("crypt() failed")));
108+
109+ PG_RETURN_BOOL(strcmp(a1->password, crypt_output) != 0);
110 }
111diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
112index 84941ed..0f1e0c1 100644
113--- a/contrib/pg_standby/pg_standby.c
114+++ b/contrib/pg_standby/pg_standby.c
115@@ -338,7 +338,7 @@ SetWALFileNameForCleanup(void)
116 if (strcmp(restartWALFileName, nextWALFileName) > 0)
117 return false;
118
119- strcpy(exclusiveCleanupFileName, restartWALFileName);
120+ strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
121 return true;
122 }
123
124diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
125index d639c4a..49bb453 100644
126--- a/src/backend/access/transam/xlog.c
127+++ b/src/backend/access/transam/xlog.c
128@@ -3017,7 +3017,7 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
129 xlogfpath, oldpath)));
130 }
131 #else
132- strncpy(oldpath, xlogfpath, MAXPGPATH);
133+ strlcpy(oldpath, xlogfpath, MAXPGPATH);
134 #endif
135 if (unlink(oldpath) != 0)
136 ereport(FATAL,
137@@ -5913,7 +5913,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
138
139 recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
140 recordXtime = recordRestorePointData->rp_time;
141- strncpy(recordRPName, recordRestorePointData->rp_name, MAXFNAMELEN);
142+ strlcpy(recordRPName, recordRestorePointData->rp_name, MAXFNAMELEN);
143 }
144 else
145 return false;
146@@ -6008,7 +6008,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
147 }
148 else
149 {
150- strncpy(recoveryStopName, recordRPName, MAXFNAMELEN);
151+ strlcpy(recoveryStopName, recordRPName, MAXFNAMELEN);
152
153 ereport(LOG,
154 (errmsg("recovery stopping at restore point \"%s\", time %s",
155@@ -6348,7 +6348,7 @@ StartupXLOG(void)
156 * see them
157 */
158 XLogCtl->RecoveryTargetTLI = recoveryTargetTLI;
159- strncpy(XLogCtl->archiveCleanupCommand,
160+ strlcpy(XLogCtl->archiveCleanupCommand,
161 archiveCleanupCommand ? archiveCleanupCommand : "",
162 sizeof(XLogCtl->archiveCleanupCommand));
163
164@@ -8760,7 +8760,7 @@ XLogRestorePoint(const char *rpName)
165 xl_restore_point xlrec;
166
167 xlrec.rp_time = GetCurrentTimestamp();
168- strncpy(xlrec.rp_name, rpName, MAXFNAMELEN);
169+ strlcpy(xlrec.rp_name, rpName, MAXFNAMELEN);
170
171 rdata.buffer = InvalidBuffer;
172 rdata.data = (char *) &xlrec;
173diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
174index 449aa6a..4acc33e 100644
175--- a/src/backend/tsearch/spell.c
176+++ b/src/backend/tsearch/spell.c
177@@ -255,7 +255,7 @@ NIAddSpell(IspellDict *Conf, const char *word, const char *flag)
178 }
179 Conf->Spell[Conf->nspell] = (SPELL *) tmpalloc(SPELLHDRSZ + strlen(word) + 1);
180 strcpy(Conf->Spell[Conf->nspell]->word, word);
181- strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN);
182+ strlcpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN);
183 Conf->nspell++;
184 }
185
186diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
187index 4763a6f..4105f17 100644
188--- a/src/backend/utils/adt/datetime.c
189+++ b/src/backend/utils/adt/datetime.c
190@@ -90,10 +90,10 @@ char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
191 * Note that this table must be strictly alphabetically ordered to allow an
192 * O(ln(N)) search algorithm to be used.
193 *
194- * The text field is NOT guaranteed to be NULL-terminated.
195+ * The token field is NOT guaranteed to be NULL-terminated.
196 *
197- * To keep this table reasonably small, we divide the lexval for TZ and DTZ
198- * entries by 15 (so they are on 15 minute boundaries) and truncate the text
199+ * To keep this table reasonably small, we divide the value for TZ and DTZ
200+ * entries by 15 (so they are on 15 minute boundaries) and truncate the token
201 * field at TOKMAXLEN characters.
202 * Formerly, we divided by 10 rather than 15 but there are a few time zones
203 * which are 30 or 45 minutes away from an even hour, most are on an hour
204@@ -108,7 +108,7 @@ static datetkn *timezonetktbl = NULL;
205 static int sztimezonetktbl = 0;
206
207 static const datetkn datetktbl[] = {
208-/* text, token, lexval */
209+ /* token, type, value */
210 {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
211 {DA_D, ADBC, AD}, /* "ad" for years > 0 */
212 {"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
213@@ -188,7 +188,7 @@ static const datetkn datetktbl[] = {
214 static int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
215
216 static datetkn deltatktbl[] = {
217- /* text, token, lexval */
218+ /* token, type, value */
219 {"@", IGNORE_DTF, 0}, /* postgres relative prefix */
220 {DAGO, AGO, 0}, /* "ago" indicates negative time offset */
221 {"c", UNITS, DTK_CENTURY}, /* "century" relative */
222@@ -4201,6 +4201,7 @@ ConvertTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl,
223 tbl->numabbrevs = n;
224 for (i = 0; i < n; i++)
225 {
226+ /* do NOT use strlcpy here; token field need not be null-terminated */
227 strncpy(newtbl[i].token, abbrevs[i].abbrev, TOKMAXLEN);
228 newtbl[i].type = abbrevs[i].is_dst ? DTZ : TZ;
229 TOVAL(&newtbl[i], abbrevs[i].offset / MINS_PER_HOUR);
230diff --git a/src/bin/initdb/findtimezone.c b/src/bin/initdb/findtimezone.c
231index 6d6f96a..6d38151 100644
232--- a/src/bin/initdb/findtimezone.c
233+++ b/src/bin/initdb/findtimezone.c
234@@ -68,7 +68,7 @@ pg_open_tzfile(const char *name, char *canonname)
235 if (canonname)
236 strlcpy(canonname, name, TZ_STRLEN_MAX + 1);
237
238- strcpy(fullname, pg_TZDIR());
239+ strlcpy(fullname, pg_TZDIR(), sizeof(fullname));
240 if (strlen(fullname) + 1 + strlen(name) >= MAXPGPATH)
241 return -1; /* not gonna fit */
242 strcat(fullname, "/");
243@@ -375,7 +375,7 @@ identify_system_timezone(void)
244 }
245
246 /* Search for the best-matching timezone file */
247- strcpy(tmptzdir, pg_TZDIR());
248+ strlcpy(tmptzdir, pg_TZDIR(), sizeof(tmptzdir));
249 bestscore = -1;
250 resultbuf[0] = '\0';
251 scan_available_timezones(tmptzdir, tmptzdir + strlen(tmptzdir) + 1,
252diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
253index 9d840a1..26cc758 100644
254--- a/src/bin/pg_basebackup/pg_basebackup.c
255+++ b/src/bin/pg_basebackup/pg_basebackup.c
256@@ -735,9 +735,9 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
257 FILE *file = NULL;
258
259 if (PQgetisnull(res, rownum, 0))
260- strcpy(current_path, basedir);
261+ strlcpy(current_path, basedir, sizeof(current_path));
262 else
263- strcpy(current_path, PQgetvalue(res, rownum, 1));
264+ strlcpy(current_path, PQgetvalue(res, rownum, 1), sizeof(current_path));
265
266 /*
267 * Get the COPY data
268@@ -1053,7 +1053,7 @@ BaseBackup(void)
269 progname);
270 disconnect_and_exit(1);
271 }
272- strcpy(xlogstart, PQgetvalue(res, 0, 0));
273+ strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
274 if (verbose && includewal)
275 fprintf(stderr, "transaction log start point: %s\n", xlogstart);
276 PQclear(res);
277@@ -1153,7 +1153,7 @@ BaseBackup(void)
278 progname);
279 disconnect_and_exit(1);
280 }
281- strcpy(xlogend, PQgetvalue(res, 0, 0));
282+ strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
283 if (verbose && includewal)
284 fprintf(stderr, "transaction log end point: %s\n", xlogend);
285 PQclear(res);
286diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
287index f2e7edd..7ae8556 100644
288--- a/src/interfaces/ecpg/preproc/pgc.l
289+++ b/src/interfaces/ecpg/preproc/pgc.l
290@@ -1315,7 +1315,7 @@ parse_include(void)
291 yytext[i] = '\0';
292 memmove(yytext, yytext+1, strlen(yytext));
293
294- strncpy(inc_file, yytext, sizeof(inc_file));
295+ strlcpy(inc_file, yytext, sizeof(inc_file));
296 yyin = fopen(inc_file, "r");
297 if (!yyin)
298 {
299diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
300index 1ba5885..af4c412 100644
301--- a/src/interfaces/libpq/fe-protocol2.c
302+++ b/src/interfaces/libpq/fe-protocol2.c
303@@ -500,7 +500,7 @@ pqParseInput2(PGconn *conn)
304 if (!conn->result)
305 return;
306 }
307- strncpy(conn->result->cmdStatus, conn->workBuffer.data,
308+ strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
309 CMDSTATUS_LEN);
310 checkXactStatus(conn, conn->workBuffer.data);
311 conn->asyncStatus = PGASYNC_READY;
312diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
313index d289f82..6f8a470 100644
314--- a/src/interfaces/libpq/fe-protocol3.c
315+++ b/src/interfaces/libpq/fe-protocol3.c
316@@ -206,7 +206,7 @@ pqParseInput3(PGconn *conn)
317 if (!conn->result)
318 return;
319 }
320- strncpy(conn->result->cmdStatus, conn->workBuffer.data,
321+ strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
322 CMDSTATUS_LEN);
323 conn->asyncStatus = PGASYNC_READY;
324 break;
325diff --git a/src/port/exec.c b/src/port/exec.c
326index c79e8ba..0726dbe 100644
327--- a/src/port/exec.c
328+++ b/src/port/exec.c
329@@ -66,7 +66,7 @@ validate_exec(const char *path)
330 if (strlen(path) >= strlen(".exe") &&
331 pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
332 {
333- strcpy(path_exe, path);
334+ strlcpy(path_exe, path, sizeof(path_exe) - 4);
335 strcat(path_exe, ".exe");
336 path = path_exe;
337 }
338@@ -275,7 +275,7 @@ resolve_symlinks(char *path)
339 }
340
341 /* must copy final component out of 'path' temporarily */
342- strcpy(link_buf, fname);
343+ strlcpy(link_buf, fname, sizeof(link_buf));
344
345 if (!getcwd(path, MAXPGPATH))
346 {
347diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
348index d991a5c..a6466eb 100644
349--- a/src/test/regress/pg_regress.c
350+++ b/src/test/regress/pg_regress.c
351@@ -1233,7 +1233,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
352 */
353 platform_expectfile = get_expectfile(testname, resultsfile);
354
355- strcpy(expectfile, default_expectfile);
356+ strlcpy(expectfile, default_expectfile, sizeof(expectfile));
357 if (platform_expectfile)
358 {
359 /*
360@@ -1288,7 +1288,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
361 {
362 /* This diff was a better match than the last one */
363 best_line_count = l;
364- strcpy(best_expect_file, alt_expectfile);
365+ strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
366 }
367 free(alt_expectfile);
368 }
369@@ -1316,7 +1316,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
370 {
371 /* This diff was a better match than the last one */
372 best_line_count = l;
373- strcpy(best_expect_file, default_expectfile);
374+ strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
375 }
376 }
377
378diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
379index d5bc83e..80c5635 100644
380--- a/src/timezone/pgtz.c
381+++ b/src/timezone/pgtz.c
382@@ -83,7 +83,7 @@ pg_open_tzfile(const char *name, char *canonname)
383 * Loop to split the given name into directory levels; for each level,
384 * search using scan_directory_ci().
385 */
386- strcpy(fullname, pg_TZDIR());
387+ strlcpy(fullname, pg_TZDIR(), sizeof(fullname));
388 orignamelen = fullnamelen = strlen(fullname);
389 fname = name;
390 for (;;)
391--
3921.7.5.4
393
diff --git a/meta-oe/recipes-support/postgresql/files/no-ecpg-test.patch b/meta-oe/recipes-support/postgresql/files/no-ecpg-test.patch
new file mode 100644
index 000000000..c0f28f425
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/no-ecpg-test.patch
@@ -0,0 +1,12 @@
1diff --git a/src/interfaces/ecpg/Makefile b/src/interfaces/ecpg/Makefile
2index dcd578f..1428423 100644
3--- a/src/interfaces/ecpg/Makefile
4+++ b/src/interfaces/ecpg/Makefile
5@@ -8,7 +8,6 @@ all install installdirs uninstall dep depend distprep:
6 $(MAKE) -C ecpglib $@
7 $(MAKE) -C compatlib $@
8 $(MAKE) -C preproc $@
9- $(MAKE) -C test $@
10
11 clean distclean maintainer-clean:
12 -$(MAKE) -C include $@
diff --git a/meta-oe/recipes-support/postgresql/files/postgresql-bashprofile b/meta-oe/recipes-support/postgresql/files/postgresql-bashprofile
new file mode 100644
index 000000000..1c931f37f
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/postgresql-bashprofile
@@ -0,0 +1,4 @@
1[ -f /etc/profile ] && source /etc/profile
2
3PGDATA=/var/lib/postgresql/data
4export PGDATA
diff --git a/meta-oe/recipes-support/postgresql/files/postgresql-setup b/meta-oe/recipes-support/postgresql/files/postgresql-setup
new file mode 100644
index 000000000..75bb01e05
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/postgresql-setup
@@ -0,0 +1,73 @@
1#!/bin/sh
2#
3# postgresql-setup Initialization operation for PostgreSQL
4
5# For SELinux we need to use 'runuser' not 'su'
6if [ -x /sbin/runuser ]
7then
8 SU=runuser
9else
10 SU=su
11fi
12
13PGENGINE=/usr/bin
14PGDATA=/var/lib/postgresql/data
15PGLOG=/var/lib/postgresql/pgstartup.log
16script_result=0
17
18initdb(){
19 if [ -f "$PGDATA/PG_VERSION" ]
20 then
21 echo -n "Data directory is not empty!"
22 echo -n " [FAILED] "
23 echo
24 script_result=1
25 else
26 echo -n "Initializing database: "
27 if [ ! -e "$PGDATA" -a ! -h "$PGDATA" ]
28 then
29 mkdir -p "$PGDATA" || exit 1
30 chown postgres:postgres "$PGDATA"
31 chmod go-rwx "$PGDATA"
32 fi
33 # Clean up SELinux tagging for PGDATA
34 [ -x /sbin/restorecon ] && /sbin/restorecon "$PGDATA"
35
36 # Make sure the startup-time log file is OK, too
37 if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]
38 then
39 touch "$PGLOG" || exit 1
40 chown postgres:postgres "$PGLOG"
41 chmod go-rwx "$PGLOG"
42 [ -x /sbin/restorecon ] && /sbin/restorecon "$PGLOG"
43 fi
44
45 # Initialize the database
46 $SU -l postgres -c "$PGENGINE/initdb --pgdata='$PGDATA' --auth='ident'" >> "$PGLOG" 2>&1 < /dev/null
47
48 # Create directory for postmaster log
49 mkdir "$PGDATA/pg_log"
50 chown postgres:postgres "$PGDATA/pg_log"
51 chmod go-rwx "$PGDATA/pg_log"
52
53 if [ -f "$PGDATA/PG_VERSION" ]
54 then
55 echo -n " [ OK ] "
56 else
57 echo -n " [FAILED] "
58 script_result=1
59 fi
60 echo
61 fi
62}
63
64case "$1" in
65 initdb)
66 initdb
67 ;;
68 *)
69 echo "Usage: $0 initdb"
70 exit 2
71esac
72
73exit $script_result
diff --git a/meta-oe/recipes-support/postgresql/files/postgresql.init b/meta-oe/recipes-support/postgresql/files/postgresql.init
new file mode 100644
index 000000000..4a4f0cd16
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/postgresql.init
@@ -0,0 +1,193 @@
1#!/bin/sh
2#
3# postgresql This is the init script for starting up the PostgreSQL
4# server.
5#
6# chkconfig: - 64 36
7# description: PostgreSQL database server.
8# processname: postmaster
9# pidfile: /var/run/postmaster.PORT.pid
10
11# This script is slightly unusual in that the name of the daemon (postmaster)
12# is not the same as the name of the subsystem (postgresql)
13
14# PGVERSION is the full package version, e.g., 8.4.0
15# Note: the specfile inserts the correct value during package build
16PGVERSION=9.2.4
17# PGMAJORVERSION is major version, e.g., 8.4 (this should match PG_VERSION)
18PGMAJORVERSION=`echo "$PGVERSION" | sed 's/^\([0-9]*\.[0-9]*\).*$/\1/'`
19
20# Source function library.
21. /etc/init.d/functions
22
23# Find the name of the script
24NAME=`basename $0`
25if [ ${NAME:0:1} = "S" -o ${NAME:0:1} = "K" ]
26then
27 NAME=${NAME:3}
28fi
29
30# For SELinux we need to use 'runuser' not 'su'
31if [ -x /sbin/runuser ]
32then
33 SU=runuser
34else
35 SU=su
36fi
37
38
39# Set defaults for configuration variables
40PGENGINE=/usr/bin
41PGPORT=5432
42PGDATA=/var/lib/postgresql/data
43PGLOG=/var/lib/postgresql/pgstartup.log
44# Value to set as postmaster process's oom_adj
45PG_OOM_ADJ=-17
46
47# Override defaults from /etc/sysconfig/postgresql if file is present
48[ -f /etc/default/postgresql/${NAME} ] && . /etc/default/postgresql/${NAME}
49
50export PGDATA
51export PGPORT
52
53lockfile="/var/lock/subsys/${NAME}"
54pidfile="/var/run/postmaster.${PGPORT}.pid"
55
56script_result=0
57
58start(){
59 [ -x "$PGENGINE/postmaster" ] || exit 5
60
61 PSQL_START=$"Starting ${NAME} service: "
62
63 # Make sure startup-time log file is valid
64 if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]
65 then
66 touch "$PGLOG" || exit 4
67 chown postgres:postgres "$PGLOG"
68 chmod go-rwx "$PGLOG"
69 [ -x /sbin/restorecon ] && /sbin/restorecon "$PGLOG"
70 fi
71
72 # Check for the PGDATA structure
73 if [ -f "$PGDATA/PG_VERSION" ] && [ -d "$PGDATA/base" ]
74 then
75 # Check version of existing PGDATA
76 if [ x`cat "$PGDATA/PG_VERSION"` != x"$PGMAJORVERSION" ]
77 then
78 SYSDOCDIR="(Your System's documentation directory)"
79 if [ -d "/usr/doc/postgresql-$PGVERSION" ]
80 then
81 SYSDOCDIR=/usr/doc
82 fi
83 if [ -d "/usr/share/doc/postgresql-$PGVERSION" ]
84 then
85 SYSDOCDIR=/usr/share/doc
86 fi
87 if [ -d "/usr/doc/packages/postgresql-$PGVERSION" ]
88 then
89 SYSDOCDIR=/usr/doc/packages
90 fi
91 if [ -d "/usr/share/doc/packages/postgresql-$PGVERSION" ]
92 then
93 SYSDOCDIR=/usr/share/doc/packages
94 fi
95 echo
96 echo $"An old version of the database format was found."
97 echo $"You need to upgrade the data format before using PostgreSQL."
98 echo $"See $SYSDOCDIR/postgresql-$PGVERSION/README.rpm-dist for more information."
99 exit 1
100 fi
101 else
102 # No existing PGDATA! Warn the user to initdb it.
103 echo
104 echo "$PGDATA is missing. Use \"postgresql-setup initdb\" to initialize the cluster first."
105 echo -n " [FAILED] "
106 echo
107 exit 1
108 fi
109
110 echo -n "$PSQL_START"
111 test x"$PG_OOM_ADJ" != x && echo "$PG_OOM_ADJ" > /proc/self/oom_score_adj
112 $SU -l postgres -c "$PGENGINE/postmaster -p '$PGPORT' -D '$PGDATA' ${PGOPTS} &" >> "$PGLOG" 2>&1 < /dev/null
113 sleep 2
114 pid=`head -n 1 "$PGDATA/postmaster.pid" 2>/dev/null`
115 if [ "x$pid" != x ]
116 then
117 echo -n " [ OK ]"
118 touch "$lockfile"
119 echo $pid > "$pidfile"
120 echo
121 else
122 echo -n " [FAILED]"
123 echo
124 script_result=1
125 fi
126}
127
128stop(){
129 echo -n $"Stopping ${NAME} service: "
130 if [ -e "$lockfile" ]
131 then
132 $SU -l postgres -c "$PGENGINE/pg_ctl stop -D '$PGDATA' -s -m fast" > /dev/null 2>&1 < /dev/null
133 ret=$?
134 if [ $ret -eq 0 ]
135 then
136 echo -n " [ OK ] "
137 rm -f "$pidfile"
138 rm -f "$lockfile"
139 else
140 echo -n " [FAILED] "
141 script_result=1
142 fi
143 else
144 # not running; per LSB standards this is "ok"
145 echo -n " [ OK ] "
146 fi
147 echo
148}
149
150restart(){
151 stop
152 start
153}
154
155condrestart(){
156 [ -e "$lockfile" ] && restart || :
157}
158
159reload(){
160 $SU -l postgres -c "$PGENGINE/pg_ctl reload -D '$PGDATA' -s" > /dev/null 2>&1 < /dev/null
161}
162
163
164# See how we were called.
165case "$1" in
166 start)
167 start
168 ;;
169 stop)
170 stop
171 ;;
172 status)
173 status postmaster
174 script_result=$?
175 ;;
176 restart)
177 restart
178 ;;
179 condrestart|try-restart)
180 condrestart
181 ;;
182 reload)
183 reload
184 ;;
185 force-reload)
186 restart
187 ;;
188 *)
189 echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
190 exit 2
191esac
192
193exit $script_result
diff --git a/meta-oe/recipes-support/postgresql/files/postgresql.pam b/meta-oe/recipes-support/postgresql/files/postgresql.pam
new file mode 100644
index 000000000..0b6fdc5f2
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/postgresql.pam
@@ -0,0 +1,4 @@
1#%PAM-1.0
2auth include common-auth
3account include common-account
4password include common-password
diff --git a/meta-oe/recipes-support/postgresql/files/postgresql.service b/meta-oe/recipes-support/postgresql/files/postgresql.service
new file mode 100644
index 000000000..4ec959e84
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/files/postgresql.service
@@ -0,0 +1,27 @@
1[Unit]
2Description=PostgreSQL database server
3After=network.target
4
5[Service]
6Type=forking
7User=postgres
8Group=postgres
9
10# Port number for server to listen on
11Environment=PGPORT=5432
12
13# Location of database directory
14Environment=PGDATA=/var/lib/postgresql/data
15
16# Disable OOM kill on the postmaster
17OOMScoreAdjust=-17
18
19ExecStart=@BINDIR@/pg_ctl start -D ${PGDATA} -s -o "-p ${PGPORT}" -w -t 300
20ExecStop=@BINDIR@/pg_ctl stop -D ${PGDATA} -s -m fast
21ExecReload=@BINDIR@/pg_ctl reload -D ${PGDATA} -s
22
23# Give a reasonable amount of time for the server to start up/shut down
24TimeoutSec=300
25
26[Install]
27WantedBy=multi-user.target
diff --git a/meta-oe/recipes-support/postgresql/postgresql-9.2.4/ecpg-parallel-make-fix.patch b/meta-oe/recipes-support/postgresql/postgresql-9.2.4/ecpg-parallel-make-fix.patch
new file mode 100644
index 000000000..63615cd51
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/postgresql-9.2.4/ecpg-parallel-make-fix.patch
@@ -0,0 +1,31 @@
1Upstream-status: backport
2
3From 602070f9cce790debd8d1469254e7726ab499ae7 Mon Sep 17 00:00:00 2001
4From: Peter Eisentraut <peter_e@gmx.net>
5Date: Fri, 29 Mar 2013 21:39:55 -0400
6Subject: [PATCH] ecpg: Parallel make fix
7
8In some parallel make situations, the install-headers target could be
9called before the installation directories are created by installdirs,
10causing the installation to fail. Fix that by making install-headers
11depend on installdirs.
12---
13 src/interfaces/ecpg/include/Makefile | 2 +-
14 1 file changed, 1 insertion(+), 1 deletion(-)
15
16diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile
17index eab833b..e92e56f 100644
18--- a/src/interfaces/ecpg/include/Makefile
19+++ b/src/interfaces/ecpg/include/Makefile
20@@ -18,7 +18,7 @@ ecpg_headers = ecpgerrno.h ecpglib.h ecpgtype.h sqlca.h sql3types.h ecpg_informi
21 sqlda.h sqlda-compat.h sqlda-native.h
22 informix_headers = datetime.h decimal.h sqltypes.h
23
24-install-headers: $(ecpg_headers) $(informix_headers)
25+install-headers: $(ecpg_headers) $(informix_headers) installdirs
26 $(INSTALL_DATA) $(addprefix $(srcdir)/,$(ecpg_headers)) '$(DESTDIR)$(includedir)/'
27 $(INSTALL_DATA) $(addprefix $(srcdir)/,$(informix_headers)) '$(DESTDIR)$(informix_esql_dir)/'
28 $(INSTALL_DATA) $(ecpg_config_h) '$(DESTDIR)$(includedir)'
29--
301.8.3.4
31
diff --git a/meta-oe/recipes-support/postgresql/postgresql-9.2.4/remove.autoconf.version.check.patch b/meta-oe/recipes-support/postgresql/postgresql-9.2.4/remove.autoconf.version.check.patch
new file mode 100644
index 000000000..022aa3d76
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/postgresql-9.2.4/remove.autoconf.version.check.patch
@@ -0,0 +1,15 @@
1Index: postgresql-9.2.4/configure.in
2===================================================================
3--- postgresql-9.2.4.orig/configure.in
4+++ postgresql-9.2.4/configure.in
5@@ -19,10 +19,6 @@ m4_pattern_forbid(^PGAC_)dnl to catch un
6
7 AC_INIT([PostgreSQL], [9.2.4], [pgsql-bugs@postgresql.org])
8
9-m4_if(m4_defn([m4_PACKAGE_VERSION]), [2.63], [], [m4_fatal([Autoconf version 2.63 is required.
10-Untested combinations of 'autoconf' and PostgreSQL versions are not
11-recommended. You can remove the check from 'configure.in' but it is then
12-your responsibility whether the result works or not.])])
13 AC_COPYRIGHT([Copyright (c) 1996-2012, PostgreSQL Global Development Group])
14 AC_CONFIG_SRCDIR([src/backend/access/common/heaptuple.c])
15 AC_CONFIG_AUX_DIR(config)
diff --git a/meta-oe/recipes-support/postgresql/postgresql.inc b/meta-oe/recipes-support/postgresql/postgresql.inc
new file mode 100644
index 000000000..1397f564d
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/postgresql.inc
@@ -0,0 +1,395 @@
1SUMMARY = "PostgreSQL is a powerful, open source relational database system."
2DESCRIPTION = "\
3 PostgreSQL is an advanced Object-Relational database management system \
4 (DBMS) that supports almost all SQL constructs (including \
5 transactions, subselects and user-defined types and functions). The \
6 postgresql package includes the client programs and libraries that \
7 you'll need to access a PostgreSQL DBMS server. These PostgreSQL \
8 client programs are programs that directly manipulate the internal \
9 structure of PostgreSQL databases on a PostgreSQL server. These client \
10 programs can be located on the same machine with the PostgreSQL \
11 server, or may be on a remote machine which accesses a PostgreSQL \
12 server over a network connection. This package contains the docs \
13 in HTML for the whole package, as well as command-line utilities for \
14 managing PostgreSQL databases on a PostgreSQL server. \
15 \
16 If you want to manipulate a PostgreSQL database on a local or remote \
17 PostgreSQL server, you need this package. You also need to install \
18 this package if you're installing the postgresql-server package. \
19 "
20HOMEPAGE = "http://www.postgresql.com"
21LICENSE = "BSD"
22DEPENDS = "zlib readline tzcode-native"
23INC_PR = "r0"
24
25ARM_INSTRUCTION_SET = "arm"
26
27SRC_URI = "http://ftp.postgresql.org/pub/source/v${PV}/${BP}.tar.bz2 \
28 file://postgresql.init \
29 file://postgresql-bashprofile \
30 file://postgresql.pam \
31 file://postgresql-setup \
32 file://postgresql.service \
33 file://0001-Use-pkg-config-for-libxml2-detection.patch \
34 file://0002-Predict-integer-overflow-to-avoid-buffer-overruns.patch \
35 file://0003-Shore-up-ADMIN-OPTION-restrictions.patch \
36 file://0004-Prevent-privilege-escalation-in-explicit-calls-to-PL.patch \
37 file://0005-Avoid-repeated-name-lookups-during-table-and-index-D.patch \
38 file://0006-Fix-handling-of-wide-datetime-input-output.patch \
39 file://0007-Make-pqsignal-available-to-pg_regress-of-ECPG-and-is.patch \
40 file://0008-Prevent-potential-overruns-of-fixed-size-buffers.patch \
41 "
42
43LEAD_SONAME = "libpq.so"
44
45# LDFLAGS for shared libraries
46export LDFLAGS_SL = "${LDFLAGS}"
47
48inherit autotools pkgconfig perlnative pythonnative useradd update-rc.d systemd
49
50SYSTEMD_SERVICE_${PN} = "postgresql.service"
51SYSTEMD_AUTO_ENABLE_${PN} = "disable"
52
53DEPENDS_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-systemctl-native', '', d)}"
54pkg_postinst_${PN} () {
55 if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd sysvinit', 'true', 'false', d)}; then
56 if [ -n "$D" ]; then
57 OPTS="--root=$D"
58 fi
59 systemctl $OPTS mask postgresql-server.service
60 fi
61}
62
63enable_pam = "${@base_contains('DISTRO_FEATURES', 'pam', 'pam', '', d)}"
64PACKAGECONFIG ??= "${enable_pam} openssl python uuid libxml tcl nls libxml perl"
65PACKAGECONFIG[pam] = "--with-pam,--without-pam,libpam,"
66PACKAGECONFIG[openssl] = "--with-openssl,--without-openssl,openssl,"
67PACKAGECONFIG[python] = "--with-python,--without-python,python,python"
68PACKAGECONFIG[uuid] = "--with-ossp-uuid,--without-ossp-uuid,ossp-uuid,"
69# when tcl native package is fixed change WORKDIR to STAGING_BINDIR_CROSS
70PACKAGECONFIG[tcl] = \
71 "--with-tcl --with-tclconfig=${STAGING_BINDIR_CROSS},--without-tcl,tcl,"
72PACKAGECONFIG[nls] = "--enable-nls,--disable-nls,,"
73PACKAGECONFIG[libxml] = "--with-libxml,--without-libxml,libxml2,libxml2"
74PACKAGECONFIG[perl] = "--with-perl,--without-perl,perl,perl"
75
76EXTRA_OECONF += "--enable-thread-safety --disable-rpath \
77 --datadir=${datadir}/${BPN} \
78 --sysconfdir=${sysconfdir}/${BPN} \
79 --without-krb5 \
80"
81EXTRA_OECONF_sh4 += "--disable-spinlocks"
82EXTRA_OECONF_aarch64 += "--disable-spinlocks"
83
84PACKAGES_DYNAMIC += "^${PN}-plperl ^${PN}-plperl-dbg \
85 ^${PN}-pltcl ^${PN}-pltcl-dbg \
86 ^${PN}-plpython ^${PN}-plpython-dbg \
87"
88
89python populate_packages_prepend() {
90
91 def fill_more(name, dbg=True):
92 if name is None or name.strip() == "":
93 return
94
95 fpack=d.getVar('PACKAGES') or ""
96 fpack="${PN}-" + name + " " + fpack
97 if dbg:
98 fpack="${PN}-" + name + "-dbg" + " " + fpack
99 d.setVar('PACKAGES', fpack)
100
101 conf=(d.getVar('PACKAGECONFIG', True) or "").split()
102 pack=d.getVar('PACKAGES') or ""
103 bb.debug(1, "PACKAGECONFIG=%s" % conf)
104 bb.debug(1, "PACKAGES1=%s" % pack )
105
106 if "perl" in conf :
107 fill_more("plperl")
108
109 if "tcl" in conf:
110 fill_more("pltcl")
111
112 if "python" in conf:
113 fill_more("plpython")
114
115 pack=d.getVar('PACKAGES', True) or ""
116 bb.debug(1, "PACKAGES2=%s" % pack)
117
118}
119
120do_configure() {
121 # do_configure_prepend
122 # make sure configure finds python includdirs with these envs
123 export BUILD_SYS=${BUILD_SYS} HOST_SYS=${HOST_SYS} \
124 STAGING_INCDIR=${STAGING_INCDIR} \
125 STAGING_LIBDIR=${STAGING_LIBDIR}
126
127 # do_configure
128 autotools_do_configure
129
130 # do_configure_append
131 # workaround perl package related bugs
132 sed -i -e "s:-L/usr/local/lib:-L=/usr/local/lib:g" \
133 ${B}/src/Makefile.global
134 LIBPNA="\${STAGING_LIBDIR_NATIVE}/perl-native"
135 LIBNA="\${STAGING_LIBDIR_NATIVE}"
136 BLIBNA="\${STAGING_BASE_LIBDIR_NATIVE}"
137 sed -i -e "/^perl_archlibexp/s:${LIBPNA}:${STAGING_LIBDIR}:g" \
138 ${B}/src/Makefile.global
139 sed -i -e "/^perl_privlibexp/s:${LIBPNA}:${STAGING_LIBDIR}:g" \
140 ${B}/src/Makefile.global
141 # remove the rpath, replace with correct lib path
142 sed -i \
143 -e "/^perl_embed_ldflags/s:-Wl,-rpath,${LIBNA}::g" \
144 -e "/^perl_embed_ldflags/s:-Wl,-rpath,${BLIBNA}::g" \
145 -e "/^perl_embed_ldflags/s:-Wl,-rpath-link,${LIBNA}::g" \
146 -e "/^perl_embed_ldflags/s:-Wl,-rpath-link,${BLIBNA}::g" \
147 -e "/^perl_embed_ldflags/s:${LIBPNA}:${STAGING_LIBDIR}:g" \
148 -e "/^perl_embed_ldflags/s:${LIBNA}:${STAGING_LIBDIR}:g" \
149 -e "/^perl_embed_ldflags/s:${BLIBNA}:${STAGING_BASELIBDIR}:g" \
150 ${B}/src/Makefile.global
151
152 # workaround perl package's libperl.so problem
153 # we are using perlnative so this perl should have same version
154 perl_version=`perl -v 2>/dev/null | \
155 sed -n 's/This is perl.*v[a-z ]*\([0-9]\.[0-9][0-9.]*\).*$/\1/p'`
156 if [ ! -h "${STAGING_LIBDIR}/perl/$perl_version/CORE/libperl.so" -a \
157 ! -h "${STAGING_LIBDIR}/libperl.so" ]; then
158 ln -sf ../../../libperl.so.5 \
159 ${STAGING_LIBDIR}/perl/$perl_version/CORE/libperl.so
160 fi
161}
162
163do_compile_append() {
164 oe_runmake -C contrib all
165}
166
167# server needs to configure user and group
168usernum = "28"
169groupnum = "28"
170USERADD_PACKAGES = "${PN}"
171USERADD_PARAM_${PN} = "-M -g postgres -o -r -d ${localstatedir}/lib/${BPN} \
172 -s /bin/bash -c 'PostgreSQL Server' -u ${usernum} postgres"
173GROUPADD_PARAM_${PN} = "-g ${groupnum} -o -r postgres"
174
175INITSCRIPT_PACKAGES = "${PN}"
176INITSCRIPT_NAME = "${BPN}-server"
177INITSCRIPT_PARAMS = "start 64 . stop 36 0 1 2 3 4 5 6 ."
178
179do_install_append() {
180 # install contrib
181 oe_runmake DESTDIR=${D} -C contrib install
182 # install tutorial
183 install -d -m 0755 ${D}${libdir}/${BPN}/tutorial
184 install ${B}/src/tutorial/* ${D}${libdir}/${BPN}/tutorial
185
186 # install COPYRIGHT README HISTORY
187 install -d -m 0755 ${D}${docdir}/${BPN}
188 for i in ${B}/{COPYRIGHT,README,HISTORY} ${B}/doc/{KNOWN_BUGS,MISSING_FEATURES,README*,bug.template}; do
189 [ -f $i ] && install $i ${D}${docdir}/${BPN}
190 done
191
192 # install dirs and server init
193 install -d ${D}${sysconfdir}/init.d
194 install -m 0755 ${WORKDIR}/${BPN}.init ${D}${sysconfdir}/init.d/${BPN}-server
195 sed -i -e "s/^PGVERSION=.*$/PGVERSION=${PV}/g" ${D}${sysconfdir}/init.d/${BPN}-server
196 install -m 0755 ${WORKDIR}/${BPN}-setup ${D}${bindir}/${BPN}-setup
197 install -d -m 700 ${D}${localstatedir}/lib/${BPN}/data
198 install -d -m 700 ${D}${localstatedir}/lib/${BPN}/backups
199 install -m 644 ${WORKDIR}/${BPN}-bashprofile ${D}${localstatedir}/lib/${BPN}/.bash_profile
200 chown -R postgres:postgres ${D}${localstatedir}/lib/${BPN}
201 # multiple server config directory
202 install -d -m 700 ${D}${sysconfdir}/default/${BPN}
203
204 if [ "${@d.getVar('enable_pam', True)}" = "pam" ]; then
205 install -d ${D}${sysconfdir}/pam.d
206 install -m 644 ${WORKDIR}/postgresql.pam ${D}${sysconfdir}/pam.d/postgresql
207 fi
208
209 # Install systemd unit files
210 install -d ${D}${systemd_unitdir}/system
211 install -m 0644 ${WORKDIR}/postgresql.service ${D}${systemd_unitdir}/system
212 sed -i -e 's,@BINDIR@,${bindir},g' \
213 ${D}${systemd_unitdir}/system/postgresql.service
214}
215
216SSTATE_SCAN_FILES += "Makefile.global"
217
218PACKAGES =+ "${PN}-client ${PN}-server-dev ${PN}-timezone \
219 libecpg-compat-dbg libecpg-compat libecpg-compat-dev \
220 libecpg-dbg libecpg libecpg-dev libecpg-staticdev libecpg-doc \
221 libpq-dbg libpq libpq-dev libpq-staticdev \
222 libpgtypes-dbg libpgtypes libpgtypes-staticdev libpgtypes-dev \
223 ${PN}-contrib ${PN}-contrib-dbg \
224"
225
226FILES_${PN} += "${sysconfdir}/init.d/${BPN}-server \
227 ${localstatedir}/lib/${BPN}/data ${localstatedir}/lib/${BPN}/backups \
228 ${localstatedir}/lib/${BPN}/.bash_profile ${sysconfdir}/default/${BPN} \
229 ${libdir}/${BPN}/dict_snowball.so ${libdir}/${BPN}/plpgsql.so \
230 ${libdir}/${BPN}/euc2004_sjis2004.so \
231 ${libdir}/${BPN}/libpqwalreceiver.so \
232 ${libdir}/${BPN}/*_and_*.so \
233 ${@'${sysconfdir}/pam.d/postgresql' \
234 if 'pam' == d.getVar('enable_pam', True) \
235 else ''} \
236"
237
238FILES_${PN}-dbg += " ${libdir}/${BPN}/.debug/dict_snowball.so \
239 ${libdir}/${BPN}/.debug/plpgsql.so \
240 ${libdir}/${BPN}/.debug/euc2004_sjis2004.so \
241 ${libdir}/${BPN}/.debug/libpqwalreceiver.so \
242 ${libdir}/${BPN}/.debug/*_and_*.so \
243"
244
245FILES_${PN}-client = "${bindir}/clusterdb \
246 ${bindir}/createdb \
247 ${bindir}/createlang \
248 ${bindir}/createuser \
249 ${bindir}/dropdb \
250 ${bindir}/droplang \
251 ${bindir}/dropuser \
252 ${bindir}/pg_dump \
253 ${bindir}/pg_dumpall \
254 ${bindir}/pg_restore \
255 ${bindir}/psql \
256 ${bindir}/reindexdb \
257 ${bindir}/vacuumdb \
258 ${bindir}/vacuumlo \
259 ${datadir}/${BPN}/psqlrc.sample"
260
261FILES_${PN}-client-doc = "${mandir}/man1/clusterdb.* \
262 ${mandir}/man1/createdb.* ${mandir}/man1/createlang.* \
263 ${mandir}/man1/createuser.* ${mandir}/man1/dropdb.* \
264 ${mandir}/man1/droplang.* ${mandir}/man1/dropuser.* \
265 ${mandir}/man1/pg_dump.* ${mandir}/man1/pg_dumpall.* \
266 ${mandir}/man1/pg_restore.* ${mandir}/man1/psql.* \
267 ${mandir}/man1/reindexdb.* ${mandir}/man1/vacuumdb.* \
268 ${mandir}/man7/* \
269"
270
271FILES_${PN}-doc += "${docdir}/${BPN}/html ${libdir}/${BPN}/tutorial/ \
272 ${mandir}/man1/initdb.* ${mandir}/man1/pg_controldata.* \
273 ${mandir}/man1/pg_ctl.* ${mandir}/man1/pg_resetxlog.* \
274 ${mandir}/man1/postgres.* ${mandir}/man1/postmaster.* \
275"
276
277FILES_${PN}-timezone = "${datadir}/${BPN}/timezone \
278 ${datadir}/${BPN}/timezonesets \
279"
280RDEPENDS_${PN} += "${PN}-timezone"
281FILES_${PN}-server-dev = "${includedir}/${BPN}/server"
282
283FILES_libecpg = "${libdir}/libecpg*${SOLIBS}"
284FILES_libecpg-dbg = "${libdir}/.debug/libecpg*"
285FILES_libecpg-dev = "${libdir}/libecpg*${SOLIBSDEV} \
286 ${libdir}/libpgtypes*${SOLIBSDEV} \
287 ${includedir}/ecpg*.h ${includedir}/${BPN}/ecpg*.h \
288 ${includedir}/pgtypes*.h ${includedir}/${BPN}/informix \
289 ${includedir}/sql3types.h ${includedir}/sqlca.h"
290FILES_libecpg-doc = "${mandir}/man1/ecpg.*"
291FILES_libecpg-staticdev = "${libdir}/libecpg*.a"
292SECTION_libecpg-staticdev = "devel"
293RDEPENDS_libecpg-staticdev = "libecpg-dev (= ${EXTENDPKGV})"
294
295FILES_libpq = "${libdir}/libpq*${SOLIBS}"
296FILES_libpq-dbg = "${libdir}/.debug/libpq* ${libdir}/${BPN}/pgxs/src/test/regress/.debug/*"
297FILES_libpq-dev = "${libdir}/libpq*${SOLIBSDEV} \
298 ${includedir}"
299FILES_libpq-staticdev = "${libdir}/libpq*.a ${libdir}/libpgport.a"
300SECTION_libpq-staticdev = "devel"
301RDEPENDS_libpq-staticdev = "libpq-dev (= ${EXTENDPKGV})"
302
303FILES_libecpg-compat = "${libdir}/libecpg_compat*${SOLIBS}"
304FILES_libecpg-compat-dbg = "${libdir}/.debug/libecpg_compat*"
305FILES_libecpg-compat-dev = "${libdir}/libecpg_compat*${SOLIBS}"
306FILES_libpgtypes = "${libdir}/libpgtypes*${SOLIBS}"
307FILES_libpgtypes-dbg = "${libdir}/.debug/libpgtypes*"
308FILES_libpgtypes-staticdev = "${libdir}/libpgtypes*.a"
309FILES_libpgtypes-dev = "${libdir}/libpgtypes*${SOLIBS} ${includedir}/pgtypes*.h"
310
311FILES_${PN}-contrib = " ${bindir}/oid2name ${bindir}/pg_standby \
312 ${bindir}/pgbench ${bindir}/vacuumlo \
313 ${S}/contrib/spi/*.example \
314 ${libdir}/${BPN}/_int.so ${libdir}/${BPN}/adminpack.so \
315 ${libdir}/${BPN}/autoinc.so ${libdir}/${BPN}/auto_explain.so \
316 ${libdir}/${BPN}/auth_delay.so ${libdir}/${BPN}/btree_gin.so \
317 ${libdir}/${BPN}/btree_gist.so ${libdir}/${BPN}/.so \
318 ${libdir}/${BPN}/chkpass.so ${libdir}/${BPN}/citext.so \
319 ${libdir}/${BPN}/cube.so ${libdir}/${BPN}/dblink.so \
320 ${libdir}/${BPN}/dict_int.so ${libdir}/${BPN}/dict_xsyn.so \
321 ${libdir}/${BPN}/dummy_seclabel.so ${libdir}/${BPN}/earthdistance.so \
322 ${libdir}/${BPN}/file_fdw.so ${libdir}/${BPN}/fuzzystrmatch.so \
323 ${libdir}/${BPN}/hstore.so ${libdir}/${BPN}/insert_username.so \
324 ${libdir}/${BPN}/isn.so ${libdir}/${BPN}/lo.so \
325 ${libdir}/${BPN}/ltree.so ${libdir}/${BPN}/moddatetime.so \
326 ${libdir}/${BPN}/pageinspect.so ${libdir}/${BPN}/pg_buffercache.so \
327 ${libdir}/${BPN}/pg_freespacemap.so ${libdir}/${BPN}/pg_trgm.so \
328 ${libdir}/${BPN}/pgcrypto.so ${libdir}/${BPN}/pgrowlocks.so \
329 ${libdir}/${BPN}/pgstattuple.so ${libdir}/${BPN}/pg_stat_statements.so \
330 ${libdir}/${BPN}/refint.so ${libdir}/${BPN}/seg.so \
331 ${libdir}/${BPN}/sslinfo.so \
332 ${libdir}/${BPN}/tablefunc.so \
333 ${libdir}/${BPN}/test_parser.so ${libdir}/${BPN}/timetravel.so \
334 ${libdir}/${BPN}/tsearch2.so ${libdir}/${BPN}/uuid-ossp.so \
335 ${libdir}/${BPN}/pgxml.so ${libdir}/${BPN}/passwordcheck.so \
336 ${libdir}/${BPN}/pg_upgrade_support.so ${libdir}/${BPN}/.so \
337 ${libdir}/${BPN}/unaccent.so \
338"
339FILES_${PN}-contrib-dbg = " \
340 ${libdir}/${BPN}/.debug/_int.so ${libdir}/${BPN}/.debug/adminpack.so \
341 ${libdir}/${BPN}/.debug/autoinc.so ${libdir}/${BPN}/.debug/auto_explain.so \
342 ${libdir}/${BPN}/.debug/auth_delay.so ${libdir}/${BPN}/.debug/btree_gin.so \
343 ${libdir}/${BPN}/.debug/btree_gist.so ${libdir}/${BPN}/.debug/.so \
344 ${libdir}/${BPN}/.debug/chkpass.so ${libdir}/${BPN}/.debug/citext.so \
345 ${libdir}/${BPN}/.debug/cube.so ${libdir}/${BPN}/.debug/dblink.so \
346 ${libdir}/${BPN}/.debug/dict_int.so ${libdir}/${BPN}/.debug/dict_xsyn.so \
347 ${libdir}/${BPN}/.debug/dummy_seclabel.so \
348 ${libdir}/${BPN}/.debug/earthdistance.so \
349 ${libdir}/${BPN}/.debug/file_fdw.so ${libdir}/${BPN}/.debug/fuzzystrmatch.so \
350 ${libdir}/${BPN}/.debug/hstore.so ${libdir}/${BPN}/.debug/insert_username.so \
351 ${libdir}/${BPN}/.debug/isn.so ${libdir}/${BPN}/.debug/lo.so \
352 ${libdir}/${BPN}/.debug/ltree.so ${libdir}/${BPN}/.debug/moddatetime.so \
353 ${libdir}/${BPN}/.debug/pageinspect.so \
354 ${libdir}/${BPN}/.debug/pg_buffercache.so \
355 ${libdir}/${BPN}/.debug/pg_freespacemap.so \
356 ${libdir}/${BPN}/.debug/pg_trgm.so \
357 ${libdir}/${BPN}/.debug/pgcrypto.so ${libdir}/${BPN}/.debug/pgrowlocks.so \
358 ${libdir}/${BPN}/.debug/pgstattuple.so \
359 ${libdir}/${BPN}/.debug/pg_stat_statements.so \
360 ${libdir}/${BPN}/.debug/refint.so ${libdir}/${BPN}/.debug/seg.so \
361 ${libdir}/${BPN}/.debug/sslinfo.so \
362 ${libdir}/${BPN}/.debug/tablefunc.so \
363 ${libdir}/${BPN}/.debug/test_parser.so ${libdir}/${BPN}/.debug/timetravel.so \
364 ${libdir}/${BPN}/.debug/tsearch2.so ${libdir}/${BPN}/.debug/uuid-ossp.so \
365 ${libdir}/${BPN}/.debug/pgxml.so ${libdir}/${BPN}/.debug/passwordcheck.so \
366 ${libdir}/${BPN}/.debug/pg_upgrade_support.so \
367 ${libdir}/${BPN}/.debug/unaccent.so \
368"
369DESCRIPTION_${PN}-contrib = "The postgresql-contrib package contains \
370 contributed packages that are included in the PostgreSQL distribution."
371
372FILES_${PN}-pltcl = "${libdir}/${BPN}/pltcl.so ${bindir}/pltcl_delmod \
373 ${binddir}/pltcl_listmod ${bindir}/pltcl_loadmod \
374 ${datadir}/${BPN}/unknown.pltcl"
375FILES_${PN}-pltcl-dbg = "${libdir}/${BPN}/.debug/pltcl.so"
376SUMMARY_${PN}-pltcl = "The Tcl procedural language for PostgreSQL"
377DESCRIPTION_${PN}-pltcl = "PostgreSQL is an advanced Object-Relational \
378 database management system. The postgresql-pltcl package contains the PL/Tcl \
379 procedural language for the backend."
380
381FILES_${PN}-plperl = "${libdir}/${BPN}/plperl.so"
382FILES_${PN}-plperl-dbg = "${libdir}/${BPN}/.debug/plperl.so"
383SUMMARY_${PN}-plperl = "The Perl procedural language for PostgreSQL"
384DESCRIPTION_${PN}-plperl = "PostgreSQL is an advanced Object-Relational \
385 database management system. The postgresql-plperl package contains the \
386 PL/Perl procedural language for the backend."
387
388# In version 8, it will be plpython.so
389# In version 9, it might be plpython{2,3}.so depending on python2 or 3
390FILES_${PN}-plpython = "${libdir}/${BPN}/plpython*.so"
391FILES_${PN}-plpython-dbg = "${libdir}/${BPN}/.debug/plpython*.so"
392SUMMARY_${PN}-plpython = "The Python procedural language for PostgreSQL"
393DESCRIPTION_${PN}-plpython = "PostgreSQL is an advanced Object-Relational \
394 database management system. The postgresql-plpython package contains \
395 the PL/Python procedural language for the backend."
diff --git a/meta-oe/recipes-support/postgresql/postgresql_9.2.4.bb b/meta-oe/recipes-support/postgresql/postgresql_9.2.4.bb
new file mode 100644
index 000000000..49ca53fae
--- /dev/null
+++ b/meta-oe/recipes-support/postgresql/postgresql_9.2.4.bb
@@ -0,0 +1,13 @@
1require postgresql.inc
2
3LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=ab55a5887d3f8ba77d0fd7db787e4bab"
4
5PR = "${INC_PR}.0"
6
7SRC_URI += "\
8 file://remove.autoconf.version.check.patch \
9 file://ecpg-parallel-make-fix.patch \
10"
11
12SRC_URI[md5sum] = "6ee5bb53b97da7c6ad9cb0825d3300dd"
13SRC_URI[sha256sum] = "d97dd918a88a4449225998f46aafa85216a3f89163a3411830d6890507ffae93"