Millet整体架构的分析
内核空间
一部分源码位于drivers/mihw
millet_core.c
主要作用: 通过netlink,为内核提供发送消息给用户态进程的几个函数并负责用户态进程发送过来的控制命令。
1.register_millet_hook
提供给内核各个millet子模块一个统一的注册函数
int register_millet_hook(int type, recv_hook recv_from,
send_hook send_to, init_hook init)
{
if (!TYPE_VALID(type)) {
pr_err("%s: type is invalid! %d\n",
__func__, type);
return RET_ERR;
}
if (millet_sk.mod[type].init) {
pr_err("%s: init has been registered %d\n",
__func__, type);
return RET_ERR;
} else
// 注册对应子模块的初始化函数
millet_sk.mod[type].init = init;
if (millet_sk.mod[type].recv_from) {
pr_err("%s: recv_from has been registered %d\n",
__func__, type);
return RET_ERR;
} else
// 注册对应子模块接收到用户态接收函数
millet_sk.mod[type].recv_from = recv_from;
if (millet_sk.mod[type].send_to) {
pr_err("%s: send_to has been registered %d\n",
__func__, type);
return RET_ERR;
} else
// 注册对应子模块发送消息给用户态的函数
millet_sk.mod[type].send_to = send_to;
if (millet_debug) {
printk("type %d register hook\n", type);
dump_stack();
}
return RET_OK;
}
2.millet_sendmsg
提供给内核各个子模块一个统一的发送消息函数
int millet_sendmsg(enum MILLET_TYPE type, struct task_struct *tsk,
struct millet_data *data)
{
u64 walltime, timecost;
unsigned long flags;
int ret = RET_OK;
if (!TYPE_VALID(type)) {
pr_err("wrong type valid %d\n", type);
return RET_ERR;
}
if (!millet_sk.mod[type].send_to) {
pr_err("mod %d send_to interface is NULL");
return RET_ERR;
}
walltime = ktime_to_us(ktime_get());
// 使用子模块注册的send_to函数
ret = millet_sk.mod[type].send_to(tsk, data, &millet_sk);
spin_lock_irqsave(&millet_sk.mod[type].lock, flags);
if (ret < 0) {
millet_sk.mod[type].stat.send_fail++;
} else if (ret > 0)
millet_sk.mod[type].stat.send_suc++;
timecost = ktime_to_us(ktime_get()) - walltime;
millet_sk.mod[type].stat.runtime += timecost;
spin_unlock_irqrestore(&millet_sk.mod[type].lock, flags);
return ret;
millet_hs.c
主要作用:握手,我觉得意义不大,就是返回一个空的millet_data。实际上millet_core.c的
LOOPBACK_MSG 就可以完成他的所有任务。
对应类型为HANDSHK_TYPE
另外一部分源码位于binder和singal的实现里,实际上只要关注几个
signal.c
int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
enum pid_type type)
{
unsigned long flags;
int ret = -ESRCH;
#ifdef CONFIG_MILLET
struct millet_data data;
if (sig == SIGKILL
|| sig == SIGTERM
|| sig == SIGABRT
|| sig == SIGQUIT) {
data.mod.k_priv.sig.caller_task = current;
data.mod.k_priv.sig.killed_task = p;
data.mod.k_priv.sig.reason = KILLED_BY_PRO;
// SIG only send SIGKILL SIGTERM SIGABRT SIGQUIT
millet_sendmsg(SIG_TYPE, p, &data);
}
#endif
if (lock_task_sighand(p, &flags)) {
ret = send_signal(sig, info, p, type);
unlock_task_sighand(p, &flags);
}
return ret;
}
binder.c
binder_transaction函数里
一个是在用户进程作为server时返回给系统进程时进行通知
一个是在用户应用收到binder时通知
freezer.c
这个__refrigerator函数实际上就是cgroupv1冻结时进程。MILLET在这里就是加了一个不冻结ptrace的应用的选项
最终就加了一个条件,就是不冻结正在ptrace的进程
内核模块参数,通过/sys/module/millet_core可以控制这个开关
这个条件
用户空间