Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > d3c4bfd951c25dab3d8c83571c73f957 > files > 25

postgresql-8.1.23-10.el5_10.src.rpm

Backport fixes for security: CVE-2014-0065 for buffer overruns, CVE-2014-0066
for crypt().  Not all original REL8_4_STABLE hunks were applicable (fixes for
newer code).

Original git commit message:

    Prevent potential overruns of fixed-size buffers.

    Coverity identified a number of places in which it couldn't prove that a
    string being copied into a fixed-size buffer would fit.  We believe that
    most, perhaps all of these are in fact safe, or are copying data that is
    coming from a trusted source so that any overrun is not really a security
    issue.  Nonetheless it seems prudent to forestall any risk by using
    strlcpy() and similar functions.

    Fixes by Peter Eisentraut and Jozef Mlich based on Coverity reports.

    In addition, fix a potential null-pointer-dereference crash in
    contrib/chkpass.  The crypt(3) function is defined to return NULL on
    failure, but chkpass.c didn't check for that before using the result.
    The main practical case in which this could be an issue is if libc is
    configured to refuse to execute unapproved hashing algorithms (e.g.,
    "FIPS mode").  This ideally should've been a separate commit, but
    since it touches code adjacent to one of the buffer overrun changes,
    I included it in this commit to avoid last-minute merge issues.
    This issue was reported by Honza Horak.


diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c
index 8b77fb2..a60eb0c 100644
--- a/contrib/chkpass/chkpass.c
+++ b/contrib/chkpass/chkpass.c
@@ -69,6 +69,7 @@ chkpass_in(PG_FUNCTION_ARGS)
 	char	   *str = PG_GETARG_CSTRING(0);
 	chkpass    *result;
 	char		mysalt[4];
+	char	   *crypt_output;
 	static char salt_chars[] =
 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
@@ -92,7 +93,15 @@ chkpass_in(PG_FUNCTION_ARGS)
 	mysalt[1] = salt_chars[random() & 0x3f];
 	mysalt[2] = 0;				/* technically the terminator is not necessary
 								 * but I like to play safe */
-	strcpy(result->password, crypt(str, mysalt));
+
+	crypt_output = crypt(str, mysalt);
+	if (crypt_output == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("crypt() failed")));
+
+	strlcpy(result->password, crypt_output, sizeof(result->password));
+
 	PG_RETURN_POINTER(result);
 }
 
@@ -151,12 +160,20 @@ chkpass_eq(PG_FUNCTION_ARGS)
 	text	   *a2 = (text *) PG_GETARG_TEXT_P(1);
 	char		str[10];
 	int			sz = 8;
+	char	   *crypt_output;
 
 	if (a2->vl_len < 12)
 		sz = a2->vl_len - 4;
 	strncpy(str, a2->vl_dat, sz);
 	str[sz] = 0;
-	PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) == 0);
+
+	crypt_output = crypt(str, a1->password);
+	if (crypt_output == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("crypt() failed")));
+
+	PG_RETURN_BOOL(strcmp(a1->password, crypt_output) == 0);
 }
 
 PG_FUNCTION_INFO_V1(chkpass_ne);
@@ -167,10 +184,17 @@ chkpass_ne(PG_FUNCTION_ARGS)
 	text	   *a2 = (text *) PG_GETARG_TEXT_P(1);
 	char		str[10];
 	int			sz = 8;
+	char	   *crypt_output;
 
 	if (a2->vl_len < 12)
 		sz = a2->vl_len - 4;
 	strncpy(str, a2->vl_dat, sz);
 	str[sz] = 0;
-	PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) != 0);
+	crypt_output = crypt(str, a1->password);
+	if (crypt_output == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("crypt() failed")));
+
+	PG_RETURN_BOOL(strcmp(a1->password, crypt_output) != 0);
 }
diff --git a/contrib/tsearch2/ispell/spell.c b/contrib/tsearch2/ispell/spell.c
index 9027263..7d2be9b 100644
--- a/contrib/tsearch2/ispell/spell.c
+++ b/contrib/tsearch2/ispell/spell.c
@@ -137,7 +137,7 @@ NIAddSpell(IspellDict * Conf, const char *word, const char *flag)
 	}
 	Conf->Spell[Conf->nspell].word = strdup(word);
 	MEMOUT(Conf->Spell[Conf->nspell].word);
-	strncpy(Conf->Spell[Conf->nspell].p.flag, flag, 16);
+	strlcpy(Conf->Spell[Conf->nspell].p.flag, flag, 16);
 	Conf->nspell++;
 	return (0);
 }
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index b0db486..6a7a174 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -2723,7 +2723,7 @@ main(int argc, char *argv[])
 		fprintf(stderr, "%s", authwarning);
 
 	/* Get directory specification used to start this executable */
-	strcpy(bin_dir, argv[0]);
+	strlcpy(bin_dir, argv[0], sizeof(bin_dir));
 	get_parent_directory(bin_dir);
 
 	printf(_("\nSuccess. You can now start the database server using:\n\n"
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 4e89cd6..adfbcb4 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -1141,7 +1141,7 @@ parse_include(void)
 		yytext[i] = '\0';
 		memmove(yytext, yytext+1, strlen(yytext));
 	
-		strncpy(inc_file, yytext, sizeof(inc_file));
+		strlcpy(inc_file, yytext, sizeof(inc_file));
 		yyin = fopen(inc_file, "r");
 		if (!yyin)
 		{
diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
index bb0ac92..bd0f00c 100644
--- a/src/interfaces/libpq/fe-protocol2.c
+++ b/src/interfaces/libpq/fe-protocol2.c
@@ -442,7 +442,7 @@ pqParseInput2(PGconn *conn)
 						if (!conn->result)
 							return;
 					}
-					strncpy(conn->result->cmdStatus, conn->workBuffer.data,
+					strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
 							CMDSTATUS_LEN);
 					checkXactStatus(conn, conn->workBuffer.data);
 					conn->asyncStatus = PGASYNC_READY;
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index d1daf14..040550a 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -203,7 +203,7 @@ pqParseInput3(PGconn *conn)
 						if (!conn->result)
 							return;
 					}
-					strncpy(conn->result->cmdStatus, conn->workBuffer.data,
+					strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
 							CMDSTATUS_LEN);
 					conn->asyncStatus = PGASYNC_READY;
 					break;
diff --git a/src/port/exec.c b/src/port/exec.c
index 1fa2d5d..18bcb4a 100644
--- a/src/port/exec.c
+++ b/src/port/exec.c
@@ -86,7 +86,7 @@ validate_exec(const char *path)
 	if (strlen(path) >= strlen(".exe") &&
 		pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
 	{
-		strcpy(path_exe, path);
+		strlcpy(path_exe, path, sizeof(path_exe) - 4);
 		strcat(path_exe, ".exe");
 		path = path_exe;
 	}
@@ -343,7 +343,7 @@ resolve_symlinks(char *path)
 	}
 
 	/* must copy final component out of 'path' temporarily */
-	strcpy(link_buf, fname);
+	strlcpy(link_buf, fname, sizeof(link_buf));
 
 	if (!getcwd(path, MAXPGPATH))
 	{
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 49485ec..c635a65 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -299,7 +299,7 @@ identify_system_timezone(void)
 	}
 
 	/* Search for the best-matching timezone file */
-	strcpy(tmptzdir, pg_TZDIR());
+	strlcpy(tmptzdir, pg_TZDIR(), sizeof(tmptzdir));
 	bestscore = -1;
 	resultbuf[0] = '\0';
 	scan_available_timezones(tmptzdir, tmptzdir + strlen(tmptzdir) + 1,