天天看點

netlink 審計子系統分析

netlink 是一種基于網絡的通信機制,允許在核心内部以及核心與使用者層之間進行通信,其正式定義見RFC3549

netlink 相對于 procfs 或 sysfs 具有以下優勢:

1.不需要輪詢。

2. 簡單、容易實作。

3. 核心可以直接向使用者層發送資訊,而無需使用者層事先請求。

netlink 隻支援資料報資訊,但提供了雙向通信。此外,netlink 不僅支援單點傳播資訊,也可以進行多點傳播。類似于其他socket機制,netlink的工作方式是異步的。

審計子系統代碼: kernle/audit.c

/* Initialize audit support at boot time. */
static int __init audit_init(void)
{
    int i;

    if (audit_initialized == AUDIT_DISABLED)
        return 0;

    printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
           audit_default ? "enabled" : "disabled");
    audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
                       audit_receive, NULL, THIS_MODULE);
    if (!audit_sock)
        audit_panic("cannot initialize netlink socket");
    else
        audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;

    skb_queue_head_init(&audit_skb_queue);
    skb_queue_head_init(&audit_skb_hold_queue);
    audit_initialized = AUDIT_INITIALIZED;
    audit_enabled = audit_default;
    audit_ever_enabled |= !!audit_default;

    audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");

    for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
        INIT_LIST_HEAD(&audit_inode_hash[i]);

    return 0;
}
           

回調函數

/* Receive messages from netlink socket. */
static void audit_receive(struct sk_buff  *skb)
{
    mutex_lock(&audit_cmd_mutex);
    audit_receive_skb(skb);
    mutex_unlock(&audit_cmd_mutex);
}
           

具體實作

/*
 * Get message from skb.  Each message is processed by audit_receive_msg.
 * Malformed skbs with wrong length are discarded silently.
 */
static void audit_receive_skb(struct sk_buff *skb)
{
    struct nlmsghdr *nlh;
    /*
     * len MUST be signed for NLMSG_NEXT to be able to dec it below 0
     * if the nlmsg_len was not aligned
     */
    int len;
    int err;

    nlh = nlmsg_hdr(skb);
    len = skb->len;

    while (NLMSG_OK(nlh, len)) {
        err = audit_receive_msg(skb, nlh);
        /* if err or if this message says it wants a response */
        if (err || (nlh->nlmsg_flags & NLM_F_ACK))
            netlink_ack(skb, nlh, err);

        nlh = NLMSG_NEXT(nlh, len);
    }
}
           

參考:

http://my.oschina.net/longscu/blog/59534

http://www.cnitblog.com/SpiWolf/archive/2006/06/14/5514.html