カーネルパニックメッセージが表示されないのはなぜですか?

カーネルパニックメッセージが表示されないのはなぜですか?

copy_to_userおよび機能を使用しないため、copy_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

テストでは、モジュールはnull値が見つかるまでアクセス可能なアドレスからデータを印刷するため、カーネルパニックが発生する理由はありません(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番目のnull文字で終わる理由はありません\0。したがって、data[7]初期化されていないランダムなデータは後に含まれます。

モジュールでこれを行うと、printk("%s\n",buff)フォーマットは%snull文字に達するまでbuffから文字を印刷します。これはかなり遠いかもしれません。長さは、次に提供される長さに制限する必要があります。

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

おすすめ記事