Por que não estou recebendo mensagem de kernel panic?

0

Como não estou usando copy_to_user e copy_from _user functions, o seguinte módulo do kernel deve dar ao kernel uma mensagem de pânico. Mas estou obtendo saída adequada. Arquitetura é x86 no Ubuntu 14.04 LTE.

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

saída 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

Código do módulo:

#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);
    
por Tushar Nimkar 03.09.2016 / 20:24

1 resposta

1

Não há razão para um pânico no kernel, já que em seu teste o módulo imprimiu dados de um endereço acessível até que um nulo fosse encontrado (você deveria ter usado o tamanho dos dados para limitar o printk).

No entanto, você pode tentar o mesmo teste outra vez e ele entrará em pânico porque seu programa (eco) foi paginado com falta de memória! Nesse caso, acessar os dados causa uma falha de página, que é o modo normal de ter os dados retornados à memória, mas como você não usou copy_from_user() , o kernel deve assumir que a falha de página é um erro de programação e entrará em pânico.

Este é o valor primário de usar copy_from_user() em muitas arquiteturas: ele marca esse código como potencialmente produzindo falhas de página "legais", que devem ser manipuladas normalmente (como quando ocorrem no espaço do usuário) como uma solicitação para página de volta nos dados. Caso contrário, é apenas uma espécie de memcpy() otimizado.

A função também faz algumas verificações preliminares sobre a validade do endereço. Consulte esta explicação .

O echo 123asa é conceitualmente implementado no espaço do usuário por código como

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

em que a cadeia copiada em data tem 7 caracteres e não tem motivos para terminar com um 8º caractere nulo data[7] . Portanto, printk("%s\n",buff) em diante conterá dados aleatórios não inicializados.

Quando em seu módulo você executa %s , o formato %code% imprimirá caracteres de buff até que ele atinja um caractere nulo, que pode estar muito distante. Em vez disso, você deve restringir o tamanho ao fornecido como

printk("%*s\n",len,buff);
    
por 04.09.2016 / 10:25