セキュリティキャンプ全国大会2017に参加してきました
初めての記事ですが、そもそもこのブログを立てるきっかけになったのはセキュリティキャンプなので感謝を込めてセキュリティキャンプの感想を最初の記事にしようと思います。
さて、8/14から5日間東京都府中市で開催されたセキュリティキャンプ全国大会2017ですが、ここでは自分の活動報告とキャンプで得たもののまとめを書こうと思います。
事前課題
自分は集中Xコースのx86OS自作ゼミに参加しました、なぜ参加したかというとUnix系OSのファイルシステムやデバイスドライバへのアクセスの提供方法などがとても美しくて、そこに対する理解を実際に作ることで深めたいと思っていたからです。
事前課題はとてもシンプルで「OSを作れるところまで作ってこい(...であってますよね)」ということだったので、参加決定してから技術書を見ながらガリガリ書いてました。
目標としては最終的にマルチタスクをサポートして、シェルからいろいろコマンドを実行できるところまで作りたいなぁと思っていたのでキャンプではシェルが実行できるまでを目標にして、そこまでのマイルストーンとしてブートローダーの作成、メモリー管理、プロセス管理、コンテキストスイッチ、システムコール、ファイルシステム、デバイスドライバ、シェルと設定しました。
事前課題で問題があったときに講師に聞けばサポートしてくださり、以前にも何度かOSを自作しようとしたことはあるのですが、うまく起動できず毎回挫折していたのでとても心強かったです。
ベアメタルプログラミングは初めてだったのでいろいろ洗礼を受けたのが印象に残ってます。事前課題であった洗礼を挙げると
- GDTRの設定ミスでGDTが正しく読み込まれず、カーネルにジャンプできない(以前の挫折の原因でした)
- PICを設定していないとPICはデフォルトの割り込み番号(エラー割り込みの番号と重なる)で割り込みをかけてくるというのを知らずに割り込みを許可したのでエラー割り込み(に見えるタイマー割り込み)が発生(PICからの割り込みの番号を任意の数ずらすことができて、それをしないと平気で6番割り込みとかかけてくる)
という感じでした、もっと仕様書を読むべきだったかもしれませんね。
これらの問題は講師の方々にサポートのおかげで解決したので本当に感謝しています。
本当はファイルシステムとプログラムローダーまで実装してキャンプに参加したかったのですが、残念ながら間に合わずファイルシステムとプログラムローダー(ELFに対応)をキャンプ中に実装することになりました。
DAY1
セキュリティキャンプの参加者インフォメーションをもらうまでは集中コースはDAY1~DAY3まで講義して終わりなのかと思ってたのですが、実際はDAY2~DAY4の専門講義枠がすべて集中コースの活動になる(選択コースは一コマ単位で選択)ということでした。
専門講義以外にも全体向けの講義や活動があって思ってたより多く学んで考える一日でした。
slコマンドを作った人の名言「くだらないものを作れないやつに何も作れない。何か作れ。」は印象に残ってます。
※slコマンド知らなかったので入れてみたらslって打つたびに機関車が画面の右端から左端に移動するのですが、その間Ctrl-Cも効かないという徹底ぶりで面白かったです。
DAY2
事前課題でファイルシステム(FAT32)のルートディレクトリにあるファイルをリスト表示したり、ファイルの中身を閲覧したりできるようにはなっていたのですが、最後まで閲覧できないファイルがあったり、最初から全く見えないファイルがあったり、表示すると文字化けするファイルなどもあったので、原因究明やバグ修正に追われているうちに終了時間ぎりぎりになってしまいました。
ファイルが閲覧できない原因は結局ファイルシステムの収まっているディスクイメージが最後まで読み込めなかったということでした。
自分のOSはキャンプ時点ではフロッピーディスクドライバを実装しておらず、OSの入っているディスクがFAT32に準拠していなかったので別のFAT32ディスクイメージを作ってそれをブート中にBIOSの機能を使って全部メモリー上に読み込むことでディスクドライバの実装を省いていたのですが、その時に読み込む量を一定以上にするとバグるのでとりあえずその量まで読み込むようにしていたのを忘れてましたorz。
ちなみになぜ一定量読み込むとバグるかですが、BIOSでフロッピーを読み出す機能とはメモリーアドレスes:bxに指定したセクターを読み込むというものですが自分のOSでは1セクター読み込んでadd bx,0x200をするというのを繰り返すというもので、bxが0xFFFFを超えた時にesを増やすということをしていなかったので、せっかくディスクイメージを読み込んだところを最初から上書きしてしまうということが起こっているようでした。
結局このバグに気づくまでに時間がかかりすぎてしまったのでこの日はそのあとプログラムローダーでELFヘッダーを読み込む部分まで実装だけして(デバッグはしてない)終了することになりました。
DAY3
この日はELFが読めるプログラムローダを実装するために奮闘してました。
この日に起きたのはELFヘッダーが正しく読み込めないというもので今までC言語の構造体が__attribute__( (packed) )をつけないと宣言通りにメモリーを使わずに(たぶん最大サイズの変数に合わせて)パディングされるということを知らずに、ELFヘッダーを構造体で読み込んでいたのでそれで正しくヘッダーが読み込めなかったというものでした。
作業開始してしばらくしてから講師の方から既存のOSにはないオリジナリティを出せという課題を出されたのですが、自分としてはなかなか苦しかったです。というのも、今回は前述のとおりUnix系OSへの理解を似たものを作ることで得るという目的で参加したのでオリジナリティは考えていなかったからです。キャンプでもう少し理解を深めてから新しいもの(オリジナリティを含むもの)を作ろうと思っていて、もっと言うと既存のものを理解せずに新しいものは作れないと思っていました。結局その場では思いつかず、明日考えた結果を報告という形になりましたが、自分がなぜUnixに憧れたか、その気持ちを整理して、同じようなことを考えている人に自分は何を提供できるか、寝室で考えてから寝ました。
また、この日は専門講義以外に企業プレゼンテーションとBoFがあり、BoFでは発想法の講義に参加しました。久保田 達也さんがいらっしゃって自分のしてきたことを語っていらっしゃいましたが、考え方のとてもいい勉強になりました。「たくさんアイデアを出してその中からピーンッと来るものを選ぶ。」きっとこれが正しい頭の使い方なのかなと思いました。
DAY4
DAY4は専門講義最終日なので一番最後にコース内で作ったものを発表するため、急いで見せられるところまで作る必要があったのですが、プログラムローダーのバグが解決できずに結局プログラムローダーが新しいプロセスを生成するところまでは発表できなかったのは悔しかったです。(当日中に何とか動くようになったのでなおさら)
起こっていたのは、まず、プログラムヘッダーが正しく読み込まれていたにも関わらず、アプリケーションのプロセスがうまく動かないということで、これは未だ原因不明です、とりあえず正しいと思われる読み込み位置等を手動で設定しました。
次にあったのが例外割り込みの発生時にはその時のレジスタの値やプロセス番号がすべて表示されるようにしてあったのですが、なぜかアプリケーション実行時にすべての値が0の謎の例外が発生するというもので、これは割り込みが発生したときにアプリケーションのプロセスのトラップフレームが渡されるのですが、GDTがアプリケーションとカーネルで異なるため、渡されてきたポインタのさすメモリー領域が正しいところを指しておらず、修正する必要があったのを修正してなかったのが原因みたいでした。
今後の課題はプログラムヘッダーの値から読み込み位置などの設定を正しく設定することですね。
キャンプで得たもの
まず、自分のプログラミングで作るものが今までゲームしかなかったところに、OSやその周辺機能が加わったのは大きかったです。OSを作る機会というのがキャンプで得たものの中で大きいです。また、バグに向き合うなかで講師の方々から様々な知識をいただきました。あと、ある規格に従う上で仕様書を読む重要性も学びました。
知識や成長もいただきましたが本などもたくさんいただきました。
運営や協賛企業等、講師やチューターの方々、ありがとうございました。
そして、参加者の皆さんはお疲れさまでした。今後もお世話になる機会があると思いますがよろしくお願いします。