2026-06-05
セキュリティキャンプ全国大会 課題
セキュリティ・キャンプ 2026 の OS自作ゼミに通過しましたので、回答を晒そうと思います。
課題リンク : https://www.ipa.go.jp/jinzai/security-camp/j5u9nn000000gazm-att/kadai_y1.txt
問題.1
本ゼミで自作したいOS(もしくはそれに類するもの)について、講義概要をよく読んだ上で具体的に回答してください。
もしこの分野について初心者である場合は、なぜシステムソフトウェアに興味を持ち、OSのどのような点に惹かれて自作したいと思うに至ったのか、あなたの個人的な実体験に基づいて記述してください。
さらに、以下の2点について必ず言及してください。
i. 現在感じている限界: その目標を一人で今すぐ完遂することを阻んでいる、具体的な技術的・認知的障壁(理解が及んでいない概念、実装で躓いているポイント、設計上の迷いなど)は何ですか?
ii. キャンプで得たいもの: セキュリティキャンプという、講師や他の受講生がいる環境を利用して、上記iで述べた障壁をどのように突破しようと考えていますか?
「有意義な議論がしたい」といった抽象的な期待ではなく、具体的にどのような技術的テーマについて議論(あるいはペアデバッグなど)をしたいか記述してください。
回答
大学に入ってから、OSの違いによる人間に提供されるインターフェースや、そもそもの提供される機能やプリインストールされる機能の違いに触れ、意識する機会が増えた。 例えば、macのディレクトリ構成では最初からDAWのプラグイン用の領域が用意されているが、Windowsにはそれがなく各々のソフトウェアがしっちゃかめっちゃかにインストール場所を指定する。また、本来刺すだけで使えるはずのUSBレシーバーを備えたBluetooth機器は機器によってうまく使えたり、ドライバを手動インストールする必要があったりする。 これはOSが機器を抽象化しているのに失敗している例だろう。 以上のような経験から、ハードウェア(入出力装置だけでなく、ディレクトリなどもHDDやSSDを抽象化していると言える)の抽象化、思想によって提供する具体の中継とその設計に興味を持っている。
ところで、キャンプは(事前学習の期間があるとはいえ)5日間と非常に短く、私自身もこの分野に関して初心者である。 よって、当然、いきなりすべてを0から自作するようなことは難しいと考える。
以上のような背景から、 “作って学ぶ OSのしくみ”のwasabiOSを拡張し、FAT形式のファイルシステムの実装を行いたい。 自分で学習用に実装している最中のwasabiOSのgithubリポジトリはこのリンク(https://github.com/temari1013/hikalium_OS1)に存在する。 具体的な詳細は以下の通りである。
仕様
- 当該書籍を完了した状態のwasabiOSをベースとし、それを拡張する機能としてFAT32形式のファイルシステムを実装する。
- ファイル用のボリュームの名前は固定でfile.img(でなくともよいが、名前は固定)とする。また、ファイル名はすべてアルファベット+ 記号である前提とする。
- 読み出しに対応する。作成は対応しない予定である。また、今回はファイルシステムの実装のみ行うため、APIやハードウェアを制御するドライバの実装は行わない。 起動時にディレクトリ構成(既存のシステででの対応するイメージとしては、ルートディレクトリでlsを実行したときの出力)を画面上に表示することまでを実装する。
- ドライバについては、UEFI側のBlockI/Oプロトコルを使用する。これは、期間的にドライバの自作は現実的ではないと判断したからである。 ブートローダの段階でメモリにボリューム情報を読み出し、それを処理する。
処理の流れ
1. ブートローダがBlock I/O Protocolを使用して、ボリューム情報をメモリ上に読み出す。2. 1.のボリューム情報からルートディレクトリエントリーのクラスタにアクセスする。 このルートディレクトリエントリーのアドレスはパーテイション先頭の1ブロックであるBPBの中の、BPB_RootClusの中から開始クラスタを取得できるため、そこからブロックのデータ領域の先頭アドレスを計算してアクセスする。3. アクセスした結果取得できたディレクトリエントリを解析し、ファイル名称を抽出する
以上のような内容を実装するにあたって、以下の二点について課題を感じている。
- ファイルシステムへの理解 FAT32以外にも、クラスタ、ボリューム、ブロックといった概念への理解が十分であるとは思えない。 実装する過程で自身の誤解が原因で想定どおりにいかず、手が止まってしまうこともあり得る。 とくに、ファイル名称を返す処理ではデータ領域が連続したブロックに格納されているとは限らないのだが、この保存ブロックを順にたどる方法が不明瞭なままである。
- 本来はドライバも自作したい ドライバの自作まで含めると手にあまるために実装ない予定だが、メモリ上の値を読んで出力するだけではファイルシステムとは言い難い
セキュリティキャンプという環境では、自力でUEFIやFATなど仕様書を読んで解釈し、実装に落とし込むという能力を鍛えることができると期待している。 既存のOS自作本や、OS以外でも広くなにかを実装する際に要求される能力ではあるが、解答がない状況でそれに取り組むのはより高い水準でその能力を要求されると考えている。 他にも、問題解決につながるわけではないが、単に概ね同年代で、コンピュータに興味がある人が多く集まる環境は刺激的である。 実際にOS自作をやっている人間が周りに多数存在したことで興味を持った側面は否定できず、また、今後ドライバ自作など他の何かを作るときの道標となるような情報も同様に吸収したいと考えている。
問題2
これまでにあなたが行った中で最も困難だった「デバッグ」体験について詳しく教えてください。
ここでいうデバッグは、必ずしもプログラミングやコンピューターに限らず、論理的推論と試行錯誤によって解決した、何らかの仕組みの意図しない挙動を修復した経験を指します。もちろん、プログラミングのデバッグ体験でも構いません。
解決に至る過程のなかで、どのように思考し、どのように手を動かして調査し、最終的に解決に至ったのかを具体的に語ってください。壮絶なデバッグ体験であればあるほど歓迎します。
その際、あなたの「思考の軌跡」をより解像度高く理解するため、以下の3点について必ず言及してください。
i. 最大のタイムロスを生んだ落とし穴: デバッグの過程で、あなたが「絶対にここが原因だ」「こういう仕様のはずだ」と信じ込んでしまい、結果的に時間を無駄にした仮説は何でしたか?
ii. 突破口となったきっかけ: 上で述べた、誤った思い込みを打ち砕き、真の原因へとたどり着くきっかけとなった具体的な事象(ある1行のエラーログ、ドキュメントの記述、物理的な観察結果、他者との対話など)は何でしたか?
iii. そこから得た学び: 最終的に判明した原因は、あなたの事前の理解や推測とどのように食い違っていましたか?また、その経験から自身の「思考の癖」や「システムに対する向き合い方」について何を学びましたか?
回答2
私のデバッグ体験は、自作webアプリケーションの作成を行ったときの経験である。 当該webアプリケーションには https://books.shimaena.ga/ でアクセスできる。URLの通り、自宅の書籍を管理するために作成したものだ。(真面目に使っていないが…) 私のgoogle アカウントでしか登録系の機能はアクセスできないようになっているが、操作画面は添付した通りで、バリデーションに通るように内容を入力して送信に成功するとトーストで通知が表示される。 一覧はだれでもアクセスできるようになっており、私が登録した書籍の一覧が表示される。 バックエンドはGolangで書かれており、httpアクセス周りの処理フレームワークにGinを採用している。また、DBには mySQLを活用している。 フロントエンドはNextJS + Reactで書かれている。 バックエンドは自宅サーバーのdockerコンテナ上に、フロントエンドは自宅サーバー上に直接立ち上がっている。
私のデバッグ体験は、このwebアプリケーションにタグ機能を追加したときの話だ。 タグ機能は3つのテーブルが関わる。 booksテーブル、tagsテーブル、book_tagsテーブルである。 多くの多対多リレーションがそうであるように、booksの各行はtagsの情報を保持していない。tagsテーブルにはidとnameの対応のみが保存されており、book_tagsテーブルに book_id(books.idに対応)とtag_id(tag.idに対応)の対応を保存する。
添付した画像の通り、タグ機能が常に全タグが指定されているものとして(表示されている二件のみをテスト用に登録していた)表示された。 この問題の原因として以下の3つを考えた。
- 登録時にすべてのタグを登録してしまっている。
- DBの読み出し時にタグテーブルを読み、タグ番号と名前を紐づけるときに失敗してすべてのタグを登録しているものとしてレスポンスしている。
- フロントエンドでタグの表示に失敗している。
ここで、DBに直接アクセスしてタグが登録されているかを確認したところ、バックエンドへの本とタグのセットの登録自体に失敗していた。
mysql> SELECT * FROM bookTags;
Empty set (0.01 sec)
問題は2つあったようだ。
- 本とタグをそもそも登録できていない
- タグ番号と名前を紐づけるときに失敗しており、GETリクエストへの返答がおかしい。
なお、フロントエンド側で本に対応するタグを入力するときはバックエンドのtagテーブルから一覧で取得させたタグから選択させており、その表示からtagテーブルへの登録そのものが失敗しており、連鎖で本とタグの対応の登録も失敗している、という仮説は棄却できていた。 問題1の方に先に取り組むため、ようやくバックエンドのapi(GET /books)を叩いたことで、問題の2つ目の認識が間違っていることに気づいた。 バックエンドからは全タグを登録していると勘違いしていたが、フロントエンドで全タグを登録しているとして表示しているのが真の問題であった。 当該コードは以下のようになっていた。
{tags && tags.length > 0 ? (
tags.map(tag => tag.name).join(', ')
) : (
'—'
)}
tagsは、本に紐づいたタグではなく、フロントエンド側で取得したtagテーブルの一覧であるため、
book.tags.map(tag => tag.name).join(', ')
とする必要があった。
また、2つめの問題は単にフィールド名の勘違いで、バックエンドにフィールド名をtag_idsとして送信すべきところをtagsとして送信していたことが原因だった。
この問題は、もともと本とタグの対応の登録もしくは対応の取得どちらか一つの問題であると考えていたが、実際には両方とも問題を抱えていたため、当初の見立てより長い時間を要することになった。 また、根本的に初回実装からデバッグまでの時間が経ちすぎており、jsonの形式など仕様を忘れていたことで、フィールド名や構造体形式に間違いはないという過信を抱かせ、問題をややこしくした。 mySQLやjsonのレスポンス、console.logの出力を確認するといった基本的なことが役にたった。
以上のようなことから、自分の作ったものを信じず、ログ出力を過剰なまでに確認することが近道であると学んだ他、作ったものは勢いがあるうちに修正しておくことも大事であると感じた。
問題3
システムソフトウェアの世界は、物理法則や限られたリソースに起因する「解決不能なトレードオフ」の連続です。 例えば「パフォーマンスの極限追求」と「消費電力の抑制」、「過去の巨大なソフトウェア資産との後方互換性の維持」と「実装の美しさ」、「抽象化レイヤによる安全性」と「ハードウェアの直接制御による性能の最大化」などが挙げられます。
もしあなたが、新しいOSやシステムソフトウェアをゼロから設計するとしたら、どのようなトレードオフに関して、どのような「尖った」決断を下しますか? 回答に際して、以下の3点について具体的に記述してください。
i. 直面するトレードオフの定義: あなたが最も葛藤を覚える、あるいは最も興味がある「相反する2つの要求」は何ですか?
ii. あなたの決断とその背景: 上記の対立において、あなたはどちらを優先しますか?一般論ではなく、あなたの個人的な経験に基づいて「そう決断する理由」を語ってください。 iii. 「犠牲」への向き合い方: その決断によって、必然的にシステムから切り捨てられるメリットや、不利益を被るユーザー(あるいは開発者)が存在するはずです。その「犠牲」に対して、設計者としてどのように責任を持ち、あるいは割り切りますか?
回答3
私が葛藤を覚えるのは、ユーザーの自由度と、システムの堅牢性である。
ここで、私はユーザー空間のコンテナへの分離という提案を行う。これはシステムの堅牢性を取る判断だ。 OSは共通でカーネル部分を持つ。この部分は完全に読み取り専用である。 ユーザー領域は可変であり、コンテナ上に立ち上がる。各ユーザの設定やインストールしたアプリケーションは各ユーザーのコンテナごとに保存される。 このコンテナ内ではシステムに対するあらゆる変更を行うことができる。 一方、カーネル部はユーザー側からは一切変更できず、OSのアップデートなど変更の際は既存のimmutableOS同様にOS自身の権限によって行う。
過去に私は自宅の共用PCのユーザーファイルをよくわからないままに移動させたことがある。 私が壊したもののさらに先代のPCは、母親の手によってウィルスのフェイクアラートのウィンドウが表示されるようになっていた。これらのPCの扱いの失敗は以下で述べるような問題点に集約される。 つまり、現行のOSでは、複数ユーザーがUIDという概念を持ち一台のPCをUIDに紐づいた権限で使用することの問題点だが、
- 管理者ユーザーが機械音痴だとPC全体がしっちゃかめっちゃかになる
- 複数ユーザー間で要求するアプリケーションのバージョンの衝突が起きやすい ということだ。 私用のPCではあまり問題にならないが、会社などのコミュニティにおいて一台のPCを複数人で使いまわしたい需要は多い。
この提案と既存のimmutableOSの概念との差は、ユーザーの変更が完全にコンテナに閉じ込められることである。 これは、ユーザーのインストールしたアプリケーションもsudo権限を持たない(持てない)ことを意味する。 なお、ディスクへの書き込みやネットワーク周りの設定ができなくなるわけではなく、ユーザーコンテナのプリセット設定に含めて起動させる。 カーソル速度など一般的なシステム設定はユーザーコンテナの内部で可能である。
この決断によって不利益を被るのは、開発者(OS自体の開発者ではなく、開発を職業にしている人間)と、一般ユーザーのうち設定を自身に対して最適化することを好むユーザーである。 私はこの不利益に対して割り切る決断を行う。 なぜなら、ここまでの議論で明らかなように、ギークのための自由度が一般ユーザーの使いづらさに寄与していると考えるからだ。 自分のためにカスタマイズできる人間は、既存のOSで問題なく需要が満たされていると考える。デスクトップ環境からインストール時に自分で選ぶことのできるArch Linux がその代表だ。 しかし、一般のあまり詳しくないユーザーが何をやってもPC本体に破壊的変更がなされない、という設計が行われているPCの需要は満たされていないように思う。
問題4
以下のプログラムを見てください。
#include <stdio.h>
int rec(int n) {
printf(""%d\n"", n);
return rec(n+1);
}
int main(void) {
return rec(0);
}
このプログラムを実行する前に、このプログラムの実行結果がどのようになるのかをできる限り正確に予想して、その予想の背後にあるあなたの理解を説明してください。必要であれば、OSのソースコードや設定パラメーターを調査しても構いませんが、このプログラムに類するコードを実行してはいけません。
予想を書き終わったら、このプログラムを実行してみましょう。
上記のプログラムをa.cとして保存してgcc -o a a.cやclang -o a a.cなどでコンパイルして実行してください。
実行できたら、その実行結果を回答に貼り付け、その結果と先程記した予想がどう異なっていたか、なぜその差異が生じたのかをできるかぎり詳しく調査して報告してください。定性的に述べるだけでなく、実際の実行環境におけるパラメーターや実装コードを示しながら、定量的にその結果が得られた理由を突き止めてください。必要に応じて、追加の実験を行ってその結果を記して利用しても構いません。また、再現性を確保するために必要と思われる情報、たとえばOSのバージョンやコンパイラのバージョンなども、必要十分な範囲で回答に含めてください。
回答4
実行環境
- OS : mac OS 26.4.1
- gccのバージョン (実態はclangだが): Apple clang version 15.0.0 (clang-1500.3.9.4) Target: arm64-apple-darwin25.4.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin
予測
まず、コードを見る。
printf(""%d\n"", n); とあるが、ダブルクォーテーションが一つ多い。普通はprintf(“%d\n”, n);である。よって、%dで記法エラーを起こす。 syntax error before %dだろうか。
実際
実際にコンパイルした結果は以下に示す通りであり、実際には想定と違いdの未定義だった。
prob4.c:4:13: error: use of undeclared identifier 'd'
printf(""%d\n"", n);
^
1 error generated.
予測2
“このプログラムの実行結果が…”と書いてあるのでコンパイルエラーになるのは問題の本質ではなくtypoかなにかだろう。気を取り直して、コードは添付したa.cの通りであるとして考える。 呼び出されたときの引数に1加えたものを引数に自身を呼び出し続けるのだから、
0
1
2
3
.....
と続く無限ループのコードであることは明白である。とはいえ、再帰的に自身を呼び出し続けるコードである以上、どこかでスタックオーバーフローを起こして停止するであろう。
ターミナルで % limit とする。
(他略)
stacksize 7MB
より、スタックサイズは7MBのようだ。関数のポインタサイズは8である。 よって、7000000 / 8 = 875000であることから、 関数の実態を置くアドレスなどを鑑みて、874900あたりで出力が止まり、セグフォになると予想した。
実行結果
(ターミナルに一気に出力されたため、末尾の方以外は表示が切れてしまった)
261417
261418
261419
261420
261421
zsh: segmentation fault ./a
実行結果は上に示した通りであり、実際には想定の1/3より少し多い程度の出力で止まってしまった。 これは実際にスタック領域に積まれるのはアドレスだけではなく、スタックフレームと呼ばれるデータ構造を積んでおり、それは関数のアドレスより大きいからである。 aのアセンブリコードを見る(a.asmとして回答に添付した。) 37行目に
sub sp, sp, #32
とあることから、一度の関数呼び出しあたり32バイトを消費していることが間違いない。 ここで、macOSにおいてC言語のコンパイルに使用されるリンカはldである。これは、gcc a.c -o a -v とした出力に
"/Library/Developer/CommandLineTools/usr/bin/ld"
が含まれていることから確認できる。
man ld を実行する。
-stack_size size
Specifies the maximum stack
size for the main thread in a
program. Without this option
a program has a 8MB stack.
(後略).
とあることから特になにも指定しなければ8MBのスタックを割り当てられることがわかる。 8MB = 1024 _ 1024 _ 8 = 8388608バイトであり、 8388608 / 32 = 262144 である。実際には261421回の関数呼び出しが行われたが、これは関数本体をおいておく分に消費されたスタック領域を除外すると妥当な値であることがわかった。
課題回答にあたって
予定管理に失敗したことと、通る可能性があるとそもそも思っていなかったため、なんと締め切り前日から着手し、トータルで20時間ほどかけました。また、そもそも技術力重視ならどうしようもないので、セキュキャンへの熱意を厚めに書くという方針を取りました。一問5時間程度の予定でしたが、課題1には7~8時間ほどあて、残りを均等に割りふったくらいの時間がかかったように思います。
また、各回答2048字制限があり、かなり短めの制限であったことから、熱意アピールのため上限いっぱいまで書く必要はなく、過不足なく問いに答えられているのであれば問題ないと判断し、勇気を持って問題によっては1000字程度で済ませています。これが良かったのかどうかはわかりませんが、この回答で通過はしていることから、少なくとも回答制限字数は回答字数の目安ではなく、あくまで上限としての意味しかないことが伺えます。
締め切り駆動したため、手元に詳解Linuxカーネルとインサイドwindowsがあれば…と思った場面が多かったこと、推敲時間もほとんどなく(これは受かると思っていなかったため推敲の意義を感じられていなかったこともかなり大きい)、日本語がやや今ひとつなことが反省点でしょうか。内容に関しては能力的にこれ以上のものは書けなかったと思います。
-
課題1 : 自分の能力では0からなにかするのは無理、書けないと判断したため、既存のものに既存の機能、それも実装案が確立されているものをくっつける方針で書きました。wasabiOSにmikanOSを参考に機能追加という方針で書いています。
-
課題2 : デバッグ体験といわれ、真っ先に思いついたものがバイト先でのデバッグでした。仕事のものを書くわけにもいかないので、大昔に作って放置していたwebアプリのバグを引張り出してきて、ライブデバッグしながら書くことになりました。この課題を最後に書いていたため、提出時間までに直せなかったらどうしようかと思いながら書いていました。
-
課題3 : 最初は手元のMacがメモリ8GBでもそこそこ動くことが感動できると思っているため、メモリの最適化と何等かの要素のトレードオフで書こうとしたのですが、そもそも最適化とは複雑であり、一つのトレードオフに落とし込めるような問題ではなく断念しました。トレードオフの解決について、個人で実装を思いつくレベルの話であれば課題1に書けばよいため、あまり具体的な実装可能性については考えない方向性で書きました。
-
課題4 : 一桁単位の予測までピッタリ解析したかったですが時間がありませんでした。
最後に
純粋に技術力で上から取った場合に私が選ばれることはありえないので、足切りラインを突破しているかと、応募者がセキュキャンでやりたいことが講師陣がセキュキャンでやらせたいことに合致しているかが重要なのではないかと推測しています。