DeNA / HandlerSocket-Plugin-for-MySQL

HandlerSocket is a NoSQL plugin for MySQL, working as a daemon inside the mysqld process, to accept tcp connections, and execute requests from clients. HandlerSocket does not support SQL queries; instead it supports simple CRUD operations on tables.
Other
1.13k stars 150 forks source link

Server startup race may result in freed memory access #112

Open laurynas-biveinis opened 8 years ago

laurynas-biveinis commented 8 years ago

On Percona Server 5.6 trunk, with AddressSanitizer, if HandlerSocket is installed:

=================================================================
==11746==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000ee90 at pc 0x0000009e4da1 bp 0x7f4262fb7430 sp 0x7f4262fb7420
READ of size 8 at 0x60200000ee90 thread T29
    #0 0x9e4da0 in intern_plugin_lock /home/laurynas/mysql-server/sql/sql_plugin.cc:750
    #1 0x9f21cd in plugin_thdvar_init(THD*, bool) /home/laurynas/mysql-server/sql/sql_plugin.cc:2874
    #2 0x910547 in THD::init() /home/laurynas/mysql-server/sql/sql_class.cc:1492
    #3 0x9162c8 in THD::THD(bool) /home/laurynas/mysql-server/sql/sql_class.cc:1127
    #4 0x7f42714263c4 in dena::dbcontext::init_thread(void const*, int volatile&) /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/database.cpp:280
    #5 0x7f4271440e9d in thr_init /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr_worker.cpp:311
    #6 0x7f4271440e9d in dena::hstcpsvr_worker::run() /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr_worker.cpp:324
    #7 0x7f427144709b in dena::worker_throbj::operator()() /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr.cpp:32
    #8 0x7f427144709b in dena::thread<dena::worker_throbj>::thread_main(void*) /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/libhsclient/thread.hpp:71
    #9 0x7f42792c16f9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76f9)
    #10 0x7f4278756b5c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x106b5c)

0x60200000ee90 is located 0 bytes inside of 8-byte region [0x60200000ee90,0x60200000ee98)
freed by thread T0 here:
    #0 0x7f4279fcf2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0xff499b in my_free /home/laurynas/mysql-server/mysys/my_malloc.c:140
    #2 0x9e547d in intern_plugin_unlock /home/laurynas/mysql-server/sql/sql_plugin.cc:1055
    #3 0x9f33f2 in plugin_unlock(THD*, st_plugin_int**) /home/laurynas/mysql-server/sql/sql_plugin.cc:1098
    #4 0x586c1f in initialize_storage_engine /home/laurynas/mysql-server/sql/mysqld.cc:4939
    #5 0x5a140f in init_server_components /home/laurynas/mysql-server/sql/mysqld.cc:5298
    #6 0x5a140f in mysqld_main(int, char**) /home/laurynas/mysql-server/sql/mysqld.cc:5845
    #7 0x58380e in main /home/laurynas/mysql-server/sql/main.cc:25
    #8 0x7f427867082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

previously allocated by thread T0 here:
    #0 0x7f4279fcf602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0xff45e9 in my_malloc /home/laurynas/mysql-server/mysys/my_malloc.c:38
    #2 0x9e4e40 in intern_plugin_lock /home/laurynas/mysql-server/sql/sql_plugin.cc:770
    #3 0x9fa6f7 in plugin_init(int*, char**, int) /home/laurynas/mysql-server/sql/sql_plugin.cc:1390
    #4 0x5a105c in init_server_components /home/laurynas/mysql-server/sql/mysqld.cc:5201
    #5 0x5a105c in mysqld_main(int, char**) /home/laurynas/mysql-server/sql/mysqld.cc:5845
    #6 0x58380e in main /home/laurynas/mysql-server/sql/main.cc:25
    #7 0x7f427867082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

Thread T29 created by T0 here:
    #0 0x7f4279f6d253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x7f42714453da in dena::thread<dena::worker_throbj>::start_nothrow() /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/libhsclient/thread.hpp:46
    #2 0x7f42714453da in dena::thread<dena::worker_throbj>::start() /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/libhsclient/thread.hpp:30
    #3 0x7f42714453da in dena::hstcpsvr::start_listen[abi:cxx11]() /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr.cpp:126
    #4 0x7f427143549a in daemon_handlersocket_init /home/laurynas/mysql-server/plugin/HandlerSocket-Plugin-for-MySQL/handlersocket/handlersocket.cpp:84
    #5 0x9ed961 in plugin_initialize /home/laurynas/mysql-server/sql/sql_plugin.cc:1157
    #6 0x9fb222 in plugin_init(int*, char**, int) /home/laurynas/mysql-server/sql/sql_plugin.cc:1432
    #7 0x5a105c in init_server_components /home/laurynas/mysql-server/sql/mysqld.cc:5201
    #8 0x5a105c in mysqld_main(int, char**) /home/laurynas/mysql-server/sql/mysqld.cc:5845
    #9 0x58380e in main /home/laurynas/mysql-server/sql/main.cc:25
    #10 0x7f427867082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

There is a race condition between HS worker threads initializing default SE and default temp SE fields and the server main thread initializing the same globally w/o locking.

HandlerSocket bundled with Percona Server has a fix at https://github.com/percona/percona-server/pull/939. The fix is to initialize HS worker thread THD object without plugin support, as it does not care about the server default storage engine or default temp storage engine setting.