| Bug #28934 | server crash when receiving malformed com_execute packets | ||
|---|---|---|---|
| Submitted: | 6 Jun 2007 20:38 | Modified: | 18 Jun 2007 15:35 |
| Reporter: | Shane Bester (Platinum Quality Contributor) | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Prepared statements | Severity: | S1 (Critical) |
| Version: | 5.0 | OS: | Any |
| Assigned to: | Georgi Kodinov | CPU Architecture: | Any |
| Tags: | crash, DoS, prepared statements | ||
[6 Jun 2007 20:38]
MySQL Verification Team
since you cannot disable prepared statements on the server, this bug can be exploited fairly easily.
[6 Jun 2007 21:10]
MySQL Verification Team
on 5.0.42 and 5.0.38-debug on windows, the server asserted with this stack trace: mysqld-debug.exe!_NMSG_WRITE(int rterrnum=10) mysqld-debug.exe!abort mysqld-debug.exe!_assert mysqld-debug.exe!Item_param::query_val_str mysqld-debug.exe!insert_params_withlog mysqld-debug.exe!mysql_stmt_execute mysqld-debug.exe!dispatch_command mysqld-debug.exe!do_command mysqld-debug.exe!handle_one_connection mysqld-debug.exe!pthread_start mysqld-debug.exe!_threadstart kernel32.dll!BaseThreadInitThunk Version: '5.0.38-enterprise-gpl-debug-log' socket: '' port: 3306 MySQL Enterprise Server - Debug (GPL) Assertion failed: 0, file .\item.cpp, line 2823
[6 Jun 2007 21:20]
MySQL Verification Team
The above crash happens when the general/binary/slow logs are enabled. I doubt the problem is limited to only that scope though.
[8 Jun 2007 14:22]
MySQL Verification Team
new testcase simply specifies random types for parameters. Look at this code: #ifdef MANGLE_TYPES ptr+=int_to_buff(ptr,2,rand()%254); //param is any type! Causes crashes/out of memory for server and errors like this: Version: '5.0.42-enterprise-gpl-debug-log' socket: '' port: 3306 MySQL Enterprise Server - Debug (GPL) 070608 16:15:49 [ERROR] mysqld-debug: Out of memory at line 51, '.\sql_string.cc' 070608 16:15:49 [ERROR] mysqld-debug: needed -654311344 byte (3555329k), memory in use: 8635822 bytes (8434k) Assertion failed: 0, file .\item.cc, line 2826
[11 Jun 2007 19:53]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/28522 ChangeSet@1.2529, 2007-06-11 22:53:06+03:00, gkodinov@magare.gmz +2 -0 Bug #28934: server crash when receiving malformed com_execute packets Sometimes a parameter slot may not get a value because of the protocol data being plain wrong. Such cases should be detected and handled by returning an error. Fixed by checking data stream constraints where possible (like maximum length) and reacting to the case where a value cannot be constructed.
[12 Jun 2007 8:02]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/28561 ChangeSet@1.2529, 2007-06-12 11:02:34+03:00, gkodinov@magare.gmz +2 -0 Bug #28934: server crash when receiving malformed com_execute packets Sometimes a parameter slot may not get a value because of the protocol data being plain wrong. Such cases should be detected and handled by returning an error. Fixed by checking data stream constraints where possible (like maximum length) and reacting to the case where a value cannot be constructed.
[14 Jun 2007 19:00]
Bugs System
Pushed into 5.1.20-beta
[14 Jun 2007 19:00]
Bugs System
Pushed into 5.0.44
[18 Jun 2007 15:35]
Paul DuBois
Noted in 5.0.44, 5.1.20 changelogs.

Description: If a program that binds X parameters to a prepared statement handle somehow changes stmt->param_count to be some different to X, then mysql_stmt_execute can crash the client or server. Mostly, a C/C++ client would crash, but not always. Server crash is easy to get when a client doesn't crash, or is JDBC or not C api based for example. In a case where the server crashed, I enabled the general query log to examine the query and it's parameters: 2 Connect root@ as anonymous on test 2 Query drop table if exists t1 2 Query create table t1(id int) 2 Query insert into t1 values (1),(2),(3),(4),(5) 2 Prepare [1] select * from t1 where id in(?,?,?,?, ?) 2 Execute [1] select * from t1 where id in(,,,0, 0) 2 Quit Notice the Execute has not correctly been run. I'll get a stack trace from a server later and upload it. How to repeat: I'll upload a complete testcase later, but for now see the below code snippet which shows us the concept: #define SELECT1 "select * from t1 where id in(?,?,?,?,?)" MYSQL_BIND bind[5]; stmt= mysql_stmt_init(conn); res= mysql_stmt_prepare(stmt, SELECT1, (unsigned long)strlen(SELECT1)); memset(&bind, 0, sizeof(bind)); for(cnt=0;cnt<5;cnt++) { bind[cnt].buffer_type=MYSQL_TYPE_LONG; bind[cnt].buffer=(char*)&cnt; bind[cnt].buffer_length=0; } mysql_stmt_bind_param(stmt, bind); //now change the number of bound parameters the server thinks it needs!! stmt->param_count=2; //this can crash client or server! mysql_stmt_execute(stmt); Suggested fix: fix the protocol?