自毁驱动:动态卸载的艺术

项目简介

在本章节中,我们将探索一个非常有趣的Linux内核驱动项目:自毁驱动。这个驱动在加载后,会在sysfs中创建一个文件。当向该文件写入特定内容时,驱动会自动卸载自己。这种机制不仅展示了Linux内核的动态模块管理能力,还体现了sysfs文件系统的强大功能。

核心概念

实现步骤

  1. 在模块初始化函数中,使用sysfs_create_file在sysfs中创建文件。
  2. 实现该文件的write操作函数,检查写入的内容是否为特定字符串(如"selfdestruct")。
  3. 当检测到特定内容时,调用schedule_work安排一个工作队列任务,在安全上下文中执行卸载操作。
  4. 在工作队列处理函数中,使用request_moduledelete_module机制卸载自身模块。

代码示例

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/fs.h>
#include <linux/workqueue.h>

static struct kobject *selfdestruct_kobj;
static struct work_struct selfdestruct_work;

static ssize_t selfdestruct_write(struct file *filp, struct kobject *kobj,
                                  struct bin_attribute *attr,
                                  char *buf, loff_t off, size_t count)
{
    if (strncmp(buf, "selfdestruct", 12) == 0) {
        schedule_work(&selfdestruct_work);
        return count;
    }
    return -EINVAL;
}

static void selfdestruct_work_fn(struct work_struct *work)
{
    char *argv[] = { "/sbin/modprobe", "-r", "selfdestruct", NULL };
    char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
    call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}

static struct bin_attribute selfdestruct_attr = {
    .attr = {
        .name = "trigger",
        .mode = 0200,
    },
    .write = selfdestruct_write,
};

static int __init selfdestruct_init(void)
{
    int ret;
    selfdestruct_kobj = kobject_create_and_add("selfdestruct", NULL);
    if (!selfdestruct_kobj)
        return -ENOMEM;
    
    ret = sysfs_create_bin_file(selfdestruct_kobj, &selfdestruct_attr);
    if (ret) {
        kobject_put(selfdestruct_kobj);
        return ret;
    }
    
    INIT_WORK(&selfdestruct_work, selfdestruct_work_fn);
    return 0;
}

static void __exit selfdestruct_exit(void)
{
    cancel_work_sync(&selfdestruct_work);
    sysfs_remove_bin_file(selfdestruct_kobj, &selfdestruct_attr);
    kobject_put(selfdestruct_kobj);
}

module_init(selfdestruct_init);
module_exit(selfdestruct_exit);
MODULE_LICENSE("GPL");

关键函数说明

函数 描述
kobject_create_and_add 创建并添加一个kobject到sysfs中
sysfs_create_bin_file 在sysfs中创建二进制属性文件
schedule_work 安排一个工作队列任务异步执行
call_usermodehelper 从内核空间执行用户空间程序

架构图

用户空间 sysfs接口 内核空间 echo "selfdestruct" sysfs文件写入 驱动write函数 工作队列调度 模块卸载

注意事项