web-dev-qa-db-ja.com

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

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

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

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

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

Rootとしてコマンドを実行すると、何をしているのかがわかるはずです。カーネルはときどき何か危険なことを防ぐが、常にではない。 /dev/memは、自分が何をしているかを本当に知っているはずの、潜在的に危険なものの1つです。

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

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

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

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

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

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

物理アドレスへの書き込みについて説明する前に、この書き込みの前に行われるチェックについて説明します。ループ内で、カーネル構成オプション 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_DEVMEMはRAMにマップする物理メモリアドレスへのアクセスをブロックしますが、RAMにマップしないアドレスへのアクセスを許可します。許可される物理アドレスの範囲の詳細はプロセッサアーキテクチャによって異なりますが、それらすべてはRAMカーネルとユーザーランドプロセスのデータが保存される場所を除きます。追加オプション- CONFIG_IO_STRICT_DEVMEM (Ubuntu 18.04以降は無効)は、ドライバーによって要求された物理アドレスへのアクセスをブロックします。

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

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

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

一般に、ハードウェアレジスタへの読み取りまたは書き込みは、ハードウェアがプログラムされているすべてのことを行います。ハードウェアへのほとんどのアクセスはこのように機能します。ソフトウェア(通常はカーネルコード)は特定の物理アドレスにアクセスし、これがプロセッサをペリフェラルに接続するバスに到達し、ペリフェラルがその役割を果たします。一部のプロセッサ(特に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))'

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

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

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

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

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

仮想マシンUbuntu 18.04でこれを試行すると、Sudoを使用していても、ルートdd: writing to '/dev/mem': Operation not permittedの権限にかかわらず、エラーcrw-r-----が返されます。 buntu Wiki から:

/ dev/mem protection

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

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

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

12