セキュリティ・キャンプ全国大会2019へ参加することになった(応募用紙晒し)

中間試験が一段落したので少し出遅れた感はあるけれど、この記事を書いています。

題名のとおりセキュリティ・キャンプ全国大会2019のシステムプログラミングトラックOS開発ゼミに参加することになったので、恒例の応募用紙晒しをしてみようと思います。 ちなみにセキュキャンに応募するのは今回が2回目です。実はリバースエンジニアリングゼミにも興味があってそちらの応募用紙も完成させてはいたのですが、最終的にOS開発ゼミのほうで提出することにしました。

あらためて自分の応募用紙を見直してみると結構はずかしいです。そういえば書いている最中も自分の文章にあまり自信がもてなくて何回も消したり書いたりしてたなあなんて思いだしました。

以下で掲載している応募用課題はこちらで公開されています https://www.ipa.go.jp/files/000073173.txt

セキュリティ・キャンプ全国大会2019のホームページはこちら https://www.ipa.go.jp/jinzai/camp/2019/zenkoku2019_index.html

応募用紙

  • 共通問題A
我々講師は、普段いくつかのOSを使っていますが、使い込むうちに色々な発見をします。
皆さんもきっとそういう体験があると思います。
あなたが普段使っているOSで、好きな機能と改善してほしい部分について、思いのたけを聞かせてください。
この問では、皆さんが普段どの程度興味を持って既存OSを観察しているかを評価します。

私が使っているOSで好きな部分は、OSのソースコードが大変に簡潔に記述されていること、そして余計な機能を一切入れないこと、またそれらによってOSに存在する脆弱性を限りなく少なくすることを目的にしていることです。 このOSのソースコードは本当にびっくりするくらいにきれいです。私はOSというものにそこまで深く触れたことがなく、C言語C++でのプログラミングを少ししたことがある程度なのですが、それでも他のOSのソースコードを読もうとしたときより「これは楽に読めるぞ」と感じたのでトリッキーなコードが少なく素直なのだと思います。また、余計な機能を一切入れないこともコードの単純化に寄与しています。普段ほとんどの人が使わないような機能のためにOSの開発がより困難なものになってしまうのは私は良くないと思います。このようにOSの構造を簡潔に、わかりやすくすることで見通しを良くすることに私はとても共感しています。 しかし、これらは決していいことづくしというわけではありません。このOSはソースコードの単純さや余計な機能を一切入れないことによってパフォーマンスを犠牲にしています。ハードウェアの性能向上を待てばパフォーマンスは良くなると思いますが、ハードウェアの性能向上にそこまで期待していいのかという問題もありますから、なかなか難しい問題だなと思います。

  • 共通問題B
皆さんが仮にOSを作るとしたら、「どんなOS(やOSの機能)を作ってみたい」でしょうか?
(既にOSを作った事がある人は、その特徴を書いてくれても構いません。)
そして、なぜそれを作ってみたいと思ったのでしょうか?
皆さんが心の中で夢描いているであろう、ワクワクするようなOS像を教えてください。
※「Linux開発者を目指そう!」テーマを受講したいと思っている方は「どんなLinuxカーネルの機能を作ってみたいか」を答えてください。
※「Raspberry Pi向け組み込みOSを作ろう!」テーマを受講したいと思っている方は「どんな組み込みシステムを作ってみたいか」を答えてください。

Linuxでは現在Linux向けにコンパイルされたプログラムしか実行することができなかったと思いますが、他のOS向けにコンパイルされたプログラムを動かすことができるバイナリエミュレーションの機能をつくってみたいです。 動機としては、この機能が特別ほしいなと思ったというわけではなく、単に実装してみたいなと思ったからです。私は数多くあるOSの機能のうちユーザーアプリケーションを実行する機能が好きです。もともと私がOSに興味をもったきっかけが、自分の書いたプログラムがどのように動いているのか知りたかったことにあるのが影響しているのかもしれません。ユーザープログラムを実行するに際してはいろんなOSでいろんな工夫がされているなと思います。例えば、LinuxにはVDSOというものがありますが、これはシステムコールはkernel側で処理されるものだという常識を覆すおもしろい発明だなと思います。

  • 共通問題C
C言語で双方向リンクリストとそれを操作する関数を作り、ソースコードを提出してください。
  リンクリストを生成する関数、要素を任意の場所に挿入する関数、全ての要素を順に標準出力に印字する関数、の3つがあれば十分です。
  やる気があればもっとたくさんの機能を実装しても構いません!
#include <stdio.h>
#include <stdlib.h>

int init(void);
void end(void);
struct node * search_tail(void);
int insert_tail(int value);
void delete_tail(void);
int insert_index(int value, unsigned int index);
void print_list(void);

struct node {
    int value;
    struct node *next;
    struct node *prev;
};

struct node *head;

int
init(void)
{
    head = malloc(sizeof(struct node));
    if(head == NULL) return -1;
    head->value = 0;
    head->next  = NULL;
    head->prev  = NULL;
    return 0;
}

void
end(void)
{
    struct node *tail = search_tail();
    while(tail != head) {
        delete_tail();
        tail = search_tail();
    }
    free(head);
    return;
}

struct node *
search_tail(void)
{
    struct node *search = head;
    while(1) {
        if(search->next == NULL) return search;
        search = search->next;
    }
}

int
insert_tail(int value)
{
    struct node *ins;
    struct node *tail = search_tail();
    
    ins = malloc(sizeof(struct node));
    if(ins == NULL) return -1;
    
    ins->value = value;
    ins->next = NULL;
    ins->prev = tail;
    tail->next = ins;
    return 0;
}

void
delete_tail(void)
{
    struct node *tail = search_tail();
    if(tail == head) return;
    tail->prev->next = NULL;
    free(tail);
    return;
}

int
insert_index(int value, unsigned int index)
{
    unsigned int counter = 0;
    struct node *current = head;
    struct node *ins;

    ins = malloc(sizeof(struct node));
    if(ins == NULL) return -1;
    
    if(index < 0) return -1;
    while(counter < index) {
        if(current == NULL) return -1;
        current = head->next;
        counter++;
    }
    if(current == NULL) return -1;

    ins->value = value;
    ins->prev  = current;
    ins->next = current->next;

    current->next = ins;
    return 0;
}

void
print_list(void)
{
    struct node *current = head->next;
    while(current != NULL) {
        printf("%d\n", current->value);
        current = current->next;
    }
    return;
}

int
main(int argc, char *argv[])
{
    if(init() < 0) return -1;
    if(insert_index(5, 0) < 0) puts("error");
    if(insert_tail(6) < 0) puts("error");
    if(insert_index(3, 1) < 0) puts("error");
    print_list();
    end();
    return 0;
}
設計・実装で工夫した点を述べてください。

整数型の符号の有無や関数の引数などを最小限に抑え、簡潔な実装を心がけました。また、メモリリークなどのバグがないようエラーチェックをしっかりと行ったつもりです。

  • 選択問題S3
Linuxカーネルについて知りたいこと、それについてこれまで調べたこと、
つまづいたことを教えてください。最終的に解決しなかったとしてもOKです。
技術力が優れているかではなく、どれだけ試行錯誤したかという観点で採点をします。
「この機能のこのコードの意味がわからなかった」という高度なものでもいいですし、
「そもそも何から手を付けていいのかもわからなかった」というものでも構いません。

共通課題でも述べたのですが、私はプログラムを実行する仕組みに興味があるのでそれに関連するコードを少しだけ読んだことがあります。そこで不思議に思ったことなのですが、linuxのローダーの実装はfsというディレクトリの下に配置されています。fsというのはおそらくfilesystemのことをさしているのだと思いますが、自分にはこの理由がよくわかりませんでしたし、調べてもこれについて述べているものは探した限りなかったです。また、実際にLinuxにコントリビュートするとして、どういう機能を実装するかというアイデアをどうやって思いつくのか知りたいです。Linuxは多くの優秀な人がコントリビュートしていると思いますが、そのなかで必要とされる実装をどうやって生み出すのか私には全然分かりません。

  • 共通問題D
その他、書ききれなかったことを好きなだけ書いてください。

いままで自分一人では解決できなかった疑問をこの機会にぜひ解消していきたいです。そして、自分もLinuxや他のOSも含め貢献出来るような人になれるように努めていきたいです。