Neil Conway <[EMAIL PROTECTED]> writes:
> Sir Mordred The Traitor <[EMAIL PROTECTED]> writes:
> > There exists a buffer overflow in a SET TIME ZONE command, that
> > allows an attacker to execute malicious code.
> 
> Here's a patch for the problem. I also fixed some other potential
> buffer overruns nearby, and added a little paranoia to another routine
> that uses a statically sized buffer.

The handling of the TZ environmental variable is subject to a buffer
overrun. To see the problem, try:

export 
TZ=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
postmaster -D /foo/bar&
psql

You get:

NOTICE:  Buffer Leak: [26914] (freeNext=0, freePrev=0, rel=0/0, blockNum=0, flags=0x0, 
refcount=0 1)
[ lots more NOTICEs ]
psql: server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.

A revised patch is attached that fixes the problem.

Cheers,

Neil

-- 
Neil Conway <[EMAIL PROTECTED]> || PGP Key ID: DB3C29FC
Index: src/backend/commands/variable.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/commands/variable.c,v
retrieving revision 1.57
diff -c -r1.57 variable.c
*** src/backend/commands/variable.c	9 Dec 2001 04:37:50 -0000	1.57
--- src/backend/commands/variable.c	21 Aug 2002 17:32:27 -0000
***************
*** 274,299 ****
  show_datestyle(void)
  {
  	char		buf[64];
  
- 	strcpy(buf, "DateStyle is ");
  	switch (DateStyle)
  	{
  		case USE_ISO_DATES:
! 			strcat(buf, "ISO");
  			break;
  		case USE_SQL_DATES:
! 			strcat(buf, "SQL");
  			break;
  		case USE_GERMAN_DATES:
! 			strcat(buf, "German");
  			break;
  		default:
! 			strcat(buf, "Postgres");
  			break;
! 	};
! 	strcat(buf, " with ");
! 	strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)"));
! 	strcat(buf, " conventions");
  
  	elog(NOTICE, buf, NULL);
  
--- 274,299 ----
  show_datestyle(void)
  {
  	char		buf[64];
+ 	char	   *dstyle;
  
  	switch (DateStyle)
  	{
  		case USE_ISO_DATES:
! 			dstyle = "ISO";
  			break;
  		case USE_SQL_DATES:
! 			dstyle = "SQL";
  			break;
  		case USE_GERMAN_DATES:
! 			dstyle = "German";
  			break;
  		default:
! 			dstyle = "Postgres";
  			break;
! 	}
! 
! 	snprintf(buf, sizeof(buf), "DateStyle is %s with %s conventions",
! 			 dstyle, EuroDates ? "European" : "US (NonEuropean");
  
  	elog(NOTICE, buf, NULL);
  
***************
*** 442,456 ****
  				{
  					/* found something? then save it for later */
  					if ((defaultTZ = getenv("TZ")) != NULL)
! 						strcpy(TZvalue, defaultTZ);
  
  					/* found nothing so mark with an invalid pointer */
  					else
  						defaultTZ = (char *) -1;
  				}
  
! 				strcpy(tzbuf, "TZ=");
! 				strcat(tzbuf, tok);
  				if (putenv(tzbuf) != 0)
  					elog(ERROR, "Unable to set TZ environment variable to %s", tok);
  
--- 442,455 ----
  				{
  					/* found something? then save it for later */
  					if ((defaultTZ = getenv("TZ")) != NULL)
! 						strncpy(TZvalue, defaultTZ, sizeof(TZvalue));
  
  					/* found nothing so mark with an invalid pointer */
  					else
  						defaultTZ = (char *) -1;
  				}
  
! 				snprintf(tzbuf, sizeof(tzbuf), "TZ=%s", tok);
  				if (putenv(tzbuf) != 0)
  					elog(ERROR, "Unable to set TZ environment variable to %s", tok);
  
***************
*** 513,520 ****
  	/* time zone was set and original explicit time zone available? */
  	else if (defaultTZ != (char *) -1)
  	{
! 		strcpy(tzbuf, "TZ=");
! 		strcat(tzbuf, TZvalue);
  		if (putenv(tzbuf) != 0)
  			elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
  		tzset();
--- 512,518 ----
  	/* time zone was set and original explicit time zone available? */
  	else if (defaultTZ != (char *) -1)
  	{
! 		snprintf(tzbuf, sizeof(tzbuf), "TZ=%s", TZvalue);
  		if (putenv(tzbuf) != 0)
  			elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
  		tzset();
Index: src/backend/utils/adt/nabstime.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/nabstime.c,v
retrieving revision 1.91
diff -c -r1.91 nabstime.c
*** src/backend/utils/adt/nabstime.c	25 Oct 2001 05:49:44 -0000	1.91
--- src/backend/utils/adt/nabstime.c	21 Aug 2002 17:32:27 -0000
***************
*** 145,165 ****
  		 * XXX is there a better way to get local timezone string w/o
  		 * tzname? - tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN, "%Z", tm);
  #endif
  
  		/*
  		 * XXX FreeBSD man pages indicate that this should work - thomas
  		 * 1998-12-12
  		 */
! 		strcpy(CTZName, tm->tm_zone);
  
  #elif defined(HAVE_INT_TIMEZONE)
  		tm = localtime(&now);
  
  		CDayLight = tm->tm_isdst;
  		CTimeZone = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
! 		strcpy(CTZName, tzname[tm->tm_isdst]);
  #else							/* neither HAVE_TM_ZONE nor
  								 * HAVE_INT_TIMEZONE */
  		CTimeZone = tb.timezone * 60;
--- 145,165 ----
  		 * XXX is there a better way to get local timezone string w/o
  		 * tzname? - tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN + 1, "%Z", tm);
  #endif
  
  		/*
  		 * XXX FreeBSD man pages indicate that this should work - thomas
  		 * 1998-12-12
  		 */
! 		StrNCpy(CTZName, tm->tm_zone, MAXTZLEN + 1);
  
  #elif defined(HAVE_INT_TIMEZONE)
  		tm = localtime(&now);
  
  		CDayLight = tm->tm_isdst;
  		CTimeZone = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
! 		StrNCpy(CTZName, tzname[tm->tm_isdst], MAXTZLEN + 1);
  #else							/* neither HAVE_TM_ZONE nor
  								 * HAVE_INT_TIMEZONE */
  		CTimeZone = tb.timezone * 60;
***************
*** 169,175 ****
  		 * XXX does this work to get the local timezone string in V7? -
  		 * tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
  #endif
  	}
  
--- 169,175 ----
  		 * XXX does this work to get the local timezone string in V7? -
  		 * tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN + 1, "%Z", localtime(&now));
  #endif
  	}
  
***************
*** 227,247 ****
  		 * XXX is there a better way to get local timezone string w/o
  		 * tzname? - tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN, "%Z", tm);
  #endif
  
  		/*
  		 * XXX FreeBSD man pages indicate that this should work - thomas
  		 * 1998-12-12
  		 */
! 		strcpy(CTZName, tm->tm_zone);
  
  #elif defined(HAVE_INT_TIMEZONE)
  		tm = localtime(&now);
  
  		CDayLight = tm->tm_isdst;
  		CTimeZone = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
! 		strcpy(CTZName, tzname[tm->tm_isdst]);
  #else							/* neither HAVE_TM_ZONE nor
  								 * HAVE_INT_TIMEZONE */
  		CTimeZone = tb.timezone * 60;
--- 227,247 ----
  		 * XXX is there a better way to get local timezone string w/o
  		 * tzname? - tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN + 1, "%Z", tm);
  #endif
  
  		/*
  		 * XXX FreeBSD man pages indicate that this should work - thomas
  		 * 1998-12-12
  		 */
! 		StrNCpy(CTZName, tm->tm_zone, MAXTZLEN + 1);
  
  #elif defined(HAVE_INT_TIMEZONE)
  		tm = localtime(&now);
  
  		CDayLight = tm->tm_isdst;
  		CTimeZone = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
! 		StrNCpy(CTZName, tzname[tm->tm_isdst], MAXTZLEN + 1);
  #else							/* neither HAVE_TM_ZONE nor
  								 * HAVE_INT_TIMEZONE */
  		CTimeZone = tb.timezone * 60;
***************
*** 251,257 ****
  		 * XXX does this work to get the local timezone string in V7? -
  		 * tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
  #endif
  	};
  
--- 251,257 ----
  		 * XXX does this work to get the local timezone string in V7? -
  		 * tgl 97/03/18
  		 */
! 		strftime(CTZName, MAXTZLEN + 1, "%Z", localtime(&now));
  #endif
  	};
  

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly

Reply via email to