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