分类: LINUX
2010-01-27 10:56:52
根据AUDIT_FILTER_TYPE链表进行审计消息的过滤(&audit_filter_list[AUDIT_FILTER_TYPE])。
函数:
int audit_filter_type(int type)
调用过程:
audit_log_start() -> audit_filter_type()
函数分析:
int audit_filter_type(int type)
{
struct audit_entry *e;
int result = 0;
rcu_read_lock();
if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
goto unlock_and_return;
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
list) {
int i;
for (i = 0; i < e->rule.field_count; i++) { //从实际情况来说,应该不需要循环,因为当初exclde这个链的rule只能设置一个field:msgtype
struct audit_field *f = &e->rule.fields[i];
if (f->type == AUDIT_MSGTYPE) {
result = audit_comparator(type, f->op, f->val);
if (!result)
break;
}
}
if (result) //只要任何一个rule匹配了msgtype,就认为匹配
goto unlock_and_return;
}
unlock_and_return:
rcu_read_unlock();
return result; //匹配为1,不匹配为0
}
audit_log_start()
{
…
if (unlikely(audit_filter_type(type)))
return NULL; //如果audit_filter_type返回1,那么不进行审计
…
}
根据AUDIT_FILTER_USER链表进行审计消息的过滤(&audit_filter_list[AUDIT_FILTER_USER])。
函数:
int audit_filter_user(struct netlink_skb_parms *cb, int type)
调用过程:
audit_receive_msg() -> audit_filter_user()
调用audit_filter_user_rules,对指定rule的每个field,audit_field *f = &rule->fields[i];
switch (f->type) {
case AUDIT_PID:
case AUDIT_UID:
case AUDIT_GID:
case AUDIT_LOGINUID:
}
可以看出,AUDIT_FILTER_USER链表仅会对以上四种id进行过滤。
如果每个域值的判断都成立,那么标志state(rule->action)并返回1。任意一个域值的判断不成立的话,立即返回0。
audit_filter_user
对此链表的某个rule,如果audit_filter_user_rules返回1,那么就要退出audit_filter_user。返回值为1,除非state是never。
如果此链表没有任何一个rule应用audit_filter_user_rules会返回1,那么默认返回1。
就是说,
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
这些类型的消息默认是要记录的。
根据AUDIT_FILTER_TASK链表进行审计消息的过滤(&audit_filter_list[AUDIT_FILTER_TASK])。
函数:
static enum audit_state audit_filter_task(struct task_struct *tsk)
调用audit_filter_rules,对指定rule的每个field,audit_field *f = &rule->fields[i];
audit_filter_rules判断的域很多,参考代码:
switch (f->type) {
case AUDIT_PID:
result = audit_comparator(tsk->pid, f->op, f->val);
break;
…
case AUDIT_PERM:
result = audit_match_perm(ctx, f->val);
break;
}
对于某条rule,如果每个域值的判断都成立,那么标志state(rule->action)并返回1。任意一个域值的判断不成立的话,立即返回0。
对此链表的某个rule,如果audit_filter_rules返回1,即找到一条匹配的rule,那么就要退出audit_filter_task。返回值为state,state已经被赋值为AUDIT_DISABLED(never)或AUDIT_RECORD_CONTEXT(always)。
如果此链表没有任何一个rule应用audit_filter_rules会返回1,那么默认返回state为AUDIT_BUILD_CONTEXT。
此函数的被调用过程:
fork_idle & do_fork -> copy_process -> audit_alloc -> audit_filter_task
下一步需要确定这两个fork函数所有会被用到的时机。
每一个进程产生的时候都会根据audit_filter_task决定[state == AUDIT_DISABLED]是否分配tsk->audit_context。如果不分配的话,那么系统调用是不能对这样的进程所产生的系统调用进行审计的。
audit_filter_syscall
对每个rule的判定,和audit_filter_task一样,都调用了audit_filter_rules。
audit_filter_task:
audit_filter_rules(tsk, &e->rule, NULL, NULL, &state)) {
audit_filter_syscall:
audit_filter_rules(tsk, &e->rule, ctx, NULL, &state)) {
1. audit_aux_data
struct audit_aux_data {
struct audit_aux_data *next;
int type;
};
2. 派生结构
a)
struct audit_aux_data_mq_open {
struct audit_aux_data d;
int oflag;
mode_t mode;
struct mq_attr attr;
};
b)
struct audit_aux_data_mq_sendrecv {
struct audit_aux_data d;
mqd_t mqdes;
size_t msg_len;
unsigned int msg_prio;
struct timespec abs_timeout;
};
c)
struct audit_aux_data_mq_notify {
struct audit_aux_data d;
mqd_t mqdes;
struct sigevent notification;
};
d)
struct audit_aux_data_mq_getsetattr {
struct audit_aux_data d;
mqd_t mqdes;
struct mq_attr mqstat;
};
e)
struct audit_aux_data_ipcctl {
struct audit_aux_data d;
struct ipc_perm p;
unsigned long qbytes;
uid_t uid;
gid_t gid;
mode_t mode;
u32 osid;
};
f)
struct audit_aux_data_execve {
struct audit_aux_data d;
int argc;
int envc;
char mem[0];
};
g)
struct audit_aux_data_socketcall {
struct audit_aux_data d;
int nargs;
unsigned long args[0];
};
h)
struct audit_aux_data_sockaddr {
struct audit_aux_data d;
int len;
char a[0];
};
i)
struct audit_aux_data_pids {
struct audit_aux_data d;
pid_t target_pid[AUDIT_AUX_PIDS];
uid_t target_auid[AUDIT_AUX_PIDS];
uid_t target_uid[AUDIT_AUX_PIDS];
unsigned int target_sessionid[AUDIT_AUX_PIDS];
u32 target_sid[AUDIT_AUX_PIDS];
char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
int pid_count;
};