You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在内核模块中将进程标记为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("");

使用步骤

  1. 编译模块(需对应内核版本的头文件支持)
  2. 加载模块:insmod unkillable.ko
  3. 写入目标进程号:echo [PID] > /proc/unkillable(替换[PID]为实际进程号)
  4. 验证效果:向目标进程发送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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:42:09