セキュリティ・ネクストキャンプ2020の応募課題をこっそり晒してみる

セキュリティ・キャンプというイベントがあり、これはIPAという組織が毎年開催している合宿形式でセキュリティを学べるイベントです。参加資格を得るためには応募課題に合格する必要があり、課題は以下のような自由記述形式です。

2020年度 セキュリティ・ネクストキャンプ 応募課題

以下について,フリーフォーマットで自由に記述し回答してください.

■ あなたに関する問い
あなたは今までどのようなことをやってきましたか.どのようなことができて,どのようなことが得意で,どのようなことに自信がありますか.
どのようなものを作りましたか.どのような情報を発信してきましたか.
どのようにしてそうしたことをやってきましたか.なぜ,そのようなことをやってきましたか.やってきてどう思いましたか.
参加できた場合,セキュリティ・ネクストキャンプにどのようなことを期待し,どのようなことをやってみたいですか.

■ 課題への姿勢に関する問い
自身で何らかの技術的な疑問を設定し,その疑問を解決しようと取り組み,その過程を示すことで,自身の技術力や課題に取り組むやりかたを説明してください.
(疑問の例:実行ファイルはどのような構造になっているのだろう? lsコマンドは何をしているのだろう? pingコマンドを実行すると何が起きるんだろう? といったようなことです)
設定する疑問は何でも構いませんし,解決しなくても構いません.
解決できたかどうかではなく,いかに課題に取り組むかという点を評価します.

■ 興味ある分野に関する問い
セキュリティ・ネクストキャンプの講義の一覧を見て,その中から興味のある講義を選び,その講義で扱うテーマに対して自分が考えること,興味,疑問,課題,自分なりの考察などを説明してください.
その分野について知識があるかどうかではなく,いかに興味や疑問を持ち,課題を考え,自分なりに調べて考察するかといった点を評価します.

■ その他に関する問い
その他,アピールしたい点などあれば自由記述で回答してください.

 

 (出典:

セキュリティ・ネクストキャンプ2020 オンライン 応募要項 :IPA 独立行政法人 情報処理推進機構 の 応募課題ファイルの一覧 のとこにあるファイル)

僕はめでたく合格してセキュリティ・ネクストキャンプ2020に参加できました。(ネクストキャンプというのは普通のセキュリティ・キャンプ全国大会より上の年齢層向けのものです。)キャンプ自体は今年はオンラインで行われ、無事終了しました。

ところで、「セキュリティキャンプ 応募課題」とかでググると回答を公開している方が何人かいらっしゃいます。どうせですし未来の応募者の参考になるかもしれないので僕も公開しちゃおうと思います。

まず最初に考えたこと

セキュリティ・ネクストキャンプ2020 オンライン 参加を目指す方へ:IPA 独立行政法人 情報処理推進機構

ここに選考の基準があります。引用しますと、

基本として、加点法で判断します。
自身の技術力ややってきたこと、発信してきたこと、何ができるかといったことなど、アピールしたい点を存分に記述してください。
多く書くことにより、「文章が長過ぎる・まとまりが無い・重複している・冗長」などとして減点するようなことはありません。 失敗した経験や落選の結果を書くことや、「文章が洗練されていない」「誤字脱字がある」などによる減点もありません。 アピールをいっぱい書いて、得をすることはあっても、損をすることはありません。自身がアピールしたいことを思い付くままにいっぱい書いて、アピールしてください。

「やる気があります」「もしも参加できたら頑張ります」というのは、書くだけならばすぐにできるので、アピールにはなりません。
いかにやる気があるか、参加できたらいかに頑張ることができるか、ということを示してください。「やる気があり、今までこうしたことをやってきています」「このようにいままでずっと手を動かしてきています」「今までこのような活動を継続してきています」ということを書くといいでしょう。それが、やる気を証明することになります。

課題については、課題が解決できたかどうかの○×や正誤で判断するのではなく、課題を解決しようとする過程や未知のことにどのように取り組むか、新たなことに挑戦しようとする姿勢を見ます。
このため課題は解決できなくても構いません。課題に対する正答を求めているわけではありません。途中経過でも構いませんので、いかに取り組んだか、難しい課題にこのように取り組んでここまではわかった、という、その過程を書いてください。

手を動かしてみてください。ネット検索で調べたことを張り付けるだけではなく、本当にそうなのかという疑問を持ち、自分で手を動かして、見て、試し、調べ、本当にそうなのかと深堀りして考えてみてください。ネット検索で出てきたことは、はたして本当なのでしょうか? 深堀りして理解し納得できているでしょうか? 自分の眼や手で確認したでしょうか? 他人に説明できるでしょうか? そして、そうしたことを書いてください。課題解決に対する、そのような姿勢を見ます。

 また、ネクストではないキャンプの応募課題晒しのブログを1つだけ読みました。とはいえちゃんとは読んでなくて雰囲気だけ感じ取りましたが。

これら2つの情報ソースから、僕は以下の結論を引き出しました。

「とにかくいっぱい書いて自分の思考力を見せつければok」

ということでそういう方針で文章を書くことにしました。具体的には思考過程をほぼ抑制ゼロの垂れ流し式でいっぱい書きました。この書き方はかなりスピードが出て好きなので、個人的にはやっててかなり楽しかったです。普通はもうちょい抑制を利かせて整ったものを書く必要があるので……。というわけでその結果が以下です、どうぞ。長いので全部追わずに雰囲気だけ参考にしていただければ。今見返してコメントも付けました。

(ちなみに、あまりにも恥ずかしい部分をちょっと削ったので以下は提出したものの完全な復元ではないです。)

あなたに対する問い

  とりあえず東京大学理学部情報科学科を卒業しました。これは一通りの基礎知識を備えているアピールですのでこれ以上触れません。

では特に何をしていたかです。私はシステムソフトウェアに関心があります。これはなぜかというと、この説明が結構難しいというか、感覚的に好きだからです。もう少し掘ってみると、このレイヤが好きな理由の一つはこのレイヤーが一番「本質的な仕組みっぽい」と感じているからだと気づきます。仕組みというのは何かを実現させるための機構や方法のことを指します。ここでいう実現されるべき何かというのはコンピュータをコンピュータたらしめるということです。システムソフトウェアの下のレイヤが入れ替わってもそれは「別の部品から作られたコンピュータ」ですし、システムソフトウェアの上のレイヤがなくてもそれは「やることのないコンピュータ」ですが、システムソフトウェアがそれぞれの部品、インタフェースを繋げて統合しなければそれはコンピュータとは呼べないのではないかと思っていて、そういう意味でシステムソフトウェアが自分にとっては一番本質的だと感じます。そして本質的なものは好きです。そういう理由で好きなんですが、でもハード屋からしたら多分ハードが一番コンピュータにとって本質的なわけで、結局これは感覚に過ぎないということはわかっています。

 なぜのところだけ長々言いましたがもう少し言います。具体的作業としては私は仕様書を読むのが好きです。これも理由はわからなくて、結局これも単に好きだから好きとしか言えない気はします。幼少期、私は家の電話機の説明書を繰り返し読んで暗記していた(そしてそれを親に言いまくって辟易させていた)という話があって、つまりそういうのを好む性向があるということでしょう。これは具体的に何をやってきたかにつながります。卒業論文では、組み込みデバイス上でのOSの開発をテーマとして行いました。ここでいうOSというのはほとんどベアメタルプログラミングに近い代物となり、この研究の実装フェーズの結構な割合は仕様書を読んで理解することに費やされました。あるいは、私は30日OS本を写経的に使ってフルスクラッチOS(https://github.com/iwannatto/x86os)を作っていたのですが、ここでもやっぱり仕様書を読むのが好きで、本ではマジックナンバーを置いてサラッと流しているFAT12フォーマット特有の部分も仕様書を探してきて本での記述と仕様書との対応関係を見たりしていました。要は仕様書を読むのが好きなのでそういうことをやってきたし、そういう意味で興味のあることは進められるしそこは自信があると言いたいです。こういうことはやってきてやっぱり楽しいなあと思います。好きがモチベーションでやっているので。

 発信はtwitter(@iwannatto)と、github(https://github.com/iwannatto)と、非常に低い頻度で書くブログ程度でしょうか。http://iwannatto.hatenablog.com/entry/2018/12/11/000009 ←これとか。文章を書くこと自体はかなり好きなので発信に抵抗はないんですが好きすぎて結構のめってしまうのでむしろ控えていて、控えすぎているという感じです。

 参加できた際に期待していることはやっぱり最初に述べた好きの理由の延長線上にあって、「本質的な部分の仕組みの理解」です。 組込みソフトウェアプラットフォームの理解というテーマはもう名前からしてそれ自体じゃんという感じはするのですが、これは単にどういうソフトウェアプラットフォームがあるかを単に知るというだけにはとどまらないと考えています。なぜなら、「その下にどういうハードウェアがあって」「どういうインタフェースを上に提供することが求められているのか」という上下の理解を必然的に伴うはずであるからです。そしてそれは最高なのでぜひやりたいです。

(いま自分でコメント)

いやまあなんでもいっぱい書くってなったらこうなるんだけどなんか恥ずかしいですね

課題への姿勢に対する問い

 普段調べてはいないけど考えてみたら気になるかもというテーマを例を見ながら適当に考えた結果、「プログラムを実行するときは何が起こるだろうか?」ということが気になりました。この疑問を解決することを課題としましょう。

 課題を前にしてまずやることは具体化や細分化だと思います。今回は課題のステートメント自体がふわっとしているのでまず具体化。とりあえず調べやすそうなlinuxってことにすると、「./hoge (hogeはelf)したとき何が起こるかを追ってみる」と具体化できる。自分の元々の知識から、「./hogeするのはシェル上なのでシェルが何かを呼んでいる」「何かというのはおそらくローダで、なんかいい感じに仮想アドレス上に配置してくれる」「配置が終わったら実行をexecveとかでやる」みたいな流れが想像できました。あとはこれのそれぞれが合っているか、流れが合っているかを確認して、自分が納得できる程度に詳細を詰められれば一応課題クリアということになるでしょう(到達点がふわっとしてますが、まあもともと課題のステートメントがふわっとしてるので……)

 とりあえず「bash プログラム 実行 流れ」とかで検索。それっぽいタイトルのページが出てくる。https://language-and-engineering.hatenablog.jp/entry/20110617/p1 そういえばexec以外にforkも大事だったなあと思い出す。ありがとう。僕の認識は割と合ってそうだな。このページは割とbashとかOSがやってくれることを記述している寄りなので探していることそのものではないけど、こういう雰囲気系のページを何個か見て雰囲気あってそうなことを確認する。

 雰囲気を確認したけど核心っぽい記事は見当たらないので、次にやれることとしてbashソースコードを読んでみる。http://git.savannah.gnu.org/cgit/bash.git/tree/ これか。execute_cmd.cとかいうめちゃくちゃそれっぽい名前のファイルがあるので見る。とりあえずexecveで検索すると何個かヒットする。

/* Execute a simple command that is hopefully defined in a disk file
somewhere.

1) fork ()
2) connect pipes
3) look up the command
4) do redirections
5) execve ()
6) If the execve failed, see if the file has executable mode set.
If so, and it isn't a directory, then execute its contents as
a shell script.

 なるほど。実際コードを軽く見てみると最終的にexecveを呼ぶっぽくなっているのでやっぱりこのコメントの流れはあってそうだと確認できた。

 ところでloadって書いてないけどローダはどこにいったんだろう?というかローダってそもそもなんだ?という気持ちになったのでいったんローダで検索をかける。https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%80 wikipedia。「ローダ (loader) は、プログラムやデータなどを、外部(他のコンピュータや外部記憶装置)からインタフェースなどを通して受け取り、主記憶装置やワークエリアに置く(ロードする)プログラムである。なお、それに加えてプログラムを起動できる状態にし、それを実行するというスタートアップなどと呼ばれる機能まで混同している者も多い。」らしい。混同してたな。まあでもメモリに置ければ良いのか。そしてこの記事の最下行にはこう書いてある。「Unixでロードを実行するのは、システムコールのハンドラ execve() である。」マジか。なんか別のローダってやつがあるのかと思ってた。もちろんwikipediaなので眉唾の気持ちを持ちつつ、でもexecveがうろ覚えだったのでここでようやくman page of execveを見る。
int execve(const char *filename, char *const argv,
char *const envp
);
あー、ファイル名、引数、環境変数だけで実行できちゃうのか。これは確かにメモリ配置とかはexecveの中でやってるなあ。

 というわけでlinuxのexecveを読む。といっても完全に辿れるわけではない(時間もないし。)https://sugawarayusuke.hatenablog.com/entry/2018/03/01/002131 それっぽいのを見つけた。先人の知恵は完全に活用しましょう。個人的な関心はメモリ配置周りなので、そのへんのことを多少わかればよしとします。読んでいく。なんかすごい複雑で長い。メモリ配置周りを全部追っても結構な分量になってしまうので、個人的に特に気になっていたメモリをどこからどうやって引っこ抜いているのかだけ調べることにする。execveがやっていることの大半は実はelfからデータを引っこ抜いて計算なりなんなりをして正しい配置先アドレスなりを求めている過程のようだ。本質っぽいのはelf_mapという名前の関数でelfの中身をプロセスの中にmmapしてるところ。あーそうか、forkした時点でプロセス空間としてメモリを持っているのか……。

 ここまでわかったことをいったんまとめると、「./hogeをするとシェルから渡された適切な情報とともにforkとexecveが行われる」「fork自体がアドレス空間をカーネルから持ってくる」「execveの中身で配置先とかを一生懸命計算して配置し、実行する」という流れらしい。ところでこれらのシステムコール呼び出しはstraceで辿れるはず。printf(“hello, world!\n”); return 0;するだけの実行ファイルhogeを作って、strace ./hogeをやるとこうなった。(完全ではないですが部分的な注釈を勝手に入れました。)

./hogeの起動。キャッシュに共有ライブラリの場所を聞く(たぶん)。

execve("./hoge", ["./hoge"], 0x7fff83631d60 /* 59 vars */) = 0
brk(NULL) = 0x556fb153c000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=92454, ...}) = 0
mmap(NULL, 92454, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f775e98d000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)

共有ライブラリを引っ張ってきて配置する。fd=3のやつがそれで、MAP_PRIVATEで引っ張ってきていて実質コピーなのでcloseしても大丈夫なんだと思う。細かくは見ないが無名領域を作ったり適宜権限(あるいは保護)を設定していたりしている。

openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f775e98b000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f775e38c000
mprotect(0x7f775e573000, 2097152, PROT_NONE) = 0
mmap(0x7f775e773000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f775e773000
mmap(0x7f775e779000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f775e779000
close(3) = 0

メモリ領域の保護を設定。

arch_prctl(ARCH_SET_FS, 0x7f775e98c4c0) = 0
mprotect(0x7f775e773000, 16384, PROT_READ) = 0
mprotect(0x556fafb0f000, 4096, PROT_READ) = 0
mprotect(0x7f775e9a4000, 4096, PROT_READ) = 0
munmap(0x7f775e98d000, 92454) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
brk(NULL) = 0x556fb153c000
brk(0x556fb155d000) = 0x556fb155d000

プログラム本体の実行と終了。

write(1, "hello, world!\n", 14hello, world!
) = 14
exit_group(0) = ?
+++ exited with 0 +++

こんな感じ。上でまとめた、「execveの中身で配置先とかを一生懸命計算して配置し、実行する」という流れは確認できたはず。あとexecveの前に何をやっているかも確認したかったのでstrace bash -c ./hogeをやったんだけどforkをしている形跡がない。もしや-cで渡したコマンドが単一だったらforkしないのかと思い、代わりに
strace -f -F bash -c "./hoge; echo fuga"
をやると以下のようになった(抜粋)

clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2c1e01ca10) = 4980
strace: Process 4980 attached
[pid 4979] rt_sigprocmask(SIG_SETMASK, , <unfinished ...>
[pid 4980] getpid( <unfinished ...>
[pid 4979] <... rt_sigprocmask resumed> NULL, 8) = 0
[pid 4980] <... getpid resumed> ) = 4980
[pid 4979] rt_sigprocmask(SIG_BLOCK, [CHLD], <unfinished ...>
[pid 4980] rt_sigprocmask(SIG_SETMASK,
, <unfinished ...>
[pid 4979] <... rt_sigprocmask resumed> , 8) = 0
[pid 4980] <... rt_sigprocmask resumed> NULL, 8) = 0
[pid 4979] rt_sigprocmask(SIG_SETMASK,
, <unfinished ...>
[pid 4980] rt_sigaction(SIGTSTP, {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, <unfinished ...>
[pid 4979] <... rt_sigprocmask resumed> NULL, 8) = 0
[pid 4980] <... rt_sigaction resumed> {sa_handler=SIG_DFL, sa_mask=
, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4979] rt_sigprocmask(SIG_BLOCK, [CHLD], <unfinished ...>
[pid 4980] rt_sigaction(SIGTTIN, {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, <unfinished ...>
[pid 4979] <... rt_sigprocmask resumed>
, 8) = 0
[pid 4980] <... rt_sigaction resumed> {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4979] rt_sigaction(SIGINT, {sa_handler=0x55f026652160, sa_mask=
, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, <unfinished ...>
[pid 4980] rt_sigaction(SIGTTOU, {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, <unfinished ...>
[pid 4979] <... rt_sigaction resumed> {sa_handler=SIG_DFL, sa_mask=
, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4980] <... rt_sigaction resumed> {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4979] wait4(-1, <unfinished ...>
[pid 4980] rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=
, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, {sa_handler=SIG_DFL, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4980] rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=
, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, {sa_handler=SIG_IGN, sa_mask=, sa_flags=SA_RESTORER, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4980] rt_sigaction(SIGCHLD, {sa_handler=SIG_DFL, sa_mask=
, sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f2c1d630fd0}, {sa_handler=0x55f026655790, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f2c1d630fd0}, 8) = 0
[pid 4980] execve("./hoge", ["./hoge"], 0x55f026bb07b0 /* 59 vars */) = 0

 長々。要はforkではなくcloneをして、その後シグナル割り込みの設定をして、4980で./hogeを実行する(4979はwaitする)という流れらしい。cloneのフラグはCLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLDなので単に親を起こすのとidを知るためっぽくて、メモリ空間の共有はやっていない。なのでたぶんcloneがそのままメモリ空間の確保になっているはず。

 とりあえずこんなものにしておきます。まだ掘る余地はかなりあるのですが、結構キリがない感じになってしまうので……。一応何か課題があったときの取り組み方を示すという目的はある程度達成できたと思います。ここまでのことをまとめると、「./hogeをするとシェルから渡された適切な情報とともにforkとexecveが行われる」「fork自体がアドレス空間カーネルから持ってくる」「execveの中身で配置先とかを一生懸命計算して配置し、実行する」という流れであると検索により推測し、straceでこれらを実際に確認した(forkはcloneでしたが)というのが今回行ったことのまとめになります。

 掘る余地がかなりあると言いましたが、具体的にはここから十分時間が与えられた場合に何をするかだけ説明しておきます。プログラムの実行時に何が起こるかというのが自分で設定した課題ですが、特に実行時にメモリがどうなるのかに興味が出てきています。これはつまり、各プロセスがどのようにメモリを管理しているか、それがforkやらなんやらのときにどうなるか、という2点を理解すればよいのだと考えます。そのため、まずcloneの実装を探すと思います。古いQ&Aですが 、https://unix.stackexchange.com/questions/87551/which-file-in-kernel-specifies-fork-vfork-to-use-sys-clone-system-call にてcloneとかの本体はkernel/fork.cにあるdo_fork()であると示唆されていて、実際に https://github.com/torvalds/linux/blob/master/kernel/fork.c を見るとdo_forkはあるのでここから読んでいきます。これの過程で触っているプロセスの情報っぽい構造体が多分プロセスの持っているメモリ管理と関係しているはずなのでそこも探っていく、ということをやると思います。後はそもそも起動時にメモリをどうやっていて、initプロセスからのforkは普通のforkなのか何か違うのか……みたいなことも気になってはいます。

(今自分でコメント)

なが。あとこれほんとにやりながら書いたので今見ると何考えてるかわかりにくい部分がめっちゃありますね。審査してくださった人に申し訳なくなってきた。

ただまあこんなんでも通ったっていうのは結構重要で、やっぱり審査をする人は(選考のポイントで仄めかされているように)知識量ではなく掘るプロセスを重視しているんじゃないかなと思います。上の文章、知識があるかどうかで言ったら全然ないですからね、「なんもしらねーうおおお調べるぞなんかちょっとわかったわ」って言ってるだけなんで。セキュキャン通った人はみんな「自分は強くないけど通ったから臆せず応募しよう!」って言っていて、それは多分知識量は関係ないよという意味だと思うし、僕もセキュキャン出すか迷ってる人がいたら同じことを言います。

興味ある分野に関する問い

 「組込みソフトウェアプラットフォームを理解する」です。僕は低レイヤに触れること自体が興味なのでこのテーマ自体はもろに興味ありなんですが、考えることとなると難しい。組み込みに触れたのは卒業経験のときとベアメタルでラズパイを触ろうとしていたときで、どっちもベアメタル寄りだったのでソフトウェアプラットフォームの知識はそう多くないんですよね。というわけでとりあえず調べてみないと始まらない。調べて自分なりの考察を書く場所にします。

 とりあえず「組み込みソフトウェアプラットフォーム」という世界一安直なワードで検索すると、組み込みプラットフォームを提供するぞという会社のホームページが出てきました。各社言っていることは違いますが、共通してそうな部分を抜き出すと「顧客の開発の手間をなるべく減らせる、かつ合目的な開発基盤を提供する」ということを言っている気がします。ちょっと見えてきた気がする。この合目的という言葉にまとめた部分がポイントですね。組み込みにも当然汎用OSみたいなものはあるのですが、組み込みにおける合目的ってメモリを小さくすることだったりリアルタイム性の確保だったりの厳し目な制約になることがあって、それだと汎用OSでは足りないことがある。そういう場合にもスムーズに開発なりができるようなソフトウェア基盤を提供するよ、というのがこれらの企業のやっていることなのでしょう。
 
 そして上を起点に考えると、汎用OSももちろんソフトウェアプラットフォームの一環ですが、それだけじゃなくて組み込みデバイスがデバイス特有の働きをちゃんとできるようにしてあげるのが組み込みソフトウェアプラットフォームなんじゃないかなと勝手に想像しました。組み込みデバイスって制約が厳しい代わりにハードウェアのリソースを一目的に全振りできたりするわけで、そういうのをやりやすくするのが組み込み特有のソフトウェアプラットフォームなんじゃないかなと思いました。

 考察だけしてもつまらないので一つ適当な例を探してみます。上はOS寄りっぽいことを言ったのでミドルウェアを調べてみます。ファイルシステムミドルウェアっぽいので「embedded filesystem」とかで検索。https://www.keil.com/pack/doc/mw/FileSystem/html/emb_fs.html 一番上にこういうのが出てきました。Embedded File System (EFS)。ざっくり読むと、NOR flash device上で動くことを前提としたファイルシステムのよう。これこそ上で言った組み込み特有の合目的な開発基盤を提供するソフトウェアなんじゃないでしょうか。たぶんこういうのが他の分野でも他のデバイス向けでも色々ある、というのが組み込みソフトウェアプラットフォームの世界なのではと推測しています。

(いまコメント)

これも思ったことを書いただけですね。これ時効だと思うので言うんですが、実は応募時点ではネクストの6科目は全部やるものではなくいくつか選ぶものだと思っていたので絶対やると決めていた組み込みのやつのことしか書いてないです。まあ選んで書く課題なので結果なんも問題もなかったとは思うんですが。

この組み込みの授業は実際めっちゃ良くて、組み込みのソフトウェアプラットフォームの見通しを得られた上に実際に触れる仮想環境も用意してもらって実際に触れたという至れり尽くせりでした。まだやりたいことが残っているのでいつかやるという気持ちだけ今も持っています(結構経ってしまったけど)。

その他に関する問い

 アピールはそんなないです。なぜなら上でほぼ出し切ったからです。(ここに一文書いてたんですが省略。)あとはatcoderを一時期やっていて水色程度まではいきました。(https://atcoder.jp/users/iwannatto

(いまコメント)

いやだって実際そうやし……。書いて損することはないので書いたほうが良い気はしたんですが、まあ設問の書き方的にもないならないで良いかなと勝手に思ったのと、あと自分が一番強い部分はシステム系の内容を掘るところだと思っているので、それより弱い内容を書いてちょっと加点を狙うよりは上の課題で認められないなら諦めていいかなと思ったので。まあ僕がめんどくさがっただけなので書きたいことがあるなら是非書いたほうが良いとは思います

 来年度以降応募する人向けのアドバイス的ななにか

 こうして見るとなんか恥ずかしいですね、こんなに恥ずかしいのに公開している僕の勇気を讃えてほしい

応募基準にも仄めかされているのとキャンプの雰囲気からも感じ取れるんですが、全体的に器用にまとめるというよりはなんか強い興味みたいなのをドリャーとアピールする方針でいったほうがいいんじゃないかという気がします。

ただ、僕のやつは結構長くウオーって勢いで書いた感じそのままの文章なんですが、別にみんながこうする必要はなくて、各個人が最適なアピールの形態を選ぶのが良いと思います。僕は自分の脳の使い方的にもアウトプットの仕方的にもウオー形式が良いと思ったのでこうしましたが、もうちょい絞って書いたほうが上手くアピールできるという人はそうしてもいいと思います(文章を洗練しても加点されないと基準に書いてあるので、あくまで自分のやりやすさのためですが)。他にネクストで晒している人とかがいないのでわからないんですが、多分僕のは平均より分量が多いんじゃないかなという気もする(かなり疑わしい)(違うかも)ので、この量(10000文字くらい、まあコード引用削ると7000~8000文字くらい?)書くのが必須だということはない気がします。文字数を増やすためだけに無理に引き伸ばしてもあんまり意味がないと思うので、書きたいだけ書くのがいいんじゃないでしょうか。

あとそういえば僕が応募したのはネクストで、これは全国大会修了者くらいのレベル感の人を対象に想定しているらしいのですが、だからといって全国大会修了者である必要はないようです。ていうか僕は全国大会修了者ではないので。ネクストのメンバーには修了者も修了者でない人も両方いたので、たぶん加味とかもされてないです(それはそう)。

なんかこうそんな感じです このページに辿り着いてるってことは応募する気あると思うので頑張ってください、セキュキャン楽しいですよ 楽しいですよって言っといてキャンプ参加記みたいなのは書いていないな 気が向いたら書きますが向かないと書きません

(おわりです)