Bug #5413 mysqlcheck segfaults when user has to few permissions
Submitted: 4 Sep 2004 20:19 Modified: 6 Sep 2004 22:51
Reporter: Christian Hammers (Silver Quality Contributor) (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:4.0.20 OS:Linux (Debian GNU/Linux)
Assigned to: Sergei Golubchik CPU Architecture:Any

[4 Sep 2004 20:19] Christian Hammers
Description:
When mysqlcheck is called by user (via defaults-extra-file) that has not enough
permissions it silently segfaults.

Note: I spotted this segfault while playing around with old 3.23 mysql privilege tables and the new 4.0 server but using fix_privilege_table is only recommended and not forced so that should be no excuse.

How to repeat:
$ strace mysqlcheck --defaults-extra-file=/etc/mysql/debian.cnf --fast mysql
...
write(3, "\f\0\0\0\3SHOW TABLES", 16)   = 16
read(3, "K\0\0\1", 4)                   = 4
read(3, "\377\24\4Access denied for user: \'debi"..., 75) = 75
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

$ cat /etc/mysql/debian.cnf
# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = debian-sys-maint
password = cuDjjMOAQSzvKjg5

mysql> SELECT * FROM user WHERE user="debian-sys-maint"\G
*************************** 1. row ***************************
           Host: localhost
           User: debian-sys-maint
       Password: 17f1b69012d86058
    Select_priv: N
    Insert_priv: N
    Update_priv: N
    Delete_priv: N
    Create_priv: N
      Drop_priv: N
    Reload_priv: Y
  Shutdown_priv: Y
   Process_priv: N
      File_priv: N
     Grant_priv: N
References_priv: N
     Index_priv: N
     Alter_priv: N
1 row in set (0.00 sec)

Suggested fix:
I spotted this segfault while playing around so maybe my privs are nonsense but it
should definetly print an error message and exit sanely.
[6 Sep 2004 18:41] MySQL Verification Team
I wasn't able to repeat on my Debian box and MySQL stuff built from latest 
BK source: 
 
write(2, ": ", 2: )                       = 2 
write(2, "Got error: 1044: Access denied f"..., 107Got error: 1044: Access denied for 
user: 'miguel@localhost' to database 'mysql' when selecting the database) = 107 
write(2, "\n", 1 
)                       = 1 
write(3, "\1\0\0\0\1", 5)               = 5 
shutdown(3, 2 /* send and receive */)   = 0 
close(3)                                = 0 
exit_group(2)                           = ?
[6 Sep 2004 19:41] Christian Hammers
I tracked the bug down to the following line in client/mysqlcheck.c line 412 which contains a bug:

   static int process_all_tables_in_db(char *database)
   ...
   if (!(mysql_query(sock, "SHOW TABLES") ||
        (res = mysql_store_result(sock))))
     return 1;

The mysql_query() function returns 0 on success, and "-1" in my example case below.
The if statement should therefore test for
   if (!(mysqlcheck()==0 || ... )
or easier to verify maybe as
   if ( (mysql_query(sock, "SHOW TABLES") != 0 ) ||
        ((res = mysql_store_result(sock)) == NULL)) {
      return 1;
   }

*But:*
All this makes no sense when the return value of this function is passed a long for a couple of times in the function chain but then ultimately discarded in main() which does not even does exit(1)!

To reproduce this bug use the following user:
INSERT INTO 
  user (host,user,password, create_tmp_table_priv)
VALUES   
  ("localhost","bug","","Y");

(strangely it behaves differently if those the one priv is also set to "N"...)
[6 Sep 2004 22:51] Sergei Golubchik
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

fixed in 4.0.21