【发布时间】:2017-10-08 20:06:37
【问题描述】:
在 Ubuntu 16.04 内核版本 4.4 中,可加载内核模块具有以下行为:
(使用字符串字面量)
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>
static int __init myinit(void)
{
char *path_name = "~/microsoft.gpg";
struct path path;
printk("Module Init\n");
if (kern_path(path_name, LOOKUP_FOLLOW, &path) < 0)
{
printk("kern_path fail\n");
return 0;
}
printk("kern_path success\n");
return 0;
}
static void __exit myexit(void)
{
printk("Module Exit\n");
return;
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL");
dmesg 的结果是
模块初始化
kern_path 成功
(使用字符串变量)
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#define MAX_PATH_LEN 256
static char path_name[MAX_PATH_LEN];
static struct proc_dir_entry *proc_file;
static int myopen(struct inode *inode, struct file *file)
{
printk("Module Open\n");
return 0;
}
static ssize_t mywrite(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
{
struct path path;
ssize_t bytes = count < (MAX_PATH_LEN - (*ppos)) ? count : (MAX_PATH_LEN - (*ppos));
if (copy_from_user(path_name, user_buffer, bytes))
return -EFAULT;
path_name[bytes] = '\0';
printk("Module Write\n");
if (kern_path(path_name, LOOKUP_FOLLOW, &path) < 0)
{
printk("kern_path fail\n");
(*ppos) += bytes;
return bytes;
}
printk("kern_path success\n");
(*ppos) += bytes;
return bytes;
}
static const struct file_operations fops =
{
.owner = THIS_MODULE,
.open = myopen,
.write = mywrite,
};
static int __init myinit(void)
{
printk("Module Init\n");
proc_file = proc_create("mymodule", 0644, NULL, &fops);
return 0;
}
static void __exit myexit(void)
{
printk("Module Exit\n");
remove_proc_entry("mymodule", NULL);
return;
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL");
在 shell 中输入的命令是
echo ~/microsoft.gpg > /proc/mymodule
dmesg 的结果是
模块初始化
模块打开
模块写入
kern_path 失败
我在写用户应用程序代码的时候没有遇到类似的问题,但是我真的很尴尬,因为内核模块有问题。
为什么问题会出现在第二个代码中?我该如何解决?
回答完成
【问题讨论】:
-
@UsagiMiyamoto 是一个指向“长偏移类型”对象的指针,表示用户正在访问的文件位置。
-
@UsagiMiyamoto 并且由于
user_buffer没有初始化,你需要在字符串的末尾添加'\0',使用count表示输入的长度。 -
@BronislavElizavetin 不幸的是,即使我加上双引号甚至将“~”更改为“/root”,结果似乎也没有改变。第一个代码工作正常,即使我尝试其他文件,第二个代码似乎也无法正常工作。
-
@UsagiMiyamoto“文件位置”不影响路径和名称。但是,如果您在 file_operations 的读取操作中不增加“文件位置”,则模块将无限循环。
-
@UsagiMiyamoto 我只想使用 proc 模块获取目标文件的文件系统名称。无需修改内核源代码。
标签: c linux-kernel