如何禁用 proc 文件的读取或写入功能?
Posted
技术标签:
【中文标题】如何禁用 proc 文件的读取或写入功能?【英文标题】:How to disable reading or writing functionality on a proc file? 【发布时间】:2021-07-11 21:37:54 【问题描述】:我正在创建一个 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,
;
【问题讨论】:
将它们指向一个返回错误代码的函数,例如EPERM
同样open()
函数可以检查他们是否指定O_RDONLY
、O_WRONLY
或O_RDWR
,并返回无效方向的错误。
@Barmar 如何将它们指向这些功能?能给我举个例子吗?另外,如何按照您的建议将权限设置为只读?这将完全按照我的意愿进行
什么意思?只需编写一个返回错误的函数key_proc_read
,然后使用.read = key_proc_read
写一个函数key_proc_open
检查打开模式。
【参考方案1】:
如果你想禁止读取,你可以省略显式设置struct file_operation
的.read
字段。如果结构体定义为static
,因此初始化为0
,所有没有显式覆盖的字段都将默认为NULL
,内核将根本不做任何事情并返回错误(我相信-EINVAL
)每当用户代码尝试在您打开的文件上调用 read
时。
或者,如果您想返回自定义错误,您可以定义一个只返回错误的虚拟函数(例如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,
不要这样做。您不需要使用预定义的操作。不要混合您创建的自定义函数和其他规范函数,例如用于序列文件的函数。序列文件需要执行一些初始化和拆卸,或者您使用 all seq_
系列文件操作,或者您自己手动执行,或者您不使用这些函数。在您的情况下,最后一个选项适用。
您可以将.release
设置为我上面显示的hello_proc_release()
,而不设置.llseek
(默认为NULL
)。
【讨论】:
以上是关于如何禁用 proc 文件的读取或写入功能?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 API 29 中弃用 getExternalStorageDirectory 时读取或写入文件?