Bug #36149 Read buffer overflow in srv0start.c found during "make test"
Submitted: 16 Apr 2008 20:14 Modified: 16 Jan 21:23
Reporter: Michael Zhivich
Status: Closed
Category:Server: InnoDB Severity:S3 (Non-critical)
Version:5.0.51a, 5.1 OS:Linux (Generic, kernel 2.6.18, gcc 4.1.2)
Assigned to: Timothy Smith Target Version:5.0+
Tags: innodb, heap overflow, make test
Triage: Triaged: D2 (Serious)

[16 Apr 2008 20:14] Michael Zhivich
Description:
While testing a research buffer overflow detection tool, I encountered a buffer overflow
in MySQL startup code.

The overflow occurs in srv_parse_data_file_paths_and_sizes() in innobase/srv/srv0start.c,
line 187.  The call to memcmp() in this line will overflow str, as it is defined (by
default) in innobase_init() in sql/ha_innodb.cc, line 1280.

Upon entry to srv_parse_data_file_paths_and_sizes(), str has value
"ibdata1:10M:autoextend".  At line 185 in srv0start.c, str pointer is adjusted past the
end of that string; thus, a call to memcmp() at this point is an overflow.

It looks like you're searching for an extra parameter (e.g. ":max:"), that's not present
in str with its default definition.

How to repeat:
Using the source tarball for MySQL 5.0.51a:

$ ./configure --with-debug
$ make
$ cd mysql-test
$ ./mysql-test-run --gdb

Create a breakpoint at innobase_init() and srv_Parse_data_file_paths_and_sizes(). Restart
the application in gdb and observe changes to str parameter.
[28 Apr 2008 17:30] Susanne Ebrecht
Verified as described with 5.0 bk source.
[28 Apr 2008 18:35] Michael Zhivich
Suggested fix:

In srv_parse_data_file_paths_and_sizes(), add a test for null-terminator before looking
for ":max:".

1. Change srv0start.c, line 187
- if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+ if ((*str != '\0') && (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {

2. Change srv0start.c, line 297 similarly
- if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+ if ((*str != '\0') && (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
[28 May 2008 10:32] Vasil Dimov
I will handle this.
[28 May 2008 18:41] Vasil Dimov
Michael,

Thank you for reporting this, I have committed the following patch:

--- cut ---
Index: srv/srv0start.c
===================================================================
--- srv/srv0start.c	(revision 2483)
+++ srv/srv0start.c	(revision 2484)
@@ -177,17 +177,17 @@ srv_parse_data_file_paths_and_sizes(
 		        size = size * 1024;
 			str++;
 		} else {
 		        str++;
 		}
 
-	        if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
+		if (0 == strncmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
 
 			str += (sizeof ":autoextend") - 1;
 
-	        	if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+			if (0 == strncmp(str, ":max:", (sizeof ":max:") - 1)) {
 
 				str += (sizeof ":max:") - 1;
 
 				size = strtoul(str, &endp, 10);
 
 				str = endp;
@@ -285,19 +285,19 @@ srv_parse_data_file_paths_and_sizes(
 		        str++;
 		}
 
 		(*data_file_names)[i] = path;
 		(*data_file_sizes)[i] = size;
 
-	        if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
+		if (0 == strncmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
 
 			*is_auto_extending = TRUE;
 
 			str += (sizeof ":autoextend") - 1;
 
-	        	if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+			if (0 == strncmp(str, ":max:", (sizeof ":max:") - 1)) {
 
 				str += (sizeof ":max:") - 1;
 
 				size = strtoul(str, &endp, 10);
 
 				str = endp;

--- cut ---
[25 Jun 2008 0:10] Calvin Sun
Merged into 6.0.6-alpha, according to Tim. But the patch has not been pushed into 5.0, 5.1
yet.
[14 Jul 2008 21:10] Paul DuBois
What was the bug here? Can you suggest a sentence for the changelog entry? Thanks.
[15 Jul 2008 9:38] Vasil Dimov
ChangeLog entry:

A potential read past end of the string has been fixed in parsing the value of the
--innodb-data-file-path option.
[15 Jul 2008 21:49] Paul DuBois
Noted in 6.0.6 changelog.

A read past the end of the string could occur while parsing the value
of the --innodb-data-file-path option.

Setting report to Patch queued pending push of fix into 5.1.x.
[17 Dec 2008 13:08] Valeriy Kravchuk
Bug #41527 was marked as a duplicate of this one.
[24 Dec 2008 23:02] Nitin Garg
I am also facing the same issue. Mysqld 5.1.30 keeps crashing on start. Is there any
workaround for the issue? From the history it seems that the bug has been around for
quite some time now and the patches have been pushed to 6.0 branch but not to 5.0.x and
5.1 branches, is there a reason for that? My error log is as follows
-----------------------------------------------------
081225  3:24:11 - mysqld got exception 0xc0000005 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help diagnose
the problem, but since we have already crashed, something is definitely wrong
and this may fail.

key_buffer_size=20971520
read_buffer_size=131072
max_used_connections=0
max_threads=160
threads_connected=0
It is possible that mysqld could use up to 
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 82930 K
bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

thd: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
006B8853    mysqld.exe!srv_parse_data_file_paths_and_sizes()[srv0start.c:211]
006A7E18    mysqld.exe!innobase_init()[ha_innodb.cc:1536]
00442748    mysqld.exe!ha_initialize_handlerton()[handler.cc:434]
00561253    mysqld.exe!plugin_initialize()[sql_plugin.cc:1002]
00565AE5    mysqld.exe!plugin_init()[sql_plugin.cc:1209]
004CE1B4    mysqld.exe!init_server_components()[mysqld.cc:3831]
004CE8C6    mysqld.exe!win_main()[mysqld.cc:4267]
004CECDB    mysqld.exe!mysql_service()[mysqld.cc:4439]
00724593    mysqld.exe!_callthreadstart()[thread.c:293]
0072462C    mysqld.exe!_threadstart()[thread.c:275]
7C80B683    kernel32.dll!GetModuleFileNameA()
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
[24 Dec 2008 23:21] Warren Ashcroft
To work around the issue I had to remove all innodb settings/variables from my.ini.
[25 Dec 2008 0:09] Nitin Garg
Thanks Warren, that was a life saver.
[6 Jan 21:20] Sönke Brecht
Following 2 workarounds work independently of each other for me:

 * Installing ATI Control Panel Version 5-5_xp-2k_cp.
 * as well as running mysqld from console (cmd)

btw: What was the reason for not patching 5.x branches?

HTH

Sönke
[16 Jan 21:09] Timothy Smith
Docs,

This was pushed now in 5.0 & 5.1, too.  Will be in 5.0.76 and 5.1.31.

Tim
[16 Jan 21:23] Paul DuBois
Noted in 5.0.76, 5.1.31 changelogs.
[4 Feb 21:59] Sveta Smirnova
There is bug #42578 which looks like duplicate.