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();
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
2020-03-20 android init执行service的脚本code位置