February 2011 Archives

opentkいじり2

| No Comments | No TrackBacks

少々事情があって、しばらく3Dまわりのことをやることになった(あまり寄り道したくないのだけど、これは前々から決まっていたことなので仕方がない)。とりあえず、先月ちょいと眺めてみたopentkを実際にいじってみようと思い立った。とりあえずWebGL相当の機能がほしい。

OpenTKのバインディングは、それぞれ数千行単位で存在しているのだけど、どうやらこれらは自動生成されているようだ。少なくともOpenGL ESについてはそうらしい。WebGLはOpenGLES2.0のレベルで足りるので、その仕組みを探ってみた。ドキュメントがほとんど無いので、ジェネレータのソースから推測して動かしてみた部分が多い。

自動生成は、khronosが配布しているCのヘッダファイルを正規表現マッチで(書式決めうちで)解析して、その結果をいったんxmlにした上で、それをC#やC++に変換しているようだ。Converter.exeがCヘッダ解析とXML生成を行い、Bind.exeがXML解析とC#生成を行う。

Bind.exeはストレートに動作したのだけど、Converter.exeは引数をいろいろ指定してやらなければならない。実際には、ビルドして生成されたBinaries/OpenTK/Debugから Converter.exe -p=gl -v:2.0 ../../../Source/Converter/Headers/ES20/gl2ext.h ../../../Source/Converter/Headers/ES20/gl2.h > gl20.xml のように実行して生成する必要がある。生成されるのは Source/Bind/Specifications/ES20/signatures.xml のようなファイルだが、一応生成したものと既存のファイルが一致するかどうかを確認した方が良い(そして一致しない)。

OpenTKは、それをもとにenum, function (wrapper), delegate (DlllImport)といったメンバーを生成する。今回はDllImportが使えないので、ここに相当するコードを別のものとして書き換えたい。CSharpCodeBuilderに少し手を加えれば出来そうだけど、まずsignatures.xmlが適切に生成されていることが重要だ...と思って、ES20相当のファイルとWebGLの仕様を比較していて気がついた。

WebGLのメンバー名は割と変更されている...

たとえば、glGenBuffers()はWebGLRenderingContextではcreateBuffer()となっている。Javascriptにはポインタなど無いので、返値がそのままバッファオブジェクトになる。といった感じで、Javascript向けにいろいろ手を加えられているようだ。これはもはや別のAPIとして捉えた方が良さそうだ。

ふと気がついてES1.1とES2.0のそれぞれに対応するOpenTKのAPIを比較してみた。すると、どうやら1.1にしか無い関数などは2.0のバインディングには存在していないようだ。どうやらOpenTKは、互換性のために名前の違いを吸収するということはあまり行わず(overrides.xmlについてのみ行い)、対象バージョンに合ったAPIを自動生成するというアプローチを採っているようだ。それならば、WebGLについては、WebGLのAPIに合わせたAPIを自動生成すれば良さそうだ。

とりあえず今日わかったことはここまで。明日はもし出来たらAPI自動生成に挑戦してみようと思う。

ビルドサーバのコード実行

| No Comments | No TrackBacks

先週はついに平日だけでの土日も全てつぶれてしまってほとんど何も出来なかったのだけど、間を縫って、ビルドスクリプト(とビルド)の実行だけを担うアカウントを作ってautotoolsビルドが通るところまでは実装した(それだけのことでも、android ndkのincludeファイルのパーミッションがなぜか640でゲスト読み取り不可だったりと、謎のトラップがあったりした)。webアプリケーションも、どちらかというとwebサーバのバグに引っかかって原因を突き止める作業が中心になってしまって、進んでいない。

本当ならそろそろサイトを公開している予定だったのだけど、理想からかけ離れたペースで進んでいるので、今後は少し余計な予定を切り落とそうと思っている。

それはさておき、先週はどちらかと言えば任意のコードを実行されうる危険からある程度合理的に安全性を確保するということについて考えていた。一応ユーザー登録によってフィルタできるとはいえ、ユーザーが投稿するコードをそのまま実行することになるわけだから、本質的に危険な挑戦になる。作りかけのサイトを見てもらった時に、gitなどから直接コードを引っ張ってこられるようにしたいというフィードバックをもらったのだけど、確かにそうなると便利だとは思いつつ、ユーザー自身が管理しないモジュールをビルドで引っ張ってくることになるわけで、割と消極的だったりする。

ビルドサーバ上で任意のコードが実行されうるというのは、実のところこのwebアプリケーション固有の問題ではなく、およそあらゆるプログラミング言語やフレームワークのCI環境などで発生しうる問題だ。悪意のコミッターがunit testの中に rm -rf / のようなコードを混ぜてもきちんと拒絶できる必要がある。悪意でなくても過失で危険なコードが動いてしまうこともある。まあCGIWrap相当のことが行われていれば、とりあえずは大丈夫だろうと思う。

この方面については、他にも類似の例があった。rpmbuildだ。rpmbuildで安全性を確保するひとつのやり方は、chrootを使うというものだ。実のところ、rpmbuildにおけるchrootは、必須依存ライブラリの切り離しを環境非依存にするというのが主目的だけど、ルートディレクトリの隔離という側面も無視できないだろう。(と思ったけど実のところrpmbuild内でビルドを実行するuserが非sudoerでビルドを実行するかどうかはちゃんと確認していない。これがsudoerだったらchrootの再度呼び出しでjailbreakできてしまう。)

ちなみに、ビルドサーバ上で任意のビルドコードが実行されうるという問題は、実際にビルドされて対象プラットフォーム上で実行されるコードに悪意のものが含まれている可能性があるという問題とは別のものだ。これは実のところこのwebアプリケーションでは対応できないから、ソースの入手だけを確実にできるようにすることで利用者責任としようと思っている。

あと、androidの場合は、アプリケーションごとにユーザーが作成されるかたちでシステムレベルではセキュリティが担保されるので、悪意のコードが実行できることによる問題は致命的ではないと思っている(個人情報へのアクセスなどは、アプリケーションのインストールの際に確認されているはずで、やはり最終的には利用者が責任を負える)。

ビルドされたコードの安全性の問題にも実は前例がある。先ほどrpmbuildについて言及したけど、opensuse build serviceが好例だ。これはたくさんのビルド登録者がOSSプロジェクトをビルドして登録し、そのパッケージの今度は消費者がwebで検索してダウンロードする、という、単純なシステムだ。ここには、ビルドされたコードに攻撃コードが含まれている可能性がある、という問題がある。ビルドしたユーザーは分かっているが、匿名で追跡困難なユーザーかもしれない。

opensuse build serviceでは、この問題に対して、機械的にコードの品質をチェックするのと並行して、「個人に対する信頼性」をパラメータ化して人的に解決するアプローチを採っているようだ。これはさすがにこの小さなプロジェクトでは実現できないので、当面は身元の分かっている人のユーザー登録のみを受け付けるかたちで運用しようと思っている。

しっかり対応しようと思うと難しい問題だけど、どこかで折り合いをつけなければ先に進めない。「永遠にアルファクオリティ」として運用することになるだろうとは思っている。

Webいじり3週間経過

| No Comments | No TrackBacks

今週は平日にはあまり自分のコードをいじる余裕が無かったのだけど、連休ということもあって、それなりにビルドサーバをいじることができた。とりあえずプロジェクトを登録してビルド出来るようになった。今のところautotoolsとndk-build、あとは配布ファイルをそのまま含んでいるprebuiltなパッケージに対応している。ビルドした成果は、abi別のバイナリアーカイブとして保存している。

ndk-buildについては、Android.mkのあるディレクトリを探して、そこをworking directoryとしてndk-buildを呼び出すようにしている。そして ../libs にビルドされたライブラリが生成されるとみなして、それをバイナリアーカイブに含めるようにしている。また、Android-OpenCVを試してみたところ、ビルドは出来たもののlibsディレクトリに.soファイルが含まれていないということに気がついたので、 ../obj ディレクトリもバイナリアーカイブに含めることにした。

autotoolsについては、以前に書いた通りのビルドを実践している。NDK r4とr5でパスが違うので、そこはスクリプトで調整している。autotoolsのmake / make installではshared libraryをビルドしてくれないので、インストールされた.aファイルを全部.soにコンパイルし直す作業をpost-installの作業として行っている。

autotoolsプロジェクトのバイナリアーカイブには、make installでインストールされたファイルが全て保存される。androidで利用できるライブラリとしては、バイナリ実行ファイルその他は不要なのだけど、このビルドサーバが本領を発揮するのは、ビルドされた他のパッケージに依存する他のライブラリをビルドする場合だ。成果物を共有ライブラリだけで配布していたら、それに依存する他のライブラリをビルドする場合には、やはり依存ライブラリからビルドしなければならなくなる。これでは面倒だ。そんなわけで、このビルドサーバでは、依存パッケージのファイルを事前に展開して、それらにPATHやLD_LIBRARY_PATH, PKG_CONFIG_PATHを通してビルドを走らせることにしている。今のところproof of conceptとして、liboggに依存するlibvorbisをこれでビルドできている。

プロジェクトビルドのdogfoodingが出来て、ある程度実用的に使えそうだということが分かったので、このまま継続してサイトを作り込もうという気持ちになってきた。そもそもndk-build一発でビルド出来るソースアーカイブを用意してもビルド出来ない人というのがそれなりにいるらしいので(たしかにNDKまで勉強したくないという人もそれなりにいそうだ)、そういう人がダウンロードするだけで足りる環境を用意するという意味でも便利なのかもしれない。

例によって公開できるようになるには、入力検証とビルドのアクセス制限が必要になるので、まだ出来そうにはない。

webいじり2週間経過

| No Comments | No TrackBacks

仕事の一環としてwebいじりができる日々は終わってしまったので、先週は空いていた日の晩しか作業できなかった。とりあえずコレは優先的に片付けたい。作業内容もリファクタリングや足りない部分を埋める程度のことしか行っていないので、特筆することが無い。dogfoodingできるところまでは早めにもっていきたいところだ。

入力のvalidationまわりが必要になるのだけど、何かしらのフレームワークを作ってやる必要がありそうだ。webサーバのコミュニティで相談してみると、ASP.NET MVCみたいなattribute based validationでは柔軟性に欠けるという。それならば自前で用意するしかなさそうだ。HTTP入力をパラメータにマッピングする機能は(簡単なものは)webサーバ上で既に実装されているけど、そこから複雑なオブジェクト(あるいは単にmodel)を構築する部分と、それをエラーレポートする仕組みさえあれば足りる気はしている。

データ量は大したこともないだろうと思ってろくに検証していないのだけど、試してみて、場合によってはredisからRDBに転換する必要も生じるかもしれない。

一番問題になるのは投稿されるコードがビルドの過程で実行されるということで、これはユーザーコンテキストをきちんと管理して、操作できる領域を限定する必要が生じるだろう。少々面倒そうだけど、絶対に必要になる。

まだまだ先は短くないようだ。