如何禁用 proc 文件的读取或写入功能?

How to disable reading or writing functionality on a proc file?

我正在创建一个 proc 文件 (/proc/key),用户可以将他的 decryption_key 写入其中,然后该密钥将用于解密存储在内核模块中的缓冲区的内容.此外,我还有另一个 proc 条目 (/proc/decrypted),它将用于读取存储解密文本的缓冲区的内容。

问题是我不希望用户能够向 (/proc/decrypted) 文件写入任何内容,也不希望他从 (/proc/key ).如何实施?

我已将 file_operations 结构中的相应函数指向 NULL,但显然,一旦用户尝试,这将导致分段错误。

如何防止从 procfs 读取或写入?我应该只创建没有主体的函数并在需要时将 file_operations 结构指向它们吗?

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char temp[128];
    memset(temp, 0, 128);
    int c; 
    c = copy_from_user(temp, buf, count);
 return count;
}


static const struct file_operations Proc_key_fops = {
 .owner = THIS_MODULE,
 .open = hello_proc_open,
 .read = NULL,
 .write = key_proc_write,
 .llseek = seq_lseek,
 .release = single_release,
};  

如果你想禁止阅读,你可以省略显式设置 struct file_operation.read 字段。如果结构定义为 static 并因此初始化为 0,则所有未显式覆盖的字段将默认为 NULL,内核将不执行任何操作并且 return 错误(我相信 -EINVAL)每当用户代码试图在你打开的文件上调用 read 时。

或者,如果您想 return 自定义错误,您可以定义一个仅 return 错误的虚拟函数(例如 return -EFAULT;)。

Do you think the way I am "writing" the key into the buffer is the right way to do it ?

由于多种原因,这是错误的。

首先,您的 copy_from_user() 盲目地信任用户 count,因此这会导致 temp 变量的内核缓冲区溢出,这是非常糟糕的。您需要先检查 and/or 限制大小。您也没有检查 copy_from_user() 的 return 值,您应该这样做(它不是 int,而是 unsigned long)。

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char temp[128];
    memset(temp, 0, 128);

    if (count > 128)
        count = 128; // or alternatively return -EINVAL or another error

    if (copy_from_user(temp, buf, count))
        return -EFAULT;

    return count;
}

现在代码更有意义了,但是变量 temp 仅在函数内部定义,因此在函数 returns 之后将丢失,您将无法使用它在其他文件操作函数中。如果你想这样做,你可以使用 filp->private_data,这是一个 struct file 的字段,正是用于此目的。

您应该在 open 上创建并初始化缓冲区,然后在 release 函数中释放它,如下所示:

static int hello_proc_open(struct inode *ino, struct file *filp) 
{
    void *buf = kmalloc(128, GFP_KERNEL);
    if (!buf)
        return -ENOMEM;

    filp->private_data = buf;

    // ... whatever else you need to do

    return 0;
}

static int hello_proc_release(struct inode *ino, struct file *filp) 
{
    kfree(filp->private_data);

    // ... whatever else you need to do

    return 0;
}

然后,在您的 write 中,您可以在将缓冲区转换为正确的类型后直接使用该缓冲区:

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char *temp = filp->private_data;
    memset(temp, 0, 128);

    if (count > 128)
        count = 128; // or alternatively return -EINVAL or another error

    if (copy_from_user(temp, buf, count))
        return -EFAULT;

    return count;
}

最后,我看到你在使用:

 .llseek = seq_lseek,
 .release = single_release,

不要这样做。您不需要使用预定义的操作。不要将您创建的自定义函数与其他规范函数(例如用于序列文件的函数)混合使用。序列文件需要执行一些初始化和拆卸,您可以使用 allseq_ 系列文件操作,或者您自己手动执行,或者您不使用这些函数。在您的情况下,最后一个选项适用。

您可以将 .release 设置为我上面显示的 hello_proc_release(),而不设置 .llseek(默认为 NULL)。