First of all, this doesn't seem to be any sort of security vulnerability (not related to any stack overflow or any stack smashing etc.).It is something to do with parsing.
Also, not related to glob_buffer or it being empty as suggested above. (even in normal case it is like that).
if (!status.batch)
{
old_buffer= *buffer;
old_buffer.copy();
}
======
As you can see it explicitly checks for single quote and does some string filtering to finally append " help ' " and " ' " to it if does not have them already.
The problem lies here --
const char *server_cmd= buffer->ptr()
If the string already starts with single quote, server_cmd ends up with value of glob_buffer like this:
print server_cmd
$10 = 0x98d660 "Your MySQL connection id is 11\nServer version: 5.5.27-rel28.0-debug-log Built by raghavendra at Tue Aug 21 00:41:10 IST 2012\n"
and rest follows.
Interesting to observe that the argument has been marked __attribute__((unused)) but is still used.
This section
===
if (!status.batch)
{
old_buffer= *buffer;
old_buffer.copy();
}
======
is also suspicious (because of unused attribute) but *not* directly relevant to this bug. (For curious, old_buffer is used in com_edit when \e is invoked, however, after the fix(below) I checked and \e along with \h was working fine: something like
> select \h help 'contents' \e will copy select to $EDITOR's buffer
>>./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> help contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
Also, with the test case:
=============================
./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql> SELECT * FROM t1;
+----+-------+
| id | name |
+----+-------+
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
+----+-------+
3 rows in set (0.00 sec)
mysql> \q
Bye (origin/Percona-Server)~21:51-0
>>./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql>
mysql>
mysql>
mysql> help contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql>
===============================================================
Lastly, even without the patch, calling help 'contents' didn't eat up any additional rows as in the description (2 rows are deleted instead of 1).
First of all, this doesn't seem to be any sort of security vulnerability (not related to any stack overflow or any stack smashing etc.).It is something to do with parsing.
Also, not related to glob_buffer or it being empty as suggested above. (even in normal case it is like that).
The problem is in com_server_help:
static int com_server_ help(String *buffer __attribute_ _((unused) ), _((unused) ), char *help_arg)
char *line __attribute_
{
MYSQL_ROW cur;
const char *server_cmd= buffer->ptr();
char cmd_buf[100 + 1];
MYSQL_RES *result;
int error;
if (help_arg[0] != '\'') charset_ info,*end_ arg))
end_ arg--;
{
char *end_arg= strend(help_arg);
if(--end_arg)
{
while (my_isspace(
*++end_arg= '\0';
}
(void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
server_cmd= cmd_buf;
}
if (!status.batch) buffer. copy();
{
old_buffer= *buffer;
old_
}
======
As you can see it explicitly checks for single quote and does some string filtering to finally append " help ' " and " ' " to it if does not have them already.
The problem lies here --
const char *server_cmd= buffer->ptr()
If the string already starts with single quote, server_cmd ends up with value of glob_buffer like this:
print server_cmd rel28.0- debug-log Built by raghavendra at Tue Aug 21 00:41:10 IST 2012\n"
$10 = 0x98d660 "Your MySQL connection id is 11\nServer version: 5.5.27-
and rest follows.
Interesting to observe that the argument has been marked __attribute_ _((unused) ) but is still used.
This section buffer. copy();
===
if (!status.batch)
{
old_buffer= *buffer;
old_
}
======
is also suspicious (because of unused attribute) but *not* directly relevant to this bug. (For curious, old_buffer is used in com_edit when \e is invoked, however, after the fix(below) I checked and \e along with \h was working fine: something like
> select \h help 'contents' \e will copy select to $EDITOR's buffer
Anyways, here is the fix:
=== modified file 'Percona- Server/ client/ mysql.cc' Server/ client/ mysql.cc 2012-08-07 06:10:00 +0000 Server/ client/ mysql.cc 2012-09-05 16:14:14 +0000
char *line __attribute_ _((unused) ), char *help_arg)
*++end_ arg= '\0';
--- Percona-
+++ Percona-
@@ -2827,7 +2827,7 @@
{
MYSQL_ROW cur;
- const char *server_cmd= buffer->ptr();
+ const char *server_cmd= help_arg;
char cmd_buf[100 + 1];
MYSQL_RES *result;
int error;
@@ -2842,8 +2842,10 @@
}
(void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
- server_cmd= cmd_buf;
+ } else {
+ (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help ", help_arg, NullS);
}
+ server_cmd= cmd_buf;
After the fix:
>>./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> help contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
Also, with the test case: ======= ======= ======= =
=======
./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create table t1 (`id` int(11) auto_increment, `name` varchar(255), primary key (`id`));
ERROR 1046 (3D000): No database selected
mysql> use test;
Database changed
mysql> drop table t1;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t1 (`id` int(11) auto_increment, `name` varchar(255), primary key (`id`));
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1(`name`) VALUES ('test1' ),('test2' ),('test3' ),('test4' );
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM t1;
+----+-------+
| id | name |
+----+-------+
| 1 | test1 |
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
+----+-------+
4 rows in set (0.00 sec)
mysql> DELETE FROM t1 LIMIT 1;
Query OK, 1 row affected (0.00 sec)
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql> SELECT * FROM t1;
+----+-------+
| id | name |
+----+-------+
| 2 | test2 |
| 3 | test3 |
| 4 | test4 |
+----+-------+
3 rows in set (0.00 sec)
mysql> \q
(origin/ Percona- Server) ~21:51- 0
Bye
>>./client/mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 5.5.27-log Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> help 'contents'
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql>
mysql>
mysql>
mysql> help contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation
Data Types
Functions
Functions and Modifiers for Use with GROUP BY
Geographic Features
Help Metadata
Language Structure
Plugins
Procedures
Table Maintenance
Transactions
User-Defined Functions
Utility
mysql>
======= ======= ======= ======= ======= ======= ======= ======= =======
Lastly, even without the patch, calling help 'contents' didn't eat up any additional rows as in the description (2 rows are deleted instead of 1).