図 7 0 5 し inux のプートプロセス ヒープ カーネルを展開するパッファ 2000H lOW buffer Size IOW buffer start 100000H メモリホール 90000 A0000H low buffer end end 圧縮カ ーネル end high_buffer_start if ( ( 0X100000 + low buffer_size) > ((ulg)high_buffer_start)) の場合 2000H 0 90000 A0000H 100000H メモリホールこ圧縮カーネルヒープ ・← low buffer size →・ lOW buffer_size low buffer start low buffer_end に示すソースコードは、誌面の都合上、一にを編集してい 0343 : high_buffer_start mv—>high—buffer—start high—buffer—start ; ます ) 。 0324 : 0325. 0326 : 0332 : 0333 : 0335 : 0336 : 0337 : 0338 : 0339 : 0340 : 0341 : 0342 : 56 static VOid setup—output—buffer run—high (struct moveparams *mv) high—buffer—start = (uch * ) ( ( (ulg)&end) + 0X3000 ) ; mv—>low-buffer_start output—data = 0X2000 ; low—buffer_end = 0X90000 ; low—buffer—size = low_buffer—end ー 0X2000 ; high—loaded = 1 ; free—mem—end—ptr = (long) high—buffer—start ; _if_ if ( ( 0X100000 + low—buffer_size) > ( (ulg)high-buffer—start) ) { ( 0X100000 + low_buffer_size) ; high—buffer—start = (uch * ) mv—>hcount = 0 ; else mv—>hc ount 0344 : } ちょっと見には理解しにくそうなコードですが、図解す るととくに難しくはありません。図 7 に 324 ~ 344 行目を 実行した結果を示します。この図で網がかかっている部分 は、展開ルーチン gunzip がカーネルの展開結果を書き込 むためのプロックで、低位アドレスから順に埋められてい きます。 338 行目の条件文が成立する場合には、 high-buffer- start カ甘旨す位置を図 7 のように右にすらします。ここで ポインタをすらすのは、あとでコピー処理の回数を減らす ためです。 実際のコピー処理は、 decompress-kernel からアセン プリ・ルーチンに戻ったあとでおこないます。詳しくは後 述しますが、ごく簡単に説明すると、 338 行目の条件文が 成立しない場合には、展開結果を図 8 のようにコピーして カーネルを連結します。一方、 338 行目の条件文か成立す る場合は、あらかしめ high-buffer-start を右にすらして UNIX MAGAZINE 2002.9
5 。し inux のブートプロセス int decompress—kernel (struct movepara-ms *mv , void *rmode) struct moveparams { unsigned char *low—buffer—start ; int lcount ; unsigned char *high—buffer—start ; int hcount ; decompress-kernel は、展開後のカーネルを配置した プロックのアドレスとその大きさを moveparams 構造体 で返します。 図 6 スタック上に確保した moveparams ・← 4 バイト→・ moveparams hcount high_buffer_start lcount low buffer start 90000H スタ ・← ESP 領域 0067 : 0068 : 0069 : 0070 : 0071 : subl $16,%esp # for moveparams movl %esp , %eax ー ) rmode pushl %esi # = 90000H pushl %eax # moveparams 一分 mv call SYMBOL_NAME (decompress—kernel) 67 ~ 68 行目では、 16 バイトの moveparams 構造体の 領域をスタックのなかに確保しています。スタックのなか に領域を確保しているのは、あとで構造体の内容を POP 命令によって取り出せるようにするためです。 69 ~ 70 行目は、 decompress-kernel に渡す引数をス タックに積む処理をおこなっているところで、サプルー チンのなかでは ESI の内容が変数 rmode で、 move- params 構造体のアドレスが変数 mv でアクセスされま す。 69 行目の ESI レジスタには、セットアップ・ルーチ ンの 779 ~ 783 行目で設定した 90000H が入っています。 以 E の操作により、 decompressAcernel を呼び出す直 前のスタックの内容は図 6 のようになります。 圧縮カーネルを展開する 圧縮カーネルを展開するルーチン decompress-kernel は、ファイル misc. c に書かれています。 0376 : 0377 : 0378 : 0379 : 0380 : 0381 : 0382 : 0383. makecrc() ; return high—loaded ; close—output—buffer-if—we-run-high(mv) ; if (high—loaded) puts ( "Ok , booting the kernel. \ Ⅱ” ) ; gunzip() ; puts ("Uncompressing Linux. 0111 : 0112 : 0359 : 0360. 0361 : 0374 : 0375 : extern int end ; static 10 Ⅱ g free—mem—ptr = (long) &end ; int decompress—kernel ( Struct moveparams , VOid *rmode) setup-output—buffer—if—we—run-high(mv) ; else setup—normal—output—buffer() ; if (free—mem-ptr く 0X100000 ) real_mode = rmode ; UNIX MAGAZINE 2002.9 112 行目のポインタ free-mem-ptr は、 head. S の 59 行目と同しく BSS 領域の最終アドレスを指します。 bzlmage 形式のカーネルは、リニアアドレス 100000H 以降で動作するようにコンパイルされています。そのた め、必然的に free-mem-ptr の値は 100000H よりも 大きいはすです。よって、サプルーチン setup-output- buffer-if-we-run-high カ鮃び出され、そのなかで或変 数 high 」 oaded の値が 1 に設疋されます。 Ok , booting the kernel. ネルを展開します。最後に、 というメッセージを表示し、サプルーチン gunzip がカー Uncompressing Linux. そして、画面ーヒに、 55 high-bufferstart に設定する処理をおこないます ( 以下 を算出し、 moveparams 構造体の low-buffer-start と は、カーネルの展開結果を書き出すプロックのアドレス サプノレーチン setup-output-buffer-if-we-run-high を表示し、アセンプリのルーチンに戻り値 1 を返します。
5 し inux のプートプロセス 図 8 図 9 展開後のカーネルを移動する ( パターン 1 ) lcount ℃ ou nt 100000H コピー hcount high_buffer_start コピー できあがり ! 展開後のカーネルを移動する ( パターン 2 ) 100000H hcount=0 がバッフアに書き込んだバイト数、つまりカーネル・プロ グラムのサイズか格納されています。このルーチンでは、 moveparams 本懾 j 匿一本の lcount と hcount を言乂疋し、テ。ー タを完成させます。 展開後のカーネルを連結する decompress-kernel ばイ孫宿されたカーネルを展開しま すが、展開した結果は IMB 末岡のアドレスと、 IMB 以 上のアドレスにう地「されて配置されています。 次におこなう処理は、物理アドレス 100000H 以降の アドレスにコピーして連結することです。ところが、実 行中のプログラムも同しアドレスに位置しているため、そ のままコピーしてしまうと実行中のプログラムが上書き されてしまいます。そこで、 move-routine-start から move-routine-end までのコピールーチンを物理アドレ ス 1000H , 幻医し、実際のコピー処理は 1000H にジャ ンプしておこないます。 コピー high_buffer_start できあがり ! 0086 : 0087 : 0088 : 0089 : 0090 : 0091 : 0092 : 0093 : 0094 : 0095 : 0096 : 0097 : 0098 : 0099 : 0100 : 0101 : 0102 : 0103 : 0104 : movl movl movl subl addl shrl cld rep movsl cli movl popl popl popl popl popl popl $move_routine_start , /oesi $ 0X1000 , % edi $move_routine_end ,%ecx %esi,%ecx $2,%ecx $ 3 ,%ecx おくことによって、図 9 のように 1 回のコピーでカーネル がおこなわれます。 output-buffer-if-we-run-high か平び出され、事後処理 サプルーチン gunzip による展開か終ったあと、 close- を連結することができるのです。 %ebx 0/oecx %edx %eax # discard the address real mode pointer # low_buffer_start lcount # high—buffer—start # hcount 0346 : 0347 : 0348 : 0349 : 0350 : 0351 : 0352 : 0353 : 0354 : 0355 : 0356. static void close—output—buffer—if—we run—high (struct moveparams *mv) if (bytes—out > low—buffer—size) { low_buffer_size; bytes—out mv—>hcount = (mv—>hcount) mv—>lcount = low_buffer_size; else if $ 0X100000 , %edi ljmp $(——KERNEL_CS) , $ 0X1000 mv—>lcount mv—>hcount bytes—out ; = 0 ; 348 行目の変数 bytes-out には、サプルー UNIX MAGAZINE 2002.9 チン gunzip 0110 : move_routine_start : 0128 : move_routine_end : サプルーチン decompress-kernel を実行しているあい だ、スタックカ叩」用されて ESP レジスタも変更されます が、その呼出しの前後で ESP レジスタの内容は同し値に 戻ります。これは、 C 言語で書かれたサプルーチンの仕様 です。 57
5 のし inux のプートプロセス そのため、 96 行目で POP されるデータは 70 行目で PUSH したデータであり、 97 行目の pop では 69 行 目で PUSH したデータカ陬り出されます。こでおもし ろい点は、 98 ~ 101 行目の POP 命令で moveparams 構造体の内容を取り出していることです。これは、 move- params 構造体の領域をスタックに石呆したためにおこな える操作です ( 図 6 ) 。 ーヨ / イ 取後に、 104 行目の LJMP ・命令で 110 行目へジャン プします。 0110 : 0111 : 0112 : 0113 : 0114 : 0115 : 0116 : 0117 : 0118 : 0119 : 0120 : 0121 : 0122 : 0123 : 0124 : 0125 : 0126 : 0127 : 0128 : 111 move_routine_start : movl %ecx , %ebp shrl $2,%ecx rep movsl movl %ebp ,%ecx andl $3,%ecx rep movl %edx ,%esi movl %eax ,0/oecx addl $ 3 , %ecx shrl $2,%ecx rep movsl movl %ebx , %esi xorl %ebx ,%ebx このサプルーチンは 1000H にコピーされて # から、実行される $ 0X100000 ljmp $ (——KERNEL_CS) , move_routine_end : ~ 118 行目では low-buffer-start から始まるプロ ックを、そして 119 ~ 124 行目では high-buffer-start か は無視されるため、結 : 勺に図 9 のように 1 回のコピーし いる状態で REP 命令を実行すると、次の MOVSL 命令 されています。そして、 ECX レジスタに 0 か、設定されて は、 EAX レジスタで度される hcount の値には 0 か疋 以降のプロックをコピーする必要がありません。このとき ただし、図 9 のパターンの場合は、 high-buffer-start ら始まるプロックをコピーします ( 図 9 ) 。 58 へジャンプして本物のカーネルを起動します。 最後に、 90000H を ESI レジスタにオ褓内し、 レス 100000H 以降に配置されます。 以のコピー処理によって、展開されたカーネルがアド かおこなわれません。 100000H 付録 : アセンブリ命令一覧 前回と今回に登場したアセンプリ命令の一覧を以下にま とめておきます。本文で引用しているコードを読むときの 参考にしてください。 add [bwl] 叩ノ , 叩 2 叩ノと叩 2 を加算した結果を叩 2 にオ褓内します。 and [bwl] 叩ノ , 叩 2 叩ノと叩 2 を AND した結果を叩 2 にオ内します。 call 夘 叩カ甘旨すアドレスをサプルーチン呼出しします。 cbtw AL レジスタの内容を符号拡張して AX レジスタに格 納します。 cld EFLAGS レジスタの DF フラグをクリアします。 外部割込みを無視する状態にします。 cmp [bwl] 叩ノ , 叩 2 叩ノと叩 2 の内容を上は交し、その結果を以下のように EFLAGS レジスタのフラグに反映させます。 0 ノ > 叩 2 CF=I 、 ZF=O 叩ノ 叩 2 CF=O 、 ZF=I 0 ノ < 0 を 2 CF=O 、 ZF=O int れれ 7 れ べクタ番号れ社 m のソフトウェア割込みを発生させま す。 .Jae 0 〃 EFLAGS レジスタが CF=O の場合、叩カ甘旨すアド レスにジャンプします。 jbe 0 EFLAGS レジスタが CF=I または ZF=I の場合、 叩カ甘旨すアドレスにジャンプします。 JC 夘 EFLAGS レジスタが CF=I の場合、 0 〃カ甘旨すアド レスにジャンプします。 Jnc 0 jae と同しです ( 別名です ) 。 cli UNIX MAGAZINE 2002.9
し洄臧 0 宮地利幸、田淵貴昭 Linux 関連のソフトウェアの更新情報をお届けする。 カーネル 2.5.23 占についてまとめてお伝えする。 今回は、開発阪カーネル 2.5.23 ~ 2.5.26 のおもな変更 *Linux カーネル 1394 、 USB の「更辛万、 JFS の多正、 NTFS 2.0.20 への ARM アーキテクチャ部分のコードの修正、 IEEE カーネノレ 2.5.26 樹冓か有効となったため、高速イミ期待できる。 ext2 、 ext3JBJ 汐トのファイノレシステムでもこのキャッシュ テムでは、コード量カ鰔り、高速イゞ図られた。さらに、 た。この変更によって、 ext2 および ext3 ファイルシス buffer-head cache が削除され、 fs/buffer. c に移され また、 ext2 、 ext3 ファイルシステムの LRU による スケジューラの修正、 NTFS 2.0.14 への更新など。 修正、 USB の更新、 Matrox フレームバッフアの修正、 ppc32 アーキテクチャ部分のコードの修正、 kbuild の カーネル 2.5.25 新、 NTFS 2.0.10 への史新など。 新、 kbuild 関連の修正、 IrDA 部分と ISDN 部分の更 IDE ドライバ、および各種ネットワーク・ドライノヾの更 スレッドでの競合など JFS の修正、 ALSA ドライバ、 カーネノレ 2.5.24 の修正など。 正、スケジューラの挙加力の第多正、 ext3 ファイルシステム キテクチャ部分のコードの更新、 i386 での initrd の修 S390 各アーキテクチャ部分のコードの修正、 X86 ー 64 アー kbuild ( カーネルのピルドシステム ) の改良、 sparc64 、 ネットワーク関連のコードの更新とサイズの縮小、 152 更新など。 *Debian GNU/Linux 3.0 Debian プロジェクトは、 7 月 19 日に Debian GNU/ Linux 3.0 (woody) をリリースした。これまでのバージ ョンでサホートしていた lntel X86 、 Motorola 680X0 、 Alpha 、 SPARC 、 PowerPC 、 ARM に加え、 3.0 では 以下のプラットホームもサポートされた。 ・ MIPS (mips (Big Endian) と mipsel (Little En- dian)) ・ lntel ltanium (ia64) ・ HP PA-RISC (hppa) ・ S / 390 ( S390 ) これで、 Debian では合言 10 のプラットホームがサ ポートされたことになる。 Linux カーネルは 2.2.20 を採用している。 - 丘は 2.4- 系のカーネルを採用するディストリビューションが多い が、 Debian のリリースチームは、 2.4 系のカーネルは未 成熟と判断して採用を見送ったとのことである。ただし、 リリースにカーネル 2.4.18 も含まれているため、ユーサ ーが追加インストールすることは可能である。 また、このリリースから名前が変更されたパッケージ や、複数個に分割されたり、 1 つにまとめられたパッケー ジもあるため、新たにパッケージをインストールするとき は注意が必要だろう。 旧バージョンからのアッフデートには、 apt-get では なく dselect の利用力甘隹奨されている。アップデートの 際にはいくつか注意点があるため、 Debian プロジェクト のページを石忍しながらおこなうことをお勧めする。 Kondara プロジェクト解散 Kondara プロジェクトは、 7 月 15 日をもって角鞴攵し た。これは、デジタルファクトリ株式会社から有限会社 工スピーへの Linux 事業の一部譲渡を受けての決定であ る。これまで、デジタルファクトリは Kondara プロジ ェクトに対して、商標 (Kondara と mph) の使用許可、 サーバーマシンと回線の提供をおこなっていたが、この措 置が今後も絲売されるかカ坏明になった。そこで、 Kon- dara フロジェクトでは「 Kondara 」の名称の返還とフ ロジェクトの解散を決定した。現在は、 kondara.org の サーバーやサービスはすべて停止している。 UNIX MAGAZINE 2002.9
lnform 攻撃者は、攻撃対象のシステムにおけるネットワーク・ サーピスから、自身の管理する DNS サーバーに対して DNS 要求を送らせることができる。結果として、攻撃 者はリモートからこの脆弱性を利用できることになる。 影響を受けるシステム 以下に示す DNS リゾノレヾ・ライプラリの実装、およ びこれらのライプラリを利用するすべてのアプリケーシ ・ libbind : ISC (lnternet Software Consortium) BIND DNS リゾルノヾ・ライプラリ ・ libc: BSDDNS リゾノレヾ・ライプラリ ・ glibc : GNU DNS リゾノレヾ・ライプラリ 前回以降、 CERT から 3 つのアドバイザリが発行さ れた。 DNS リゾルバのバッフア・オーバーフローに関する脆 弱性は、 ) 危囲に景をおよはすおそれがある。べンダー などから公開される情報に一ト分注意すべきである。 なお、 GNU DNS リゾノレヾ・ライプラリ (glibc) につ いてのは、アドバイサリの改訒版 ( 7 月 10 日発行 ) 以 降に掲載されている。このようにアドバイザリは随日れ攵訂 されているので、 CERT の Web ページをこまめにチェ ックして改訒版の有無を石忍すべきである。また、各アド バイザリの末尾には、、 Revision History ( 改言廨己録 ) " が 記されているので、この部分にかならす目をとおす習慣を つけておこう。 ◆ CERT Advisory より CA -2002-19 ・ Buffer Overflow in Multiple DNS Resolver Libraries 2002 年 6 月 28 日発行 概要 DNS リゾノレヾ・ライプラリのいくつかの実装には、バッ フア・オーバーフローに起因する脆弱匪か存在する。 れらの DNS リゾノレヾ・ライプラリを利用している OS とアプリケーションは、すべて影響を受けるおそれが ある。 DNS とは、 IP ネットワークにおいてホスト名、 IP ア ドレスなどの情報を提供する樹冓である。これらの清報 を取得するために、ネットワーク・アプリケーション は、、リゾノレヾ " を利用する。リゾノレヾは、 OS に付属の ライプラリとして実装されていることが多い。 リモートの攻撃者が、この脆弱性を衝く DNS 応答を 返し、攻撃対象のシステム上で任意のコードを実行した り、サービス妨害攻撃をおこなう可能性がある。攻撃者 によって起動されたすべてのコードは、脆弱なリゾルバ 関数を呼び出したプロセスの権限で実行される。 文 1 : DNS リゾノレヾ・ライプラリを修正済みのバー ジョンにアップグレードする。 ほとんどのシステムでは、複数のアプリケーションが DNS リゾノレヾ・ライプラリを使っている可能性がある。 したがって、ライプラリのアップグレードおよびパッ チの適用後、静的にリンクされたアプリケーションを 修正済みのライプラリを用いて再コンパイルする必要が ある。 動的にリンクされたアプリケーションについては、再 コンバイルの必要はない。ただし、リゾノレヾ・ライプ ラリの修正を反映させるために、再起動しなければなら この修正をおこなうシステム管理者は、以下の手順に沿 って作業すべきである。 1. パッチを適用するか、最新のリゾルバ・ライプラリ を入手する。 2. リゾルバ・ライプラリを重加勺にリンクしているサービ スを再起動する。 3. 旧いライプラリを静的にリンクしていたアプリケー ションについてはパッチを適用したライプラリまた は最新のライプラリを用いて再コンパイルする。 対策 2 : ローカル・キャッシュ DNS サーバーを利用 する。 ローカル・キャッシュをおこなう DNS サーバーを用 いて DNS 応答を再構成すれば、悪意ある DNS 応答か らシステムを防御できる。 BIND 9 では、このガ去で 154 UNIX MAGAZINE 2002.9
表 1 紹介したアドバイサリ 発行日 修正日 タイトル 番号 CERT Advisory (http://www.cert.org/advisories/ 6 月 28 日 7 月 26 日 CA -2002-19 Buffer Overflow ⅲ MuItipIe DNS ResoIver Libraries 7 月 10 日 7 月 19 日 CA ー 2002 ー 20 Multiple Vulnerabilities ⅲ CDE TooITaIk 7 月 22 日 7 月 25 日 CA ー 2002 ー 21 Vulnerability in PHP 応答を防げる ()加勺 DNS のアッフ。デート・メッセージ は除く ) 。一方、 BIND 8 ではすべての DNS 応答は防 げないので、キャッシュ DNS サーバーとして BIND 8 を利用している場合には、このガ去は効果がないこと もある。 CA-2002-20. Multiple Vulnerabilities in CDE ToolTalk 2002 年 7 月 10 日発行 CDE (Common Desktop Environment) ToolTaIk RPC データベース・サーバーに、 2 つの脆弱性が発見 された。 1 つ目の脆弱性 ( VU # 975403 ) では、リモー トの攻撃者によるファイルの削除、サービス妨害攻撃、 任意のコードやコマンドの実行を許すおそれがある。 2 つ目の脆弱生 ( VU # 299816 ) では、ローカルの攻撃者 によって任意のファイルが上書きされてしまう可能生が ある。 VU # 9754031 : rpc. ttdbserverd (CDE ToolTalk RPC データベース・サーバー ) は、 -TT-ISCLOSE() へのファイル言己主子の引数をヨ - 分に検証しない。 -TT-ISCLOSE() 手続きを巧妙に呼び出せば、リモー トの攻撃者は記億領域 ( メモリ ) の特定の位置をゼロで 上書きできる。攻撃者は、この脆弱性と有効な TooI- Talk RPC リクエストを組み合わせ、攻撃対象システ ム上の ToolTalk RPC データベース・サーバーがア クセス可能なファイルをすべて削除することができる。 通常、このデータベース・サーバーは root の権限で実 行されるため、あらゆるファイルか削除される可能性が ある。 VU # 2998162 : rpc. ttdbserverd (CDE TooITaIk RPC データベース・サーバー ) は、ファイル操作を十 分に検証しない。 1 http://www.kb.cert.0rg/Vu1S/id/975403 2 http://www.kb.cert.0rg/Vu1S/id/299816 UNIX MAGAZINE 2002.9 特定の ToolTalkRPC リクエストにシンポリック・リ ンクを参照させることで、攻撃対象システム上の Tool- Talk RPC データベース・サーノヾー ( 通常は root 権限 で実行される ) がアクセス可能なファイルを任意の内容 のファイルで上書きできる。これによって、サーピス 妨害攻撃がおこなわれる可能性がある。 影響を受けるシステム ・ CDE ToolTalk を実行しているシステム ・べンダーカ甘是供するパッチを適用する。 ・脆弱なサービスを無効にする。 ・脆弱なサービスへのアクセスを遮断する。 CA -2002-21 . VuInerabiIity in PHP 2002 年 7 月 22 日発行 概要 PHP でファイルのアップロードを扱う部分、すなわち multipart/form-data に脆弱性が存在する。リモート の攻撃者は、巧妙な POST 要求を Web サーバーに送 り、 PHP カリ用するデータ構造を破壊することができ る。これによって、 Web サーバーの権限で任意のコー ドを実行したり、 PHP や Web サーバーをクラッシュ させる可能生がある。 X86 システム上では任意のコードの実行は不可能との報 告もあるが、そのシステムで実行されている PHP およ び Web サーバーに被害がおよぶおそオ劯ゞあるので、適 切なパッチを適用したはうがよい。 影響を受けるシステム ・ PHP 4.2.0 / 4.2.1 ・べンダーカ甘是供するパッチを適用する。 職斤バージョンにアップグレードする。 ・ POST リクエストを無効にする。 ・ PHP サービスを無効にする。 155