
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)
フォーマットは%s
null文字に達するまでbuffから文字を印刷します。これはかなり遠いかもしれません。長さは、次に提供される長さに制限する必要があります。
printk("%*s\n",len,buff);