如何在内核模块中将进程标记为SIGNAL_UNKILLABLE?
实现方案
核心思路
要实现标记进程为SIGNAL_UNKILLABLE,核心是找到目标进程的signal_struct结构体,修改其flags字段添加对应位;同时通过procfs节点接收用户输入的PID,完成用户态到内核态的交互。
完整代码实现
#include <linux/kernel.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/uaccess.h> #include <linux/sched/signal.h> #include <linux/capability.h> static struct proc_dir_entry *unkillable_proc; static ssize_t unkillable_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char pid_str[16]; pid_t pid; struct task_struct *task; struct signal_struct *sig; // 限制输入长度,防止缓冲区溢出 if (count > sizeof(pid_str) - 1) count = sizeof(pid_str) - 1; // 从用户空间拷贝输入内容 if (copy_from_user(pid_str, buf, count)) return -EFAULT; pid_str[count] = '\0'; // 将字符串转换为整数PID if (kstrtoint(pid_str, 10, &pid) != 0) return -EINVAL; // 通过PID查找对应的task_struct task = pid_task(find_vpid(pid), PIDTYPE_PID); if (!task) return -ESRCH; // 权限校验:仅root用户可执行修改操作 if (!capable(CAP_SYS_ADMIN)) { put_task_struct(task); return -EPERM; } // 加锁保护并发访问,修改SIGNAL_UNKILLABLE标记 sig = task->signal; spin_lock_irq(&sig->siglock); sig->flags |= SIGNAL_UNKILLABLE; spin_unlock_irq(&sig->siglock); // 释放task_struct引用,避免内存泄漏 put_task_struct(task); return count; } static const struct proc_ops unkillable_proc_ops = { .proc_write = unkillable_write, }; static int __init unkillable_init(void) { // 创建proc文件节点,权限设置为仅root可写 unkillable_proc = proc_create("unkillable", 0200, NULL, &unkillable_proc_ops); if (!unkillable_proc) { pr_err("Failed to create proc entry\n"); return -ENOMEM; } pr_info("Unkillable module loaded\n"); return 0; } static void __exit unkillable_exit(void) { proc_remove(unkillable_proc); pr_info("Unkillable module unloaded\n"); } module_init(unkillable_init); module_exit(unkillable_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Mark target process as SIGNAL_UNKILLABLE"); MODULE_AUTHOR("");
使用步骤
- 编译模块(需对应内核版本的头文件支持)
- 加载模块:
insmod unkillable.ko - 写入目标进程号:
echo [PID] > /proc/unkillable(替换[PID]为实际进程号) - 验证效果:向目标进程发送SIGKILL等致命信号,进程不会被终止
关键注意事项
- 权限控制:必须以root身份执行写入操作,普通用户无权限修改进程的signal标记
- 并发安全:修改
signal_struct->flags时必须持有siglock自旋锁,避免多CPU并发访问导致的数据竞争 - 资源释放:通过
pid_task获取task_struct后,必须调用put_task_struct释放引用,防止内存泄漏 - 内核版本兼容:代码基于5.x+内核编写,旧版本内核可能需要调整
pid_task、find_vpid等API的使用方式
内容的提问来源于stack exchange,提问作者jp_
相关产品推荐
相关产品推荐

