Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107730
  • 博文数量: 41
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 16:25
文章分类

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: LINUX

2010-01-27 10:55:44

1)auditd

启用方法:service auditd startauditd

禁用方法:service auditd stop

 

2)内核审计功能,消息获取部分

启用方法:启动参数audit=1auditctl -e 1

禁用方法:auditctl -e 0

冲区

1)   定义

/* The audit_buffer is used when formatting an audit record.  The caller

 * locks briefly to get the record off the freelist or to allocate the

 * buffer, and locks briefly to send the buffer to the netlink layer or

 * to place it on a transmit queue.  Multiple audit_buffers can be in

 * use simultaneously. */

struct audit_buffer {

  struct list_head     list;

  struct sk_buff       *skb;  /* formatted skb ready to send */

     struct audit_context *ctx;  /* NULL or associated context */

  gfp_t                   gfp_mask;

};

 

2)   说明

审计缓冲区。包含了sk_buff描述的套接字缓冲区。套接字缓冲区用来存储审计消息。

 

1)   定义

/* The audit_freelist is a list of pre-allocated audit buffers (if more

 * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of

 * being placed on the freelist). */

static DEFINE_SPINLOCK(audit_freelist_lock);

static int    audit_freelist_count;

static LIST_HEAD(audit_freelist);

 

/* AUDIT_MAXFREE is the number of empty audit_buffers we keep on the

 * audit_freelist.  Doing so eliminates many kmalloc/kfree calls. */

#define AUDIT_MAXFREE  (2*NR_CPUS)

 

2)   说明

当使用audit_buffer_alloc()申请新的审计缓冲区时,如果audit_freelist存在空闲的,直接取下使用;否则分配。

当使用audit_buffer_free()释放审计缓冲区时,如果audit_freelist_count > AUDIT_MAXFREE,释放。否则audit_freelist_count++;并且加入空闲链表:list_add(&ab->list, &audit_freelist);

1)  

static struct sk_buff_head audit_skb_queue;

2)   说明

用于存放审计消息的具体内容。

链表的长度存在限制。当超过长度限制时,不能往里面加入新的sk_buff,需要等待内核线程kauditd将至少一个sk_buff发送到用户空间。

1)  

/* Audit filter lists, defined in */

struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {

LIST_HEAD_INIT(audit_filter_list[0]),

LIST_HEAD_INIT(audit_filter_list[1]),

LIST_HEAD_INIT(audit_filter_list[2]),

LIST_HEAD_INIT(audit_filter_list[3]),

LIST_HEAD_INIT(audit_filter_list[4]),

LIST_HEAD_INIT(audit_filter_list[5]),

#if AUDIT_NR_FILTERS != 6

#error Fix audit_filter_list initialiser

#endif

};

 

struct audit_entry {

struct list_head   list;

struct rcu_head             rcu;

struct audit_krule rule;

};

 

struct audit_krule {

int                         vers_ops;

u32                         flags;

u32                         listnr;            // AUDIT_FILTER_USER

u32                         action;            // AUDIT_NEVER || AUDIT_ALWAYS

u32                         mask[AUDIT_BITMASK_SIZE];

u32                         buflen; /* for data alloc on list rules */

u32                         field_count;       // audit_field的个数

char                        *filterkey; /* ties events to rules */

struct audit_field *fields;

struct audit_field *arch_f; /* quick access to arch field */

struct audit_field *inode_f; /* quick access to an inode field */

struct audit_watch *watch;  /* associated watch */

struct audit_tree  *tree;   /* associated watched tree */

struct list_head   rlist;   /* entry in audit_{watch,tree}.rules list */

};

 

struct audit_field {

u32                                  type;              //事件类型,参考audit_filter_user_rules

u32                                  val;               //设置的值,被比较

u32                                  op;                         //操作符

char                                 *se_str;

struct selinux_audit_rule   *se_rule;

};

2)   说明

6条链表,分别对应6种事件。

 

1)   说明

如果不为0,限制每秒发送的审计记录个数。防止DOS攻击。

1)   定义

static atomic_t    audit_lost = ATOMIC_INIT(0);

2)   说明

丢失的审计记录数。造成丢失的途径:

   0) [suppressed in audit_alloc]

   1) out of memory in audit_log_start [kmalloc of struct audit_buffer]

   2) out of memory in audit_log_move [alloc_skb]

   3) suppressed due to audit_rate_limit

   4) suppressed due to audit_backlog_limit

1)   定义

/* Hash for inode-based rules */

struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];

 

#define AUDIT_INODE_BUCKETS  32

2)   说明

貌似不重要

1)   说明

调用netlink_kernel_create(),创建netlink套接字,注册接受函数:

audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, THIS_MODULE);

初始化套接字链表:

skb_queue_head_init(&audit_skb_queue);

注册SELinux回调函数:

selinux_audit_set_callback(&selinux_audit_rule_update);

如果定义了CONFIG_AUDITSYSCALL,注册inotify操作函数集:

audit_ih = inotify_init(&audit_inotify_ops);

[用法?]于节点的规则的hash表:

INIT_LIST_HEAD(&audit_inode_hash[i]);

通信

1)  

audit_receive() -> audit_receive_skb() -> audit_receive_msg(skb, nlh)

 

audit_receive_msg()中根据不同的msg_type = nlh->nlmsg_type;进行检查后。

第一次接受消息时,创建内核线程kauditd

if (!kauditd_task)

          kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");

根据msg_type进行不同的处理:

 

switch (msg_type) {

          case AUDIT_GET:

                   audit_send_reply            //发送Audit状态信息

          case AUDIT_SET:

audit_set_enabled  audit_set_failure  audit_set_rate_limit  audit_set_backlog_limit          //设置Audit参数

                            case AUDIT_USER:

                            case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:

                            case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:

                                     audit_filter_user; //调用audit_filter_user_rules[后面介绍]

                            case AUDIT_ADD:

                            case AUDIT_DEL:

                            case AUDIT_LIST:

                                     audit_receive_filter

                            case AUDIT_ADD_RULE:

                            case AUDIT_DEL_RULE:

                            case AUDIT_LIST_RULES:

                                     audit_receive_filter

                            case AUDIT_TRIM:

                                     audit_trim_trees();

                            case AUDIT_MAKE_EQUIV:

                                     audit_tag_tree

                            case AUDIT_SIGNAL_INFO:

                                     audit_send_reply

                  

1)   说明

kauditd_thread()

取下一个skb,唤醒audit_backlog_wait队列上的等待者。

如果存在audit_pid,发送netlink_unicast(audit_sock, skb, audit_pid, 0);否则printk

如果audit_skb_queue为空,加入kauditd_wait队列等待。

skb链表

1)  

static inline int audit_rate_check(void)

2)   说明

返回1表示没有超过速率限制;返回0表示速率过快。

如果audit_rate_limit等于0,表示不限速(默认),返回1

如果发送的审计记录数不小于audit_rate_limit,在<=1秒,那么返回0

 

audit_log_start[audit_skb_queue长度超限]audit_log_end调用。

1)   定义

/**

 * audit_log_lost - conditionally log lost audit message event

 * @message: the message stating reason for lost audit message

 *

 * Emit at least 1 message per second, even if audit_rate_check is

 * throttling.

 * Always increment the lost messages counter.

*/

void audit_log_lost(const char *message)

2)   说明

首先增加atomic_inc(&audit_lost);

然后判断要不要进行处理print = (audit_failure == AUDIT_FAIL_PANIC || !audit_rate_limit);

如果设置了audit_failure == AUDIT_FAIL_PANIC;或者不限速audit_rate_limit==0;那么需要处理。

如果限速,那么如果自打上次处理以来超过1秒了,就要处理。如果不超过1秒,就不处理。

 

根据处理标志print,调用audit_panic进行lost时的处理。

1)   定义

struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type)

2)   说明

首先调用audit_filter_type,检查根据audit_filter_list[AUDIT_FILTER_TYPE],不想要的事件类型将不继续处理。

如果套接字缓冲区列表超过长度限制,那么可能会1加入等待队列audit_backlog_wait2)报错返回NULL(检查发送的速率)

如果不超长,ab = audit_buffer_alloc(ctx, gfp_mask, type);申请audit_buffer

分配成功的话,获得时间戳和序列号,调用audit_log_format(ab, "audit(%lu.%03lu:%u): ", t.tv_sec, t.tv_nsec/1000000, serial);

之后返回ab

type=SYSCALL msg=audit(1208941951.177:520792):

1)  

static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, gfp_t gfp_mask, int type)

2)   说明

申请并填充audit_buffer。优先从audit_freelist上寻找有无空闲audit_buffer。没有的话ab = kmalloc(sizeof(*ab), gfp_mask);

 

之后:

ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);

#define AUDIT_BUFSIZ 1024

 

填充的方法如下:

ab->ctx = ctx;

ab->gfp_mask = gfp_mask;

nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));

nlh->nlmsg_type = type;

nlh->nlmsg_flags = 0;

nlh->nlmsg_pid = 0;

nlh->nlmsg_seq = 0;

1)   定义

void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)

static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,  va_list args)

2)   说明

audit_log_format()调用audit_log_vformat()

按照参数fmt,添加信息到skb->tail,并增加skb->tail

1)  

void audit_log_end(struct audit_buffer *ab)

2)   说明

挂接到套接字缓冲区链表尾,或直接printk

首先检查速率audit_rate_check,否则如果audit_pid存在,那么挂接skb_queue_tail(&audit_skb_queue, ab->skb);并唤醒等待队列kauditd_wait wake_up_interruptible(&kauditd_wait);

否则的话查看printk_ratelimit(),没有问题就printkprintk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0));有问题的话,audit_log_lost()

最后,无论如何,都要audit_buffer_free(ab);

 

 

 

阅读(1200) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~