summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch')
-rw-r--r--meta-oe/recipes-support/postgresql/files/0008-Prevent-potential-overruns-of-fixed-size-buffers.patch393
1 files changed, 393 insertions, 0 deletions
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