audit

 

一、socket系统调用创建socket/sock

系统调用参数family为PF_NETLINK,protocol为NETLINK_AUDIT

186  int audit_open() {
187      return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
188  }

 

1.创建struct socket

2. 创建struct sock(struct netlink_sock)

调用net_proto_family类型里的create函数指针创建netlink_sock,family为PF_NETLINK,所以net_families[family]即指向netlink_family_ops,所以是调用netlink_create()。netlink_sock里包含了struct sock,并且把它放置在第一个field,所以创建了netlink_sock也即创建了sock,因为netlink_proto里的slab成员没有设置,所以是调用的kmalloc(netlink_proto.obj_size)来分配的netlink_sock,netlink_proto.obj_size即为netlink_sock struct size;

设置socket的proto_ops类型成员ops为netlink_ops,这个后面user space使用这个socket调用sendto、recvfrom等系统调用将会调用到这个函数集里的对应函数(netlink_sendmsg/netlink_recvmsg等);

调用sock_init_data()绑定socket和sock,设置sock struct的一些成员,比如sk_rcvbuf、sk_sndbuf两个buffer的size、sk_data_ready成员设置为sock_def_readable(有数据发给这个socket,调用这个函数唤醒在这个socket上等待的线程);

设置sock的sk_protocol成员为NETLINK_AUDIT

3.为socket创建fd

创建fd,这个fd将会返回给user space,之后user space调用socket相关的系统调用都将根据这个fd来操作,在kernel里根据这个fd再找到对应的socket

 

二、sendto系统调用设置user space的audit线程

user space构造好audit_message,这个struct第一个成员为nlmsghdr,data成员为数组,数组size为8970,这个数组是存放的message payload,此时message payload为audit_status,设置了这个struct的pid为logd.auditd线程的pid、mask成员为AUDIT_STATUS_PID。然后设置audit_message.nlh.nlmsg_len,这个len是nlmsghdr struct size+payload size(即audit_status struct size)。然后是调用了sendto系统调用;

 #define MAX_AUDIT_MESSAGE_LENGTH 8970
44  struct audit_message {
45      struct nlmsghdr nlh;
46      char data[MAX_AUDIT_MESSAGE_LENGTH];
47  };

 

kernel __sys_sendto() 

根据buf、len设置iovec、iov_iter;

根据fd找到对应的socket;

调用netlink_sendmsg()

--如果netlink_sock还没有bind,即其bound成员为false,则调用netlink_autobind(),在此函数里会设置netlink_sock的portid,这个portid即是此user线程所在的进程的pid,此pid通过task_tgid_vnr(current)得到,之后有一个插入hash table的动作,然后将netlink_sock.bound设置为1;

--调用netlink_alloc_large_skb()分配一个sk_buff,此时传入的size参数为netlink msg size(msg header+msg payload),然后设置sk_buff.cb的portid成员为netlink_sock.portid、将user space的netlink msg(header+payload) copy到sk_buff;

--user space没有设置sockaddr_nl除nl_family外的其它所有成员(这些成员的值均被memset为0了),所以dst_group、dst_portid均为0,所以没有调用netlink_broadcast();

--调用netlink_unicast(),此时的dst_portid为0,为0表示kernel里的sock,根据portid以及sk_protocol查找对应的sock,这里的sk_protocol为NETLINK_AUDIT,所以这里查询到的sock为kernel audit所创建的sock,因为是kernel  sock,所以调用netlink_unicast_kernel,它会调用netlink_rcv指针函数,此时它指向audit_receive();

 

posted @ 2022-03-20 18:54  aspirs  阅读(379)  评论(0编辑  收藏  举报