前面讲过审计有两个特征:正式的检查和独立的执行者。Linux内核的audit子系统并不纯粹,它还包含部分日志功能。下面列出审计消息的四个来源,其中前三个来源实际上是日志属性的消息。
1.内核
内核中的一些子系统会使用audit子系统提供的函数产生audit日志消息。audit主要提供了3个函数供其他子系统使用:audit_log_start、audit_log、audit_log_end。下面以SELinux为例看一下调用过程:
audit_log_start准备一个buffer,audit_log_format向buffer中填充内容,audit_log_end将buffer制作成audit消息发出。
内核用audit_log系列函数生成的实际上是日志消息,不是审计性质的消息。
2.用户态守护进程
第二个来源是一些用户态守护进程。以sshd为例看几段代码:
audit_open和audit_log_acct_message都在audit的用户态库中实现。audit_open的实现比较简单:
audit_open函数的核心就是获得一个NETLINK_AUDIT类型的NETLINK套接字。
audit_log_acct_message函数的核心是调用函数audit_send_user_message,audit_send_user_ message会调用函数audit_send。audit_send的核心是调用Linux系统调用sendto,也就是通过netlink套接字发送消息给内核。(www.xing528.com)
简言之,用户态守护进程sshd会申请一个audit netlink套接字,然后向这个套接字中发送消息。netlink套接字作为内核态和用户态的接口,sshd发送的消息会被内核接收。内核接收这些消息后,不做任何处理,再发还给audit netlink套接字,但是套接字的端口号换成auditd相关的端口号。用户态的auditd进程会接收这些消息。这种设计有些怪异,用户态产生的消息不直接发送给用户态的auditd,而发给内核,由内核转发给用户态的auditd。
3.auditd
第三个来源是auditd本身,这个就不细说了。auditd本身是一个用户态守护进程,不同的是,它不会把自身产生的audit消息传入内核,而是直接发送给audispd,同时写入audit.log。
4.系统调用
这是最重要的一个来源,因为前三个来源都是日志,不是审计,只有这个来源才是审计。内核作为独立的个体做正式的检查,它检查的对象是用户态进程,检查点设置在系统调用的实现里面。
先看系统调用入口中的audit钩子函数:
在系统调用的入口调用__audit_syscall_entry,在出口调用__audit_syscall_exit。下面看一下这两个函数:
除了这两个钩子函数,还有许多audit钩子函数分布在系统调用的函数调用路径中。这些钩子函数都在做一件事:将信息填入进程的audit_context结构中。下面看一下audit_context结构:
在进程的task_struct中有一个指针指向一个audit_context实例。在audit_context中有一部分成员用于规则匹配,一部分成员用于生成审计消息。文件和目录的处理比较复杂,audit_context中有一些成员专门用于文件和目录的审计。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。