Hi again! Sorry for crossposting, but I sent the initial post also to -bugs, because I did not get an answer on -odbc.
On 2004-05-11 12:03 +0200, Martin Pitt wrote: > I noticed Apache segfaulting when I feed a simple form with long inputs: > > [Tue May 4 11:32:10 2004] [notice] child pid 4084 exit signal Segmentation > fault (11) > > Such inputs are used by php function odbc_connect as username and password to > connect to a DSN using postgresql driver: > > $connection = @odbc_connect(DSN, $_POST['username'], $_POST['password']) > > The output of gdb is: > > (gdb) run -X -d apache > [...] > [Thread debugging using libthread_db enabled] > [...] > Program received signal SIGSEGV, Segmentation fault. > [Switching to Thread 1076569920 (LWP 832)] > 0x44c3d627 in SOCK_put_next_byte () from /usr/lib/postgresql/lib/psqlodbc.so > > Or: > [same stuff here] > 0x44c4c3d0 in strncpy_null () from /usr/lib/postgresql/lib/psqlodbc.so > > I suspect a security issue because playing around with long input strings of "A" > I've been able to trigger in Apache error.log this message: > > free(): invalid pointer 0x41414141! > > 0x41 is obviously one of my "A"... The problem is that make_string() in misc.c does not check whether the target buffer is big enough to hold the copied string. I added a bufsize parameter to make_string() and used it in all calls to it. I tried it with my php4 crash test script and now it works properly. The attached patch is for the current stable release 07.03.0200. Thanks a lot to Peter Eisentraut for pointing me at the problem origin. Unless you have a better idea it would be nice if you could apply the patch to the official sources and also include it in the next release. I will upload updated Debian packages for unstable and stable this afternoon (16:00 CEST) if nobody reports a problem or a better solution. Thanks in advance, Martin -- Martin Pitt Debian GNU/Linux Developer [EMAIL PROTECTED] [EMAIL PROTECTED] http://www.piware.de http://www.debian.org
Index: connection.c =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/connection.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 connection.c --- connection.c 22 Jan 2004 15:02:52 -0000 1.1.1.1 +++ connection.c 13 May 2004 08:47:22 -0000 @@ -107,7 +107,7 @@ ci = &conn->connInfo; - make_string(szDSN, cbDSN, ci->dsn); + make_string(szDSN, cbDSN, ci->dsn, sizeof(ci->dsn)); /* get the values for the DSN from the registry */ memcpy(&ci->drivers, &globals, sizeof(globals)); @@ -120,8 +120,8 @@ * override values from DSN info with UID and authStr(pwd) This only * occurs if the values are actually there. */ - make_string(szUID, cbUID, ci->username); - make_string(szAuthStr, cbAuthStr, ci->password); + make_string(szUID, cbUID, ci->username,sizeof(ci->username)); + make_string(szAuthStr, cbAuthStr, ci->password, sizeof(ci->password)); /* fill in any defaults */ getDSNdefaults(ci); Index: drvconn.c =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/drvconn.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 drvconn.c --- drvconn.c 22 Jan 2004 15:02:52 -0000 1.1.1.1 +++ drvconn.c 13 May 2004 08:47:22 -0000 @@ -112,7 +112,7 @@ return SQL_INVALID_HANDLE; } - make_string(szConnStrIn, cbConnStrIn, connStrIn); + make_string(szConnStrIn, cbConnStrIn, connStrIn, sizeof(connStrIn)); #ifdef FORCE_PASSWORD_DISPLAY mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn); Index: execute.c =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/execute.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 execute.c --- execute.c 22 Jan 2004 15:02:49 -0000 1.1.1.1 +++ execute.c 13 May 2004 08:47:22 -0000 @@ -101,7 +101,7 @@ if (!szSqlStr[0]) self->statement = strdup(""); else - self->statement = make_string(szSqlStr, cbSqlStr, NULL); + self->statement = make_string(szSqlStr, cbSqlStr, NULL, 0); if (!self->statement) { SC_set_error(self, STMT_NO_MEMORY_ERROR, "No memory available to store statement"); @@ -150,7 +150,7 @@ * keep a copy of the un-parametrized statement, in case they try to * execute this statement again */ - stmt->statement = make_string(szSqlStr, cbSqlStr, NULL); + stmt->statement = make_string(szSqlStr, cbSqlStr, NULL, 0); if (!stmt->statement) { SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "No memory available to store statement"); @@ -775,7 +775,7 @@ mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn); - ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL); + ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL, 0); if (!ptr) { CC_set_error(conn, CONN_NO_MEMORY_ERROR, "No memory available to store native sql string"); Index: info.c =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/info.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 info.c --- info.c 22 Jan 2004 15:02:50 -0000 1.1.1.1 +++ info.c 13 May 2004 08:47:23 -0000 @@ -1387,7 +1387,7 @@ show_views = FALSE; /* make_string mallocs memory */ - tableType = make_string(szTableType, cbTableType, NULL); + tableType = make_string(szTableType, cbTableType, NULL, 0); if (tableType) { strcpy(table_types, tableType); @@ -2555,7 +2555,7 @@ * only use the table name... the owner should be redundant, and we * never use qualifiers. */ - table_name = make_string(szTableName, cbTableName, NULL); + table_name = make_string(szTableName, cbTableName, NULL, 0); if (!table_name) { SC_set_error(stmt, STMT_INTERNAL_ERROR, "No table name passed to PGAPI_Statistics."); @@ -3009,7 +3009,7 @@ internal_asis_type = INTERNAL_ASIS_TYPE; #endif /* UNICODE_SUPPORT */ pktab[0] = '\0'; - make_string(szTableName, cbTableName, pktab); + make_string(szTableName, cbTableName, pktab, sizeof(pktab)); if (pktab[0] == '\0') { SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys."); @@ -3543,8 +3543,8 @@ schema_needed[0] = '\0'; schema_fetched[0] = '\0'; - make_string(szPkTableName, cbPkTableName, pk_table_needed); - make_string(szFkTableName, cbFkTableName, fk_table_needed); + make_string(szPkTableName, cbPkTableName, pk_table_needed, sizeof(pk_table_needed)); + make_string(szFkTableName, cbFkTableName, fk_table_needed, sizeof(fk_table_needed)); conn = SC_get_conn(stmt); #ifdef UNICODE_SUPPORT Index: misc.c =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/misc.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 misc.c --- misc.c 22 Jan 2004 15:02:50 -0000 1.1.1.1 +++ misc.c 13 May 2004 08:47:23 -0000 @@ -259,12 +259,13 @@ /*------ * Create a null terminated string (handling the SQL_NTS thing): * 1. If buf is supplied, place the string in there - * (assumes enough space) and return buf. - * 2. If buf is not supplied, malloc space and return this string + * (at most bufsize-1 bytes) and return buf. + * 2. If buf is not supplied, malloc space and return this string; + * (buflen is ignored in this case). *------ */ char * -make_string(const char *s, int len, char *buf) +make_string(const char *s, int len, char *buf, int bufsize) { int length; char *str; @@ -275,6 +276,8 @@ if (buf) { + if(length >= bufsize) + length = bufsize-1; strncpy_null(buf, s, length + 1); return buf; } Index: misc.h =================================================================== RCS file: /cvsroot/pkg-postgresql/psqlodbc/psqlodbc-07.03.0200/misc.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 misc.h --- misc.h 22 Jan 2004 15:02:50 -0000 1.1.1.1 +++ misc.h 13 May 2004 08:47:23 -0000 @@ -119,7 +119,7 @@ void remove_newlines(char *string); char *strncpy_null(char *dst, const char *src, int len); char *trim(char *string); -char *make_string(const char *s, int len, char *buf); +char *make_string(const char *s, int len, char *buf, int bufsize ); char *make_lstring_ifneeded(ConnectionClass *, const char *s, int len, BOOL); char *my_strcat(char *buf, const char *fmt, const char *s, int len); char *schema_strcat(char *buf, const char *fmt, const char *s, int len,
pgpbQaXkwQIwg.pgp
Description: PGP signature