MySQL5.5-audit plugin的函数调用流程分析

继续研究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)


这里会调用两次mysql_audit_general函数,分别对应不同的事件类型

4.mysql_audit_general() (sql_audit.h)


5.mysql_audit_notify() (sql_audit.cc),该函数比较简短,会调用一个函数指针


这里,以event_class作为偏移量,来调用相应的函数指针:

audit_handlers作为全局变量,定义:


5.1 general_class_handler()

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审计插件的执行流程进行修改,来满足一些有趣的需求




你可能感兴趣的:(plugin)