为什么我没有收到内核恐慌消息?

为什么我没有收到内核恐慌消息?

由于我没有使用copy_to_usercopy_from _user函数,因此以下内核模块应该向内核发出紧急消息。但我得到了正确的输出。架构是 ubuntu 14.04 LTE 上的 x86。

$ sudo mknod /dev/mem_char c 61 0
$ sudo chmod 777 /dev/char
$ echo 123asa >/dev/mem_char

dmesg 输出:

[  494.821648] mem_driver: module license 'unspecified' taints kernel.
[  494.821653] Disabling lock debugging due to kernel taint
[  494.821678] mem_driver: module verification failed: signature and/or  required key missing - tainting kernel
[  573.581104] data from user : 123asa
[  573.581104]  tushar!!
[  573.581104] eload
[  573.581104] t
[  573.581104] /bin/grub-script-check
[  573.581104] bkdf2
[  573.581104] e

模块代码:

#include<linux/module.h>
#include<linux/fs.h>
#include<linux/init.h>

ssize_t mem_read (struct file *, char __user *,size_t, loff_t *);
ssize_t mem_write (struct file *, const char __user *, size_t, loff_t *);
int mem_open (struct inode *, struct file *);
int mem_release (struct inode *, struct file *);

int major_no=61;    //if major no=0 then dynamic mean kernel alocate it 

struct file_operations fops={
    .open=mem_open,
    .read=mem_read,
    .write=mem_write,
    .release=mem_release,
};

ssize_t mem_read (struct file *fp, char __user *buff,size_t len,  loff_t *off)
{
    printk("buffer :%s \n",buff);
    return 0;
}
ssize_t mem_write (struct file *fp, const char __user *buff, size_t len, loff_t *off)
{
    //  char kbuff;
    //  printk("Function name : %s \n",__func__);
    printk("data from user : %s\n",buff);
    //    kmalloc();      
    return len;
}
int mem_open (struct inode *ip, struct file *fp)
{
    // printk("Function name : %s \n",__func__);
    return 0;
}
int mem_release (struct inode *ip, struct file *fp)
{
    // printk("Function name : %s \n",__func__);
    return 0;
}
static int mem_init(void)
{
    int ret;
    //        printk("mem_init\n");
    ret =register_chrdev(major_no,"mem_driver",&fops);
    if(ret<0)
    {
        //       printk("registetation fails with major no : %d",major_no);
        return ret; 
    }
    // printk("mem_driver register with major no %d\n",major_no);      
    return 0;
}
static void mem_exit(void)
{
    //  printk("exit\n");
    unregister_chrdev(major_no,"mem_driver");   
}
module_init(mem_init);
module_exit(mem_exit);

答案1

没有理由出现内核恐慌,因为在您的测试中,模块从可访问地址打印数据,直到找到空值为止(您应该使用数据的长度来限制 printk)。

然而,您可能会再次尝试相同的测试,但它会出现恐慌,因为您的程序(echo)已被调出内存!在这种情况下,访问数据会导致页面错误,这是将数据分页回内存的正常方法,但由于您没有使用copy_from_user(),内核必须假设页面错误是编程错误并且会出现恐慌。

这是在许多体系结构上使用的主要价值copy_from_user():它将这段代码标记为可能产生“合法”页面错误,应该将其作为对数据分页的请求进行正常处理(当它们发生在用户空间中时)。否则它只是一种优化memcpy()

该函数还对地址的有效性进行一些初步检查。看这个解释


从概念上讲,它echo 123asa是在用户空间中通过如下代码实现的

char data[1024];
memcpy(data,"123asa\n",7);
write(1,data,7);

其中复制到的字符串data有 7 个字符长,并且没有理由以第 8 个空字符结尾\0。因此,data[7]以后将包含随机的未初始化数据。

当您在模块中执行此操作时printk("%s\n",buff),格式%s将从 buff 打印字符,直到到达空字符,这可能很远。您应该将长度限制为中提供的长度

printk("%*s\n",len,buff);

相关内容