我正在创建一个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
(。