dd if = / dev / urandom of = / dev / memは安全ですか?


10

これは正確に何をしますか?これでベースメモリにアクセスする方法がわかりません...ちょっと変だと思います。安全ですか?

dd if=/dev/urandom of=/dev/mem

あなたが話すこの「安全」は何ですか?何に関して安全ですか?
ワルティネーター

このコマンドで何を達成したいですか?
jochen

回答:


23

家でこれを試さないでください!システムがクラッシュする可能性があり、本当に運が悪いと、周辺機器が損傷したり、コンピュータが起動できなくなる可能性があります。

実際、ほとんどのプラットフォームでは、エラーで失敗するだけですが、それはハードウェアアーキテクチャによって異なります。非特権ユーザーとしてコマンドを実行しない限り、これが無害であるという保証はほとんどありません。権限のないユーザーの場合、コマンドを開くことができないため、コマンドは完全に無害です/dev/mem

rootとしてコマンドを実行すると、自分が何をしているかがわかるはずです。カーネルは時々危険なことをすることを防ぎますが、常にではありません。/dev/mem自分が何をしているかを本当に知っているはずの、潜在的に危険なことの1つです。

/dev/memLinuxで書き込みがどのように機能するかを説明します。一般的な原理は他のUnicesでも同じですが、カーネルオプションなどはまったく異なります。

プロセスがデバイスファイルを読み書きするときに何が起こるかは、カーネル次第です。デバイスファイルへのアクセスは、このデバイスファイルを処理するドライバーでいくつかのコードを実行します。たとえば、への書き込みにより/dev/memの関数write_memdrivers/char/mem.c呼び出されます。この関数は4つの引数を取ります。開いているファイルを表すデータ構造、書き込むデータへのポインター、書き込むバイト数、およびファイル内の現在の位置です。

呼び出し元が最初にファイルを開く権限を持っている場合にのみ、これまでに取得することに注意してください。デバイスファイルは、通常、ファイルのアクセス許可に従います。の通常の権限は/dev/memcrw-r-----所有root:kmemしているため、rootにならずに書き込み用に開こうとすると、「権限が拒否されました」(EACCESS)になります。しかし、あなたがrootである場合(またはrootがこのファイルのアクセス権を変更した場合)、オープニングは通過し、書き込みを試行できます。

write_mem関数内のコードはいくつかの健全性チェックを行いますが、これらのチェックだけではすべての問題から保護するのに十分ではありません。まず、現在のファイル位置*pposを物理アドレスに変換します。それが失敗した場合(実際には、32ビットの物理アドレスを持つプラットフォーム上に64ビットのファイルオフセットがあり、ファイルオフセットが2 ^ 32より大きいため)、書き込みはEFBIG(ファイルが大きすぎる)で失敗します。次のチェックは、書き込む特定の物理アドレスの範囲がこの特定のプロセッサアーキテクチャで有効であるかどうかであり、障害が発生するとEFAULT(不良アドレス)が発生します。

次に、Sparcとm68kでは、最初の物理ページでの書き込みのどの部分も黙ってスキップされます。

これで、1つのMMUページに収まるブロック内のデータを反復処理するメインループに到達しました。 は、仮想メモリではなく物理メモリにアクセスしますが、データをメモリにロードして格納するプロセッサ命令は仮想アドレスを使用するため、コードは物理アドレスを仮想アドレスにマップするように調整する必要があります。Linuxでは、プロセッサアーキテクチャとカーネル構成に応じて、このマッピングは永続的に存在するか、オンザフライで作成する必要があります。それが仕事です(そして何をしても元に戻します)。次に、関数は渡されたバッファから読み取ります/dev/memxlate_dev_mem_ptrunxlate_dev_mem_ptrxlate_dev_mem_ptrcopy_from_userwriteシステムコールし、物理メモリが現在マップされている仮想アドレスに書き込むだけです。コードは通常のメモリストア命令を発行し、これが何を意味するかはハードウェア次第です。

物理アドレスへの書き込みについて説明する前に、この書き込みの前に行われるチェックについて説明します。ループ内ではpage_is_allowed、カーネル構成オプションCONFIG_STRICT_DEVMEMが有効になっている場合(デフォルトではこの場合)、関数は特定のアドレスへのアクセスをブロックします。許可されたアドレスにのみdevmem_is_allowed到達できます。/dev/memその他の場合、EPERMで書き込みが失敗します(操作は許可されません)。このオプションの説明は次のとおりです。

このオプションがオンで、IO_STRICT_DEVMEM = nの場合、/ dev / memファイルは、PCIスペースとBIOSコードおよびデータ領域へのユーザースペースアクセスのみを許可します。これは、dosemuとX、および/ dev / memのすべての一般的なユーザーにとって十分です。

これは非常にx86中心の説明です。実際、より一般的には、CONFIG_STRICT_DEVMEMRAMにマップする物理メモリアドレスへのアクセスをブロックしますが、RAMにマップしないアドレスへのアクセスを許可します。許可される物理アドレスの範囲の詳細は、プロセッサアーキテクチャによって異なりますが、カーネルとユーザーランドプロセスのデータが保存されているRAMはすべて除外されます。追加オプションCONFIG_IO_STRICT_DEVMEM(Ubuntu 18.04では無効)は、ドライバーが要求する物理アドレスへのアクセスをブロックします。

RAMにマップする物理メモリアドレス。それでは、RAMにマップしない物理メモリアドレスはありますか?はい。これは、アドレスに書き込むことが何を意味するかについて上記で約束した議論です。

メモリストア命令は必ずしもRAMに書き込む必要はありません。プロセッサはアドレスを分解し、ストアをディスパッチするペリフェラルを決定します。(私が「プロセッサ」と言うとき、私は同じ製造元から来ていないかもしれない周辺機器コントローラを含みます。)RAMはそれらの周辺機器の1つにすぎません。ディスパッチがどのように行われるかは、プロセッサアーキテクチャに大きく依存しますが、基本はすべてのアーキテクチャでほぼ同じです。プロセッサは基本的にアドレスの上位ビットを分解し、ハードコードされた情報、一部のバスをプローブして得られた情報、およびソフトウェアによって構成された情報に基づいて入力されたいくつかのテーブルでそれらを検索します。多くのキャッシングとバッファリングが含まれる可能性がありますが、簡単に言えば、この分解の後、バスとそれを処理するのは周辺機器次第です。(または、テーブルルックアップの結果、このアドレスにペリフェラルが存在しない可能性があります。その場合、プロセッサはトラップ状態に入り、通常は呼び出しプロセスのSIGBUSとなるカーネル内のコードを実行します。)

RAMにマップするアドレスへのストアは、以前にこのアドレスに格納されていた値を上書きする以外は何も「実行」せず、同じアドレスで後でロードすると最後に格納された値が返されることが保証されます。ただし、RAMにも、このように動作しないアドレスがいくつかあります。リフレッシュレートや電圧などを制御できるレジスタがいくつかあります。

一般に、ハードウェアレジスタへの読み取りまたは書き込みは、ハードウェアが実行するようにプログラムされているものは何でも実行します。ハードウェアへのほとんどのアクセスはこのように機能します。ソフトウェア(通常はカーネルコード)は特定の物理アドレスにアクセスし、これがプロセッサをペリフェラルに接続するバスに到達し、ペリフェラルがその役割を果たします。一部のプロセッサ(特にx86)には、メモリのロードおよびストアとは異なるペリフェラルへの読み取り/書き込みを引き起こす個別のCPU命令もありますが、x86でも、ロード/ストアを介して多くのペリフェラルに到達します。

このコマンドdd if=/dev/urandom of=/dev/memは、アドレス0(および書き込みが成功する限り、後続のアドレス)にマップされているペリフェラルにランダムデータを書き込みます。実際には、多くのアーキテクチャでは、物理アドレス0にペリフェラルがマッピングされていないか、RAMが割り当てられているため、最初の書き込みは失敗します。ただし、アドレス0にマップされたペリフェラルがある場合、またはコマンドを変更して別のアドレスに書き込む場合、ペリフェラルで予測できない何かがトリガーされます。ランダムなデータが増加するアドレスにあると、興味深いことをする可能性はほとんどありませんが、原則として、コンピューターの電源をオフにし(実際にこれを実行するアドレスがある可能性があります)、ブートを不可能にするBIOS設定を上書きしたり、それを損傷する方法でバギー周辺機器。

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'

ありがとうございました!これは私が探していたものです!/ dev / memが周辺機器やハードウェア関連のようなものへのメモリアクセスを許可するかどうかだけで混乱しました!
Coder14

周辺機器は、x86 PCの物理アドレス0にマッピングできません。その構成は決して起動しません。
ジョシュア

これは真実ではありません
イヴァン、

1
もちろん、カーネルにはダメージを与えますが、BIOSにはダメージを与えません
Yvain

1
@イヴァンが真実ではないのですか?とCONFIG_STRICT_DEVMEM有効になっている場合、実際にはカーネルを損傷することはできません。
Gilles「SO-邪悪なことをやめ

12

カーネルが適切に構成されていれば安全です(機能しないため安全です)

マニュアルページごとのmem(4)

/ dev / memは、コンピューターのメインメモリのイメージであるキャラクターデバイスファイルです。これは、たとえば、システムを検査(およびパッチを適用)するために使用できます。

したがって、理論dd if=/dev/urandom of=/dev/mem的には、インストールした物理メモリのアドレス空間全体を上書きする必要があります。カーネルやその他のプログラムはメモリから実行されるため、システム効果的にクラッシュさせるはずです。実際には限界があります。同じmanページから:

Linux 2.6.26以降、アーキテクチャによっては、CONFIG_STRICT_DEVMEMカーネル構成オプションにより、このファイルを介してアクセスできる領域が制限されています。

これを仮想マシンUbuntu 18.04で試すと、rootの権限がdd: writing to '/dev/mem': Operation not permittedあってもなくてもエラーが返されます。Ubuntu Wikiから:sudocrw-r-----

/ dev / mem保護

一部のアプリケーション(Xorg)では、ユーザー空間から物理メモリに直接アクセスする必要があります。このアクセスを提供するために、特別なファイル/ dev / memが存在します。以前は、攻撃者がrootアクセス権を持っている場合、このファイルからカーネルメモリを表示および変更することが可能でした。CONFIG_STRICT_DEVMEMカーネルオプションは、非デバイスメモリアクセスをブロックするために導入されました(元の名前はCONFIG_NONPROMISC_DEVMEM)。

つまり、技術的には安全ではありません(システムをクラッシュさせるため)。カーネルオプションCONFIG_STRICT_DEVMEMが無効になっているとセキュリティホールになりますが、これまでのところ、そのオプションが有効になっているとコマンドは実行されません。クロスサイト複製によると、再起動で問題が修正されますが、もちろん、その時点でのRAM内のデータは失われ、ディスクにフラッシュされません(必要な場合)。

以前にリンクを使用して複製された複製に推奨される方法があるbusybox devmemため、RAMをいじくり回すことが決まっている場合は、やっぱり方法があるかもしれません。


6
「安全です」いいえ、確かに安全ではありません。を使用してもCONFIG_STRICT_DEVMEM、ペリフェラルがマップされているメモリ領域にアクセスできます/dev/mem。これがの重要なポイントです。周辺機器にランダムなものを書き込むと、何かが起こる可能性があります。マップされていないアドレスにアクセスしようとすると、「操作は許可されません」というメッセージが表示され、コマンドはアドレス0から始まります。アドレス0が何かにマップするかどうかは、ハードウェアアーキテクチャによって異なります。PCのどこにもマッピングされない可能性があることはすべて知っていますが、一般的に安全ではありません。
Gilles 'SO-悪をやめなさい' 19/07/27

1
@Gilles x86(x86-64については不明)では、RAMの最初の1 KiB(アドレス0x0〜0x3ff)が割り込みベクトルを保持します。ベクトルごとに4バイトのアドレス。ランダムなゴミでそれらを上書きすることに成功した場合、あらゆる種類の興味深いことがすぐに発生する可能性があります。ほとんどの場合、二重または三重の障害が発生し、システムがクラッシュしますが、保証はありません...
CVn

@aCVn確かに何かがマップされています(head -c 1024 </dev/mem | od -tx1)が、プロセッサがリアルモード(8088モード)でないときにこれらが使用されるかどうかはわかりません。私はそれらが64ビットモードで使用できるとは思いません。結局のところ、8088割り込みベクトルはアドレスに32ビットしかありません。ちなみに、これはCONFIG_STRICT_DEVMEMsetでアクセスできるので、Linuxでは使用しないと思います。
Gilles 'SO-悪をやめ

@ギレス:x86の0ページはv86、ブートローダーなどのために予約されています。これがリアルモードの割り込みベクタテーブルです。プロテクトモードでは、IVTは別の場所にあります(マシンレジスタはどこにあるかを示します)。
ジョシュア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.