c-如何禁用proc文件的读写功能



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

问题是,我不希望用户能够向(/proc/decrypted(文件写入任何内容,也不希望他从(/proc/key(中读取任何内容。如何实现这一点?

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

我怎样才能阻止监考生阅读或写作?我应该只创建没有正文的函数,并在需要时将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,并且每当用户代码试图在打开的文件上调用read时,内核将不会执行任何操作并返回错误(我相信-EINVAL(。

或者,如果要返回自定义错误,可以定义一个只返回错误的伪函数(例如return -EFAULT;(。

你认为我是这样的吗;书写";把钥匙插入缓冲区是正确的方法吗?

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

首先,您的copy_from_user()盲目信任用户count,因此这会导致temp变量上的内核缓冲区溢出,这非常糟糕。您需要先检查和/或限制大小。您也没有检查copy_from_user()的返回值,这是您应该检查的(它不是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仅在函数内部本地定义,因此在函数返回后将丢失,您将无法在其他文件操作函数中使用它。如果要执行此操作,可以使用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,

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

您只需将.release设置为上面显示的hello_proc_release(),然后不设置.llseek(默认为NULL(。

最新更新