Description:
If a INFORMATION_SCHEMA plugin's init() function fails (returns 1),
then an attempt is made to free schema_table twice during the
INSTALL PLUGIN command.
This is the backtrace:
Program received signal SIGABRT, Aborted.
0x00000008012ed32c in thr_kill () at thr_kill.S:2
2 RSYSCALL(thr_kill)
Current language: auto; currently asm
(gdb) bt
#0 0x00000008012ed32c in thr_kill () at thr_kill.S:2
#1 0x0000000800d4eabe in _thr_send_sig (thread=0xb06600, sig=6)
at /usr/src/lib/libthr/thread/thr_kern.c:92
#2 0x0000000800d4b468 in _raise (sig=6) at /usr/src/lib/libthr/thread/thr_sig.c:178
#3 0x00000008013ba003 in abort () at /usr/src/lib/libc/stdlib/abort.c:65
#4 0x0000000801395711 in __assert (func=Could not find the frame base for "__assert".
) at /usr/src/lib/libc/gen/assert.c:54
#5 0x0000000801319186 in arena_run_reg_dalloc (run=0x150b000, bin=0xab6df8,
ptr=0x150b140, size=64) at /usr/src/lib/libc/stdlib/malloc.c:2197
#6 0x000000080131b91f in arena_dalloc_small (arena=0xab6b48, chunk=0x1500000,
ptr=0x150b140, pageind=11, mapelm=0 '\0') at /usr/src/lib/libc/stdlib/malloc.c:3228
#7 0x000000080131bcb6 in arena_dalloc (arena=0xab6b48, chunk=0x1500000, ptr=0x150b140)
at /usr/src/lib/libc/stdlib/malloc.c:3325
#8 0x000000080131bd78 in idalloc (ptr=0x150b140)
at /usr/src/lib/libc/stdlib/malloc.c:3342
#9 0x000000080131ea2a in free (ptr=0x150b140) at /usr/src/lib/libc/stdlib/malloc.c:4679
#10 0x00000000007d85bc in my_no_flags_free (ptr=0x150b140) at my_malloc.c:59
#11 0x00000000006edb1c in finalize_schema_table (plugin=0xba2268) at sql_show.cc:6662
#12 0x000000000075a605 in plugin_deinitialize (plugin=0xba2268, ref_check=true)
at sql_plugin.cc:815
#13 0x000000000075a79e in reap_plugins () at sql_plugin.cc:903
#14 0x000000000075bf65 in mysql_install_plugin (thd=0x161a000, name=0x161c040,
dl=0x161c050) at sql_plugin.cc:1680
#15 0x00000000005d479a in mysql_execute_command (thd=0x161a000) at sql_parse.cc:4575
#16 0x00000000005d4d32 in mysql_parse (thd=0x161a000,
inBuf=0x1522010 "install plugin innodb_trx soname 'ha_innodb.so'", length=47,
found_semicolon=0x7fffffbbddc0) at sql_parse.cc:5630
#17 0x00000000005d5944 in dispatch_command (command=COM_QUERY, thd=0x161a000,
packet=0x1630001 "install plugin innodb_trx soname 'ha_innodb.so'",
packet_length=47) at sql_parse.cc:1121
#18 0x00000000005d6a6f in do_command (thd=0x161a000) at sql_parse.cc:781
#19 0x00000000005c68cc in handle_one_connection (arg=0x161a000) at sql_connect.cc:1115
#20 0x0000000800d48b48 in thread_start (curthread=0xb06600)
at /usr/src/lib/libthr/thread/thr_create.c:256
#21 0x0000000000000000 in ?? ()
The execution path is the following:
sql/sql_plugin.cc:1626: mysql_install_plugin()
sql/sql_plugin.cc:1657: plugin_initialize()
sql/sql_plugin.cc:1002: initialize_schema_table()
sql/sql_show.cc:6617: schema_table is allocated
sql/sql_show.cc:6621: plugin->data= schema_table
sql/sql_show.cc:6632: plugin->plugin->init() is called, assume it returns 1
sql/sql_show.cc:6636: goto err
sql/sql_show.cc:6645: my_free(schema_table, MYF(0))
sql/sql_plugin.cc:1006: goto err
sql/sql_plugin.cc:1661: goto deinit
sql/sql_plugin.cc:1661: reap_plugins()
sql/sql_plugin.cc:903: plugin_deinitialize()
sql/sql_plugin.cc:815: finalize_schema_table()
sql/sql_show.cc:6651: ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data
sql/sql_show.cc:6662: my_free(schema_table, MYF(0)) <-- oops
This bug does not immediately result in a crash on Linux (i.e. it
survives the double free) and on FreeBSD with standard libc it crashes
after one more INSTALL/UNINSTALL command. I had to remove
"#define MALLOC_PRODUCTION" from /usr/src/lib/libc/stdlib/malloc.c in
order to catch this on time. So it may be hard to reproduce but reading
the above execution path and the code makes the bug obvious.
I confirm that the attached patch fixes this bug. The second free() is
not attampted if schema_table (plugin->data) is NULL.
How to repeat:
Have a INFORMATION_SCHEMA plugin whose init() function returns 1 and try to install with
with INSTALL PLUGIN foo SONAME 'foo.so'
Suggested fix:
--- sql/sql_show.cc.orig 2008-04-29 17:12:12.000000000 +0300
+++ sql/sql_show.cc 2008-04-29 17:00:53.000000000 +0300
@@ -6640,12 +6640,13 @@ int initialize_schema_table(st_plugin_in
schema_table->table_name= plugin->name.str;
}
DBUG_RETURN(0);
err:
my_free(schema_table, MYF(0));
+ plugin->data = NULL;
DBUG_RETURN(1);
}
int finalize_schema_table(st_plugin_int *plugin)
{
ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
Description: If a INFORMATION_SCHEMA plugin's init() function fails (returns 1), then an attempt is made to free schema_table twice during the INSTALL PLUGIN command. This is the backtrace: Program received signal SIGABRT, Aborted. 0x00000008012ed32c in thr_kill () at thr_kill.S:2 2 RSYSCALL(thr_kill) Current language: auto; currently asm (gdb) bt #0 0x00000008012ed32c in thr_kill () at thr_kill.S:2 #1 0x0000000800d4eabe in _thr_send_sig (thread=0xb06600, sig=6) at /usr/src/lib/libthr/thread/thr_kern.c:92 #2 0x0000000800d4b468 in _raise (sig=6) at /usr/src/lib/libthr/thread/thr_sig.c:178 #3 0x00000008013ba003 in abort () at /usr/src/lib/libc/stdlib/abort.c:65 #4 0x0000000801395711 in __assert (func=Could not find the frame base for "__assert". ) at /usr/src/lib/libc/gen/assert.c:54 #5 0x0000000801319186 in arena_run_reg_dalloc (run=0x150b000, bin=0xab6df8, ptr=0x150b140, size=64) at /usr/src/lib/libc/stdlib/malloc.c:2197 #6 0x000000080131b91f in arena_dalloc_small (arena=0xab6b48, chunk=0x1500000, ptr=0x150b140, pageind=11, mapelm=0 '\0') at /usr/src/lib/libc/stdlib/malloc.c:3228 #7 0x000000080131bcb6 in arena_dalloc (arena=0xab6b48, chunk=0x1500000, ptr=0x150b140) at /usr/src/lib/libc/stdlib/malloc.c:3325 #8 0x000000080131bd78 in idalloc (ptr=0x150b140) at /usr/src/lib/libc/stdlib/malloc.c:3342 #9 0x000000080131ea2a in free (ptr=0x150b140) at /usr/src/lib/libc/stdlib/malloc.c:4679 #10 0x00000000007d85bc in my_no_flags_free (ptr=0x150b140) at my_malloc.c:59 #11 0x00000000006edb1c in finalize_schema_table (plugin=0xba2268) at sql_show.cc:6662 #12 0x000000000075a605 in plugin_deinitialize (plugin=0xba2268, ref_check=true) at sql_plugin.cc:815 #13 0x000000000075a79e in reap_plugins () at sql_plugin.cc:903 #14 0x000000000075bf65 in mysql_install_plugin (thd=0x161a000, name=0x161c040, dl=0x161c050) at sql_plugin.cc:1680 #15 0x00000000005d479a in mysql_execute_command (thd=0x161a000) at sql_parse.cc:4575 #16 0x00000000005d4d32 in mysql_parse (thd=0x161a000, inBuf=0x1522010 "install plugin innodb_trx soname 'ha_innodb.so'", length=47, found_semicolon=0x7fffffbbddc0) at sql_parse.cc:5630 #17 0x00000000005d5944 in dispatch_command (command=COM_QUERY, thd=0x161a000, packet=0x1630001 "install plugin innodb_trx soname 'ha_innodb.so'", packet_length=47) at sql_parse.cc:1121 #18 0x00000000005d6a6f in do_command (thd=0x161a000) at sql_parse.cc:781 #19 0x00000000005c68cc in handle_one_connection (arg=0x161a000) at sql_connect.cc:1115 #20 0x0000000800d48b48 in thread_start (curthread=0xb06600) at /usr/src/lib/libthr/thread/thr_create.c:256 #21 0x0000000000000000 in ?? () The execution path is the following: sql/sql_plugin.cc:1626: mysql_install_plugin() sql/sql_plugin.cc:1657: plugin_initialize() sql/sql_plugin.cc:1002: initialize_schema_table() sql/sql_show.cc:6617: schema_table is allocated sql/sql_show.cc:6621: plugin->data= schema_table sql/sql_show.cc:6632: plugin->plugin->init() is called, assume it returns 1 sql/sql_show.cc:6636: goto err sql/sql_show.cc:6645: my_free(schema_table, MYF(0)) sql/sql_plugin.cc:1006: goto err sql/sql_plugin.cc:1661: goto deinit sql/sql_plugin.cc:1661: reap_plugins() sql/sql_plugin.cc:903: plugin_deinitialize() sql/sql_plugin.cc:815: finalize_schema_table() sql/sql_show.cc:6651: ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data sql/sql_show.cc:6662: my_free(schema_table, MYF(0)) <-- oops This bug does not immediately result in a crash on Linux (i.e. it survives the double free) and on FreeBSD with standard libc it crashes after one more INSTALL/UNINSTALL command. I had to remove "#define MALLOC_PRODUCTION" from /usr/src/lib/libc/stdlib/malloc.c in order to catch this on time. So it may be hard to reproduce but reading the above execution path and the code makes the bug obvious. I confirm that the attached patch fixes this bug. The second free() is not attampted if schema_table (plugin->data) is NULL. How to repeat: Have a INFORMATION_SCHEMA plugin whose init() function returns 1 and try to install with with INSTALL PLUGIN foo SONAME 'foo.so' Suggested fix: --- sql/sql_show.cc.orig 2008-04-29 17:12:12.000000000 +0300 +++ sql/sql_show.cc 2008-04-29 17:00:53.000000000 +0300 @@ -6640,12 +6640,13 @@ int initialize_schema_table(st_plugin_in schema_table->table_name= plugin->name.str; } DBUG_RETURN(0); err: my_free(schema_table, MYF(0)); + plugin->data = NULL; DBUG_RETURN(1); } int finalize_schema_table(st_plugin_int *plugin) { ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;