web-dev-qa-db-ja.com

非特権モードであっても、/ dev / memをmmapする方法は?

私の理解では、ユーザー空間プログラムは非特権モードで実行されるため、メモリやI/Oに直接アクセスできません。

次に、ユーザー空間プログラムで/ dev/memをmmapするときに、メモリまたはI/Oの場所に直接どのように正確にアクセスできますか?

例えば:

int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);

これは、組み込みデバイスで非常に一般的に使用されるハックです。

これで、変数ledsを即座に使用して、0x80840000に存在する可能性のある任意のデバイスにアクセスできます。

システムコールを使用してそのアドレスにアクセスすることはもうありません。

のようなものでも

leds[0x20] = val;

うまくいくでしょう。

ただし、I/Oアドレスへの直接の読み取り/ I/Oアドレスからの書き込みなどの特権操作は、システムコールを介してプロセッサを特権モードにすることによってのみ可能です。

ソース

4
Stark07

権限のないプロセスによる/dev/memへのアクセスを許可すると、セキュリティ上の問題が発生するため、許可しないでください。

私のシステムでは、ls -l /dev/memは次のようになります。

crw-r----- 1 root kmem 1, 1 Sep  8 10:12 /dev/mem

したがって、rootはそれを読み書きでき、kmemグループ(たまたま存在しないグループ)のメンバーはそれを読み取ることはできますが、書き込むことはできません。また、他の誰もそれを開くことはできません。したがって、これは安全なはずです。

/dev/memが私のものである場合、非特権プロセスは、mmapはもちろん、ファイルを開くことすらできなかったはずです。

システムの/dev/memの権限をチェックして、安全であることを確認してください!

7
Celada

ユーザープロセスに表示されるアドレス(rootとして実行されているか、特権のないユーザーとして実行されているかに関係なく)は仮想アドレスであり、ページテーブルを通じてMMUによって物理アドレスにマップされます。ページテーブルの設定は特権操作であり、カーネルコードによってのみ実行できますが、ページテーブルが設定されると、ユーザーモードでメモリへのアクセスが許可されます。

具体的には、コードはmmapを使用して、カーネルが特定の範囲の物理メモリにアクセスできるようにページテーブルを設定するように要求します。カーネルは、プロセスの特権(/dev/memへの読み取り/書き込みアクセス権を持っている)をチェックし、物理メモリにアクセスできるようにページテーブルを設定します。

4
jch

ledsの値は仮想アドレスです。現在のプロセスのユーザー空間にある限り、プロセスはRAMのどこにあるかに関係なく、特権モードである必要なく、leds[0] = valのような命令を介して直接アクセスできます。仮想アドレスはマッピングされます

0
xiaokaoy