Bug #51841 mysqld crash when loading plugin of different version
Submitted: 8 Mar 2010 19:44 Modified: 22 Sep 2010 6:33
Reporter: Sergei Golubchik Email Updates:
Status: Patch queued Impact on me:
None 
Category:MySQL Server: User-defined functions ( UDF ) Severity:S3 (Non-critical)
Version:5.1 OS:Any
Assigned to: Assigned Account CPU Architecture:Any
Tags: Contribution
Triage: Triaged: D1 (Critical)

[8 Mar 2010 19:44] Sergei Golubchik
Description:
MySQL supports loading of plugins even if the plugin API version does not match MYSQL_PLUGIN_INTERFACE_VERSION exactly, it is enough if the major version matches.

In this case MySQL copies the st_mysql_plugin structure from the plugin so in case it has a different size. But it does not copy the last all-zeros element of the plugin array and later crashes when iterating this allocated array, because it does not end with a zero element.

How to repeat:
build the server, increase MYSQL_PLUGIN_INTERFACE_VERSION by one, build ha_example.so, try to load it into the server with the original MYSQL_PLUGIN_INTERFACE_VERSION.

Suggested fix:
In sql_plugin.cc, plugin_dl_add() function:

-     my_malloc(i*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
+     my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));

this will take care of the bug.

Additionally, you can wrap the whole block (starts from the first "for (i= 0;" and ends with "sym= cur;") in "if (sizeof_st_plugin != sizeof(st_mysql_plugin))" to avoid unnecessary copying.
[9 Mar 2010 8:39] Sveta Smirnova
Thank you for the report.

I can not repeat described behavior if change MYSQL_PLUGIN_INTERFACE_VERSION to 0x0101, then run plugin.test What also should be done to repeat the problem?
[9 Mar 2010 10:17] Sergei Golubchik
make a typo in the plugin name. That is, try to load a non-existing plugin from an existing so library.
[9 Mar 2010 10:27] Sveta Smirnova
Thank you for the feedback.

Verified as described.

$bzr diff
=== modified file 'include/mysql/plugin.h'
--- include/mysql/plugin.h      2009-06-10 08:59:49 +0000
+++ include/mysql/plugin.h      2010-03-09 10:27:10 +0000
@@ -65,7 +65,7 @@
   Plugin API. Common for all plugin types.
 */
 
-#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0100
+#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
 
 /*
   The allowable types of plugins

=== modified file 'mysql-test/t/plugin.test'
--- mysql-test/t/plugin.test    2009-10-08 08:39:15 +0000
+++ mysql-test/t/plugin.test    2010-03-09 10:23:33 +0000
@@ -5,7 +5,7 @@
 DROP TABLE t1;
 
 --replace_regex /\.dll/.so/
-eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
+eval INSTALL PLUGIN exampre SONAME $HA_EXAMPLE_SO;
 --replace_regex /\.dll/.so/
 --error 1125
 eval INSTALL PLUGIN EXAMPLE SONAME $HA_EXAMPLE_SO;

With correct plugin version server just returns proper error.
[21 Sep 2010 20:48] 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/118747

3197 Mats Kindahl	2010-09-21
      BUG#51841: mysqld crash when loading plugin of different version
      
      In sql_plugin.cc there is a loop that counts the number of plugin
      structures by iterating the memory and finding a NULL in the info
      field, which indicates a zero row terminating the list of plugin
      structures. However, when copying the structures, the row containing
      zeroes are missed, causing crashes later when not finding the end
      of the list of plugins.
      
      This patch solves the problem by allocating memory for an extra row
      and zeroing out the memory. When copying, this will leave a row of
      zeroes at the end of the array of plugins, acting as a sentinel for
      the end of the list.
[21 Sep 2010 21:04] 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/118751

3087 Mats Kindahl	2010-09-21
      BUG#51841: mysqld crash when loading plugin of different version
      
      In sql_plugin.cc there is a loop that counts the number of plugin
      structures by iterating the memory and finding a NULL in the info
      field, which indicates a zero row terminating the list of plugin
      structures. However, when copying the structures, the row containing
      zeroes are missed, causing crashes later when not finding the end
      of the list of plugins.
      
      This patch solves the problem by allocating memory for an extra row
      and zeroing out the memory. When copying, this will leave a row of
      zeroes at the end of the array of plugins, acting as a sentinel for
      the end of the list.