如何禁用 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,
不要这样做。您不需要使用预定义的操作。不要将您创建的自定义函数与其他规范函数(例如用于序列文件的函数)混合使用。序列文件需要执行一些初始化和拆卸,您可以使用 all 和 seq_
系列文件操作,或者您自己手动执行,或者您不使用这些函数。在您的情况下,最后一个选项适用。
您可以将 .release
设置为我上面显示的 hello_proc_release()
,而不设置 .llseek
(默认为 NULL
)。
我正在创建一个 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,
不要这样做。您不需要使用预定义的操作。不要将您创建的自定义函数与其他规范函数(例如用于序列文件的函数)混合使用。序列文件需要执行一些初始化和拆卸,您可以使用 all 和 seq_
系列文件操作,或者您自己手动执行,或者您不使用这些函数。在您的情况下,最后一个选项适用。
您可以将 .release
设置为我上面显示的 hello_proc_release()
,而不设置 .llseek
(默认为 NULL
)。