web-dev-qa-db-ja.com

(可能な場合)ユーザー空間からカーネル空間にアクセスする方法は?

ユーザーメモリーとカーネルメモリーは、Linuxカーネル内でどの程度正確に区別されますか(カーネルスペースにセキュリティを与えるという観点から)?

ユーザー空間からカーネルアドレス空間に書き込むにはどうすればよいですか

私が知る1つの方法は、システムコールを使用することです。使用できるシステムコールは複数ありますが、最終的にはすべてシステムコールになります。システムコールの場合でも、データをカーネルスペースに送信し、データ(ドライバーまたは各モジュール)がcopy_from_user()などの関数を呼び出して、ユーザースペースからカーネルスペースにデータをコピーします。ここでは、アドレス空間に正確に書き込んでいるわけではありません。カーネルバッファーにコピーする必要があるデータを含むユーザーポインターを渡しています。

私の質問は、カーネルスペースに存在する物理アドレスにアクセスして操作を実行する方法はありますか?

次に、システムコール以外に、ユーザーアプリケーションからカーネルスペースに書き込む方法は他にありますか?

私はこれをスタックオーバーフローから参照しました link 。しかし、私の質問はそこでは回答されておらず、別の視点からのものだと思います。したがって、私は別の質問をすることを考えました。

あなたの知識を共有してください...ありがとう。

22
mk..

ユーザー空間からカーネルアドレス空間に書き込む方法は何ですか?

他の方法があるかどうかはわかりませんが、_/dev/mem_とシステムコールmmap()を使用して物理メモリにアクセスできます。

/ dev/memは、コンピューターのメインメモリのイメージであるキャラクターデバイスファイルです。これは、たとえば、システムの調査(およびパッチの適用)に使用できます。 memのバイトアドレスは、物理メモリアドレスとして解釈されます。

_/dev/mem_の詳細: http://linux.about.com/library/cmd/blcmdl4_mem.htm

mmap()の詳細: http://linux.die.net/man/2/mmap

mmap()を使用して_/dev/mem_のセクションをマップし、ユーザープログラムで使用できます。簡単なコード例:

_#define MAPPED_SIZE //place the size here
#define DDR_RAM_PHYS  //place the physical address here

int _fdmem;
int *map = NULL;
const char memDevice[] = "/dev/mem";

/* open /dev/mem and error checking */
_fdmem = open( memDevice, O_RDWR | O_SYNC );

if (_fdmem < 0){
printf("Failed to open the /dev/mem !\n");
return 0;
}
else{
printf("open /dev/mem successfully !\n");
}

/* mmap() the opened /dev/mem */
map= (int *)(mmap(0,MAPPED_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,_fdmem,DDR_RAM_PHYS));

/* use 'map' pointer to access the mapped area! */
for (i=0,i<100;i++)
printf("content: 0x%x\n",*(map+i));

/* unmap the area & error checking */
if (munmap(map,MAPPED_SIZE)==-1){
perror("Error un-mmapping the file");
}

/* close the character device */
close(_fdmem);
_

ただし、マッピングしている領域がカーネルなどで使用されていないことを確認してください。そうしないと、システムがクラッシュ/ハングし、ハードウェアの電源ボタンを使用して強制的に再起動します。

それが役に立てば幸い。

23

ユーザーメモリーとカーネルメモリーは、Linuxカーネル内でどの程度正確に区別されますか(カーネルスペースにセキュリティを与えるという観点から)?

私があなたの質問を理解したかどうかわかりません。

カーネルにとって、技術的に大きな違いはありません。それは単なるメモリです。どうして?最も特権の高いCPUモードで実行されているカーネルがすべてのメモリにアクセスできるためです。

ユーザー空間からカーネルアドレス空間に書き込む方法は何ですか?

カーネルまたはカーネルモードのデバイスドライバーにセキュリティホールがない限り、少なくとも直接はできません。ただし、カーネル(またはそのドライバーの1つ)は、ユーザーモードアプリケーションのメモリからカーネルメモリにデータをコピーする場合があります。

...カーネルスペースに存在する物理アドレスにアクセスして、それに操作を実行する方法はありますか?

同様に、仮想アドレスから物理アドレスへの変換が存在する場合は、物理アドレスを使用してメモリにアクセスできないはずです。いったん有効になると、カーネル自体もこの変換を回避できません。任意の物理アドレスのメモリにアクセスするには、ページテーブルに適切な仮想アドレスから物理アドレスへのマッピングを作成する必要があります。

システムコールとは別に、ユーザーアプリケーションからカーネルスペースに書き込む方法は他にありますか?

例外をトリガーすることで、CPUにカーネルコードへの切り替えを強制することもできます(0による除算、ページ違反、一般保護違反など)。カーネルは、例外を処理する最初のカーネルです。カーネルは、例外に応じて必要に応じてメモリを変更します。ページフォールト時にどこか(ディスクなど)からデータをロードする場合があります。

4
Alexey Frunze