继续研究audit plugin,首先gdb源代码
启动mysqld,加上--debug选项
进入gdb:
(gdb) attach 19079 (mysqld的进程号)
(gdb) b mysql_audit_notify(THD*, unsigned int, unsigned int, ...) (猜测该函数会调用audit的notify函数)
(gdb) c
Continuing.
启动mysql客户端
Breakpoint 1, mysql_audit_notify (thd=0x16fe09b0, event_class=1, event_subtype=0)
at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_audit.cc:207
207 audit_handler_t *handlers= audit_handlers + event_class;
(gdb) bt
#0 mysql_audit_notify (thd=0x16fe09b0, event_class=1, event_subtype=0) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_audit.cc:207
#1 0x00000000006943d6 in thd_prepare_connection (thd=0x16fe09b0) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_connect.cc:715
#2 0x0000000000694c61 in do_handle_one_connection (thd_arg=0x16fe09b0) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_connect.cc:780
#3 0x0000000000694d3b in handle_one_connection (arg=0x16fe09b0) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_connect.cc:706
#4 0x00000034f7e064a7 in start_thread () from /lib64/libpthread.so.0
#5 0x00000034f72d3c2d in clone () from /lib64/libc.so.6
(gdb)
可见,在准备创建客户端连接时也会调用audit,在gdb过程中,发现该函数被调用了很多次:
Breakpoint 1, mysql_audit_notify (thd=0x1706c790, event_class=1, event_subtype=0)
Breakpoint 1, mysql_audit_notify (thd=0x16fe09b0, event_class=0, event_subtype=3)
查了一下notify函数的记录,写入了如下操作:
select @@version_comment limit 1;
select @@version_comment limit 1;
mysql > use yinfeng
SELECT DATABASE();
SELECT DATABASE();
看起来,似乎每次操作之前都会调用两次mysql_audit_notify函数,即使执行一次错误的操作(比如向一个不存在的表插入数据)
————————————————————————————————————————————————
但当执行select、create table之类的命令时,则是先完成命令,然后才会跳到断点
#0 mysql_audit_notify (thd=0x1706c790, event_class=0, event_subtype=2) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_audit.cc:207
#1 0x00000000005c7f84 in mysql_audit_general (thd=0x1706c790, event_subtype=2, error_code=0, msg=0x0)
at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_audit.h:131
#2 0x00000000005c9d22 in dispatch_command (command=COM_QUERY, thd=0x1706c790, packet=0x1706f601 "", packet_length=27)
at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_parse.cc:1398
#3 0x00000000005ca0f8 in do_command (thd=0x1706c790) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_parse.cc:771
#4 0x0000000000694c7e in do_handle_one_connection (thd_arg=0x1706c790) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_connect.cc:787
#5 0x0000000000694d3b in handle_one_connection (arg=0x1706c790) at /home/yinfeng.zwx/mysql-5.5.14/sql/sql_connect.cc:706
#6 0x00000034f7e064a7 in start_thread () from /lib64/libpthread.so.0
#7 0x00000034f72d3c2d in clone () from /lib64/libc.so.6
看起来dispatch_command函数似乎是audit的入口,简要的归纳一下流程:
1.do_handle_one_connection()
2. do_command
3.dispatch_command(sql_parse.cc)
4.mysql_audit_general() (sql_audit.h)
audit_handlers作为全局变量,定义:
5.2 connection_class_handler()
可以看到上述两个函数都会调用event_class_dispatch,该函数的参数形式与自定义的插件函数参数完全一致,
深入代码可以发现,在创建连接的时候调用了上述两个函数都被调用了,其中conneciton_class_handler()在函数thd_prepare_connection中被调用:
6.event_class_dispatch() (sql_audit.cc:466-491)
7. plugins_dispatch()
最终,我们到达了实际调用插件函数,使用函数指针来实现:
————————————————————————————————————————————————————————————
下一步:
尝试对该audit审计插件的执行流程进行修改,来满足一些有趣的需求