2.4.4 文件系统变化的审计
审计系统使用inotify机制监视文件系统的变化,并将监视的结果通过审计系统记录到log文件中。
内核审计系统调用函数audit_init进行初始化时,函数audit_init会调用函数inotify_init创建并初始化一个监视处理实例audit_ih。程序可以在指定节点的watch链表中查找监视处理实例audit_ih的watch,如果找到watch,就可以调用在监视处理实例audit_ih中的函数处理审计事件。
1.审计监视的数据结构
审计监视结构audit_watch用来存放用于监视文件系统变化规则的相关信息。审计规则链表audit_filter_list[AUDIT_FILTER_WATCH]用来存储审计监视的规则。每条审计规则结构audit_krule含有审计监视结构指针watch,审计规则结构audit_krule与审计监视结构指针相关的部分列出如下:
struct audit_krule {
......
struct audit_watch*watch;
......
};
审计监视结构audit_watch列出如下(在linux26/include/linux/audit.h中):
struct audit_watch {
atomic_tcount; /*引用数 */
char*path; /* 加watch的路径*/
dev_tdev; /* 与超级块设置被关的指针*/
unsigned longino; /*相关的节点号*/
struct audit_parent*parent; /* associated parent */
struct list_headwlist; /* 用于挂接到parent->watches 链表上 */
struct list_headrules; /* 相关的规则*/
};
|
结构audit_parent用来封装watch,它还含有审计监视的链表和状态标识等,它对应规则描述路径的父目录节点,因此,文件系统变化时,inotify机制的hook函数通过父目录节点的watch触发监视处理实例的函数。
父目录中每个文件路径可能对应一个审计监视规则,因此,结构audit_parent提供了链表指针watches存放父目录下文件的审计监视结构audit_watch实例。
程序可以通过审计规则链表找到watch,还可以在节点的watch链表中找到需要的watch。
结构audit_parent列出如下:
struct audit_parent {
struct list_headilist;/*用于挂接在inotify注册链表上*/
struct list_headwatches; /*用于挂接结构audit_watch实例的链表头*/
struct inotify_watchwdata;/*inotify机制的watch数据*/
unsignedflags;/*状态标识*/
};
|
2.添加审计监视规则
审计应用程序auditctl可使用-w或-W选项添加或删除文件系统监视规则,这两个选项说明如下:
-w |
添加与删除审计监视规则的过程是相反的过程,下面只分析添加审计监视规则的机制。
当审计应用程序auditctl添加审计监视规则时,内核审计系统针对所有规则统一调用函数audit_receive_filter将审计规则加到审计规则链表上。对于审计监视规则,函数audit_receive_filter的调用层次图如图2-7所示。
错误!
![]() |
| 图2-7 函数audit_receive_filter添加审计监视规则的调用层次图 |
图2-7中,内核审计系统函数audit_receive_filter分析应用程序auditctl设置的审计监视规则,调用函数audit_init_watch将规则初始化为结构audit_watch实例,放入规则链表中。
函数audit_add_watch在节点和规则实例krule中加入watch。它调用函数inotify_find_watch在节点的watch链表中查找匹配监视处理实例audit_ih的watch,如果没找到,就调用函数audit_init_parent初始化watch,并将其加入到节点和监视处理实例audit_ih的watch链表中,再将watch加入到审计监视规则链表中。
watch加入节点后,监视文件系统变化的hook函数就可以调用watch中的监视处理函数,hook函数通过watch的成员指针找到监视处理实例audit_ih,audit_ih含有审计文件系统变化的记录函数,记录函数将文件系统变化信息通过审计系统写入到log文件中。
函数audit_add_watch列出如下(在linux26/kernel/auditfilter.c中):
/*参数ndw是文件的结构nameidata 实例,ndp为文件所在目录的结构实例*/
static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
struct nameidata *ndw)
{
//得到审计监视规则实例,前面运行的函数audit_init_watch根据规则已初始化了这个实例
struct audit_watch *watch = krule->watch;
struct inotify_watch *i_watch;
struct audit_parent *parent;
int ret = 0;
if (ndw) {
watch->dev = ndw->dentry->d_inode->i_sb->s_dev; //得到文件所在的设备
watch->ino = ndw->dentry->d_inode->i_ino;//得到文件的节点号
}
mutex_unlock(&audit_filter_mutex);
//在目录节点上查找符合audit_ih的watch,找到后,放在i_watch中
if (inotify_find_watch(audit_ih, ndp->dentry->d_inode, &i_watch) < 0) {
/*如果在目录节点上没有找到watch,初始化watch,创建结构audit_parent实例并放在parent中
parent = audit_init_parent(ndp);
if (IS_ERR(parent)) { //如果初始化出错,返回错误
/* 调用者期望互斥锁处于锁住状态*/
mutex_lock(&audit_filter_mutex);
return PTR_ERR(parent);
}
} else
//找到watch,得到它的结构audit_parent实例,并放在parent中
parent = container_of(i_watch, struct audit_parent, wdata);
mutex_lock(&audit_filter_mutex);
/* parent在取得audit_filter_mutex之前被移走,则返回错误*/
if (parent->flags & AUDIT_PARENT_INVALID)
ret = -ENOENT;
else
audit_add_to_parent(krule, parent); //将parent加入到krule中,krule代表一条审计规则
/*引用计数减1,如果引用计数为0,删除watch */
put_inotify_watch(&parent->wdata);
return ret;
}
|
函数audit_add_to_parent将给定的规则与父目录的结构inotify_watch实例联系起来,调用者必须持有互斥锁audit_filter_mutex,其列出如下:
static void audit_add_to_parent(struct audit_krule *krule,
struct audit_parent *parent)
{
//得到审计监视规则实例,前面运行的函数audit_init_watch根据规则已初始化这个实例
struct audit_watch *w, *watch = krule->watch;
int watch_found = 0;
//遍历链表watches,watches存放着目录下所有文件的结构audit_watch实例
list_for_each_entry(w, &parent->watches, wlist) {
// parent->watches为目录的结构audit_watch实例,w为文件的结构audit_watch实例
if (strcmp(watch->path, w->path))
continue;
watch_found = 1;
audit_put_watch(watch); //引用计数减1
audit_put_watch(watch);
audit_get_watch(w); //引用计数加1
krule->watch = watch = w; //将文件的结构audit_watch实例放到内核规则实例krule上
break;
}
if (!watch_found) { //在链表watches没有找到文件的结构audit_watch实例,将
get_inotify_watch(&parent->wdata); //引用计数加1
watch->parent = parent;
list_add(&watch->wlist, &parent->watches); //将&watch加入到parent->watches 链表上
}
list_add(&krule->rlist, &watch->rules);
}
|
3.监视处理实例audit_ih
文件系统变化的审计消息是通过监视处理实例audit_ih进行处理的,它的操作函数集为audit_ inotify_ops,操作函数集中的函数audit_handle_ievent处理inotify事件。当文件系统发生变化时,inotify机制hook函数会通过watch调用函数audit_handle_ievent将文件系统变化的审计消息通过审计系统写入到log文件中。
内核审计系统初始化时,初始化函数audit_init会调用函数inotify_init创建并初始化监视处理实例audit_ih。函数audit_init与创建监视处理实例相关的代码列出如下(在linux26/kernel/audit.c中):
struct inotify_handle *audit_ih;
static int __init audit_init(void)
{
......
#ifdef CONFIG_AUDITSYSCALL
audit_ih = inotify_init(&audit_inotify_ops);
if (IS_ERR(audit_ih))
audit_panic("cannot initialize inotify handle");
#endif
......
}
操作函数集audit_inotify_ops列出如下:
#ifdef CONFIG_AUDITSYSCALL
static const struct inotify_operations audit_inotify_ops = {
.handle_event= audit_handle_ievent,
.destroy_watch= audit_free_parent,
};
#endif
|
函数audit_handle_ievent根据inotify事件更新审计规则结构实例上的审计监视数据,调用审计系统接口函数将文件系统变化信息写入到log文件中,其函数列出如下(在linux26/kernel/auditfilter.c中):
void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
u32 cookie, const char *dname, struct inode *inode)
{
struct audit_parent *parent;
//通过节点的i_watch找到结构audit_parent实例
parent = container_of(i_watch, struct audit_parent, wdata);
if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
//更新规则结构实例中的审计监视,并调用审计系统接口函数记录文件系统变化的信息
audit_update_watch(parent, dname, inode->i_sb->s_dev,
inode->i_ino, 0);
else if (mask & (IN_DELETE|IN_MOVED_FROM))
audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
/* inotify自动删除watch 并发送IN_IGNORED */
else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
audit_remove_parent_watches(parent);
/* inotify不删除watch,因此需要手动删除它 */
else if(mask & IN_MOVE_SELF) {
audit_remove_parent_watches(parent);
inotify_remove_watch_locked(audit_ih, i_watch);
} else if (mask & IN_IGNORED)
put_inotify_watch(i_watch); //删除watch
}
|
| 回书目 上一节 下一节 |
|
· 第六章 你能帮我吗?.. · Linux笔试面试题选摘测.. · 08年5月软考网管上午真.. · 性能测试从零开始 目录 · 08年5月软考网工上午真.. · 上周拒绝服务攻击(DDo.. |
· 08年5月各大网上书店及.. · 2008年5月24日软考试题.. · 软件设计师专家临考模.. · 上周网络管理员专家自.. · 网络工程师自测获奖名.. · 08年4月各大网上书店及.. |
|
||||
| · NAC安全访问控制 · 网络布线测试仪器 · Windows Server 2008专.. · Windows远程桌面应用 · 网络故障排除宝典 · 运营商封堵ADSL共享 中.. · 解析35岁技术人的价值.. · 世纪枭雄比尔盖茨的王.. |
· 主流品牌防火墙配置 · ASP.NET开发教程 · 超级计算机TOP500专题 · Vista SP1对决XP SP3 · SQL Server 2008/2005.. · 程序员如何成长? · C#技术开发指南 · 虚拟化技术还有点“虚” |
|||
|
||||
| · SOA 面向服务架构 · SQL Server 2008/2005.. · Apache技术专题 · 三层交换技术专题 · SQL Server入门到精通 · Windows远程桌面应用 · C#技术开发指南 · Apache技术专题 |
· Windows集群服务应用 · C#技术开发指南 · 国际文档格式标准开战 · 路由器设置与口令恢复 · Linux 集群技术专题 · PHP开发应用手册 · SOA 面向服务架构 · 企业数据恢复指南 |
|||
|
||||
| · SQL Server入门到精通 · SQL Server 2008/2005.. · SOA 面向服务架构 · Apache技术专题 · C#技术开发指南 · 三层交换技术专题 · Apache技术专题 · C#技术开发指南 |
· Windows远程桌面应用 · 企业数据恢复指南 · Windows集群服务应用 · 路由器设置与口令恢复 · Linux 集群技术专题 · SOA 面向服务架构 · 了解统一威胁管理(UTM).. · 反垃圾邮件技术应用 |
|||