看板の話

【注意】I'm not a lawyer だよ! This is not legal advice だもんね!


Piro さんが長文を書かれていたので一部だけ切り出してつまみ食い.ただし GPL vs BSDL の話ではなくて看板の話.

  • 自分の作った物が誰にどう使われようとも構わない、極端な話、誰かが看板だけ掛け替えた「改良版」を作って商売していようとも全く構わない、という事であれば、パブリックドメインにしたり、あるいはBSDスタイルのライセンスを選択して問題ないでしょう。
  • 自分の作った物が看板を掛け替えただけの「改良版」として勝手に商売に使われるのは我慢ならない、やるならこっちにも分け前をよこせ、それが嫌なら無償で同じ条件でソースも含めて公開しろ、という事であれば、コピーレフトなライセンスを選択した方がいいでしょう。
  • 自分の作った物がアイデアだけ引き継がれるのはいいけど、自分の血と汗と涙の結晶であるソースコードが他人にそのまま利用されるのは腹立たしい。アイデアを同じように具現化したかったら、自分で同じだけの血と汗と涙を投じて実装し直して欲しい。という事であれば、ソースコードを公開しないクローズドライセンスにした方がいいでしょう。
  • 自分の作った物がソースコードも含めて引き継がれていって欲しい、他の人が自分と同じような苦労をしなくてもいいようにしたい、人類共有の財産にしたい、という時に、コピーレフトにするべきなのか、それともBSDスタイルにするべきなのか。そこが問題です。
Latest topics > 「コピーレフトとBSDスタイルではBSDスタイルの方が発展するのでは」という議論についての誤解あるいは言葉の裏にある欺瞞 - outsider reflex

これを読んで看板の方に反応しちゃったというか,つまり,ソフトウェアに十分以上の思い入れがあるなら,商標とるのも選択肢に入れるべきですかねと.

  • 自分の作ったソフトウェアに対するブランドイメージが,第三者の「改良版」で勝手に使われたり左右されたりするのは我慢ならない.ブランドに影響する活動はぜんぶうちを通してもらうし,新たに何か立ち上げるならブランド構築はゼロからスタートしてもらう → 商標取ろう
  • 自分の作ったソフトウェアに対するブランドイメージが,第三者の活動によってどう利用され・変化しようとかまわない.勝手にやってくれ. → なにもしない or 商標のとれない名前 (地名とか?) を使おう?

て感じなんですかね.
前者の例は,プロプライエタリなソフトウェアはもちろん,OSS の世界でも大手 Linux ディストリビューター (Debian, Fedora, Ubuntu, ...) や MozillaArduino にしろ企業っぽいところはたいていそうです.仮に「改良版」で何か活動しようとしたい場合でも,看板の付け替えはほぼ確実に要求されています.仮に OSS のライセンスを守って著作権をクリアしても,あなたは Debian Lite とか Fedora Lite とか Firefox Lite という名前を使えないことになります.たぶんね.
後者としては,「~ごった煮版」「私家製~」「偽~」「Patched ~」「~版○○」とか煮え切らない名前で公開されているたくさんのソフトウェアの周辺にいくつもの例を見つけることができるでしょう.fork の盛んな OSS の世界ではこういった例もたくさん見ることができます.
つまるところ,あなたが活動を行う上で,ブランドに対する姿勢によっては,商標が必要になるケースがあります.これはOSS・プロプライエタリどちらでも行われていることで,いずれの場合であっても世に先例を見つけることができるでしょう.

2012年やったこと - Chromium 編

前回に引き続き今度は Chromium 編.chromium.org のアカウントを作ってもらったはいいものの,メールアドレスの 1 文字目を大文字にされて激しく凹むということもあった一年.

Windows 8 向け TSF 対応

Chromium を Windows 8 向けに TSF 対応させるというミッション.いやな予感はしていたものの,Mozc の TSF 対応もあるのであまり積極的に手を出せずにいたら,結局ぎりぎりになって火消し案件として振ってきた,という感じの一件.

Windows 8 では IME の TSF 対応が注目されていたりするわけだけど,実は Immersive Mode で動作するブラウザの方も TSF に対応させる必要がある.対応させないと Immersive Mode で CJK の入力ができない.それはまずいというわけで TSF を扱ったことのある Mozc チーム (もっとも Mozc で TSF 経験者といっても私ぐらいだけど) に話が回ってきた.のが 7 月終わりから 8 月頭にかけて.Windows 8 の MSDN 向けリリースは 8 月 15 日.一般リリースは 10 月 26 日.
「どうしてこんなになるまで放っておいたんですかー!」……といっても始まらないので一時期は Mozc チームから 5 人ぐらいヘルプに回しつつ,6 週間 (これは Chromium の平均的なリリースサイクルでもある) でどうにか動くものをでっち上げる.結局細かいバグまで全部取り除くにはもう 1 サイクル (6週間) かかったけど.
この間 Mozilla 方面からはこういう声も聞こえてきたり.


まあ実際は 5 人全員が働きっぱなしということはなくって,内容が専門的になってくるにつれ段階的に人数を減らしていく感じで.戦力の逐次投入の逆ができたという点では満足.
ちなみに自分はリードエンジニアとして参加しつつ,コードを書くよりは主に設計と裏方に注力 (TSF 未経験者ばっかりなので,こうする方がむしろスケールすると判断).全コードのレビューをしたり,ドキュメントをメンテしたり,TSF についての軽い Tech Talk をしたり,Windows のデバッグテクニックのレクチャーをしたり.あとはアーキテクチャ上の最終決定を行ったり (これは胃が痛かった…).同僚がもりもりコードを書いてくれたのでほんと助かった.ぺこり.
もちろん反省点も色々ある.一番大きな反省点は,Chromium のコードレビューに不慣れな人間 (自分含む) がいることを考慮していなかったところ.アプリケーションの TSF 対応では,メッセージポンプやテキストウィジットに手を入れる必要がある.もちろんこれらは重要コンポーネント,大物レビュアーが出てくるし自然とレビューの目も厳しくなる.もうちょっとコミットログや事前の根回しに注意していれば,レビュー期間は半分以下に収まったんじゃないかと思う.最初のキックオフの時にレビュー対策を盛り込んでおけば…… このあたりの文化的背景については @omo2009 先生がすばらしい記事を書いていらっしゃるので興味がある人はこちらをどうぞ.

Handle IMR_QUERYCHARPOSITION even when there is no composition

コンポジション文字列が存在しない時でも IMR_QUERYCHARPOSITION に応答するという変更.実際には単にカーソル位置を返すだけ.

Mozc の TSF 対応を行なっている時に気づいた問題で,空文字列に対するITfContextView::GetTextExt でカーソル位置を取得するためにはこうなっていたほうが都合が良い,という変更.
ブラウザと IME 両方に手を出していると,楽な側で直せるというのは便利.具体的には以下の差が現れる.
f:id:NyaRuRu:20130103213724p:plain
f:id:NyaRuRu:20130103213730p:plain
Chromium 24 にてリリース予定.

2012年やったこと - Mozc 編

いままで仕事で書いたコード (Chromium とか Mozc とか) については基本的に言及しないようにしていたんですが,ソースコードが公開されている内容についてはまあいいかということでまとめてみます (もちろんソースコードが公開されていないことについても色々やってますが).とりあえず Mozc 編*1.順序は概ね時系列.

Visual C++ 2010 対応

ちまちまとコンパイルエラーに対処.ビルドスクリプトを vcbuild に加えて msbuild にも対応させたぐらい.あとは gyp にも問題を見つけたので一件パッチを upstream.

1.3.975.10x にてリリース.

SHOW_INFOLIST_IMMEDIATELY compatibility flag

Windows 環境でのバグ.
Meadow 3.0 や NTEmacs 22 で Mozc を利用していると,用例ウィンドウが表示されないというバグ.Mozc 開発チーム内で発見されて回ってきたもの.
これの原因がなんというか脱力系.もともと用例ウィンドウは「最後の UI 更新から 500 ミリ秒経って何のアクションも起きていなければ表示する」というロジックで動いていた.ところが,Meadow 3.0 や NTEmacs 22 はポーリングを行っていて,より短い間隔で IME の UI 更新通知を送ってくる (実際には更新する必要がないケースでも).これをトリガーとして候補ウィンドウの再レイアウトが行われるため,永遠に「最後の UI 更新から 500 ミリ秒経過」という条件が成立しない.
これらのアプリケーションではディレイなしに用例ウィンドウを表示するようにして対処.

1.3.975.102 にてリリース.

「半角空白を入力」が動作しないバグの修正

たまには変換エンジン側のバグも直してみようキャンペーン第一弾.
カスタムキーマップにて「半角空白を入力」「全角空白を入力」というコマンドが選択可能であるにも関わらず,特定条件でうまく動作しないという問題,の修正.

1.4.1003.10x にてリリース.

キャンセル後 IME を無効化

たまには変換エンジン側のバグも直してみようキャンペーン第二弾.
ATOK と MS-IME のデフォルト設定の違いのひとつに,IME をオフにしたときに未確定の入力文字列を確定させるかそれともキャンセルさせるか,というものがある (MS-IME では確定,ATOK の ATOK キーマップではキャンセルさせるのがデフォルト).
これまでのバージョンの Mozc では MS-IME にあわせて確定させていたのだけど,やっぱり ATOK スタイルが良いという人もいる.そういう人のためにカスタマイズの幅を増やしてみたという変更.
といっても,これ以上コンフィグオプションを増やしたくはないよねということで,「キャンセル後 IME を無効化」というキーコマンド側を追加することで対処してみた.この方法だと,ATOK キー設定に自然に対応させられるのもよし.

ATOK (キーマップ) 派の人向けに実装しただけのつもりが,なぜか vim 方面の人に受けるという不思議な経験もした.

バージョン 1.4.1003.10x にてリリース.

サロゲートペア対応

クライアント側と変換エンジン側両方の修正.
Windows クライアントに関しては,実際サロゲートペア対応をサボっていたのでその対応を粛々と.再変換とか確定取り消し周りが地味にめんどくさかった.
変換エンジン側は,UTF-8 を UCS2 に変換して処理している箇所がいくつか残っていたのでその残党狩り.
この変更のおかげで,後の Unicode 絵文字対応がそこそこ楽になる.
バージョン 1.4.1003.10x にてリリース.

Mozc Issue 14

uim-mozc の開発者の人からのレポートで,Protocol Buffers のライブラリと動的リンクしていると,起動時にエラーになるので静的リンクに変更して欲しい,というもの.レポートから 1 年半以上放置されていたので見かねて修正.
ちなみに Debian/Ubuntu/Fedora/Vineはこの辺まるっと無視して今も動的リンクしていたはず.ほんと静的リンク嫌いますよね……

1.4.1003.10x にてリリース.

GCC 4.7 環境での warning つぶし

Linux 向け修正.
タイトル通り.
1.4.1003.10x にてリリース.

ibus_engine_delete_surrounding_text 対応

Linux の IBus 環境向け変更.IBus の比較的新しい API である ibus_engine_delete_surrounding_text を使用して,確定取り消し・再変換を実装するというもの.これ以前は Windows のようにバックスペースキーイベントを送っていた.
ちょうど Firefox 側に関連バグが登録されていたのだけど,Mozc 側の問題ということで対処できた感じになる.

1.4.1003.10x にてリリース.

gtest なしでのビルドのサポート

openSUSE のパッケージで,Mozc が gtest に依存するのを独自パッチをあててまで回避しているっぽかったので,そういうことをしなくて良いように上流側で対処してみた,というもの.
1.4.1033.10x にてリリース.

compiler_specific.h 導入

コンパイラ依存コードの便利マクロ集.Chromium の同名のファイルにインスパイアされたもの.この頃から Clang 対応を考え始める.

1.5.1053.10x にてリリース

cURL 依存の排除

Linux 向け変更.
OSS Mozc ではネットワーク機能を一切有効にしていないにもかかわらず,ビルドに cURL が必要という状態だったので,cURL なしでビルドできるようにしたというもの.
1.5.1053.10x にてリリース

QTBUG-25536 対策

Qt QString::toUcs4() がサロゲートペア領域の文字に対してうまく動かない,という問題に対する Mozc 側のワークアラウンド.

const uint kData[] = { 0x10000 };
QString test = QString::fromUcs4(kData, 1);
const QVector<uint> ucs4s = test.toUcs4();
if (ucs4s.size() == 1) {
    qDebug() << "correct";
} else {
    qDebug() << "wrong";
}

このコード,最新の Qt 5.0.0 でも正しく動かない.ので,Mozc から QString::toUcs4() の呼び出しを削除する方向で対処.

1.5.1053.10x にてリリース

X11 Selection monitor

Linux 向け.
ibus-mozc が GtkTextView でしか再変換ができなかったのを,もうちょっと対応環境を増やした,という変更.
諸悪の根源は,Gtk IM Module の get_surrounding_text がしょぼいことである.この API,カーソル周辺文字列 + カーソル位置しか取得できない.アンカー位置が取得できないため,現在選択されているテキストというのが分からない状態で再変換を実装しなければならない.
今回とった workaround は,xcb-xfixes を利用して,X11 のセレクションイベントをモニターするというもの.セレクションイベント経由で現在選択されているテキストを記録しておいて,get_surrounding_text で取得された周辺文字列 + カーソル位置と比較し,矛盾がないように選択領域を再構築する.
xcb とかはじめて使ったのでなかなかにおもしろかった.

あと,このコードを書いているときに Linux 版 Firefox にサロゲートペア絡みのバグを見つけたので,Bugzilla に報告したところ,Mozilla Japan の中野さんに直して頂けました.感謝.

1.6.1187.102 にてリリース.

Mac OS X Lion でのビルド対応

対応したつもりになって 1 年近く放置してしまったバグの対処.

1.6.1187.102 にてリリース.

scim-mozc is removed

予告通り scim-mozc をリポジトリから削除.
直接の原因は内部のメンテナの不在.
まあ今更 SCIM もないでしょう.(Tizen を除く)

1.6.1187.102 にてリリース.

Debian-specific files are removed

Mozc のリポジトリに存在する Debian パッケージ定義ファイルがメンテナンスされていないので削除した,というもの.
ちょうど Debian 本家でメンテナンスされているパッケージ定義ファイルとの乖離が激しくなってきたところだったというのも理由のひとつ.

1.6.1187.102 にてリリース.

IBus 1.4.1 未満のサポート停止

IBUS_CHECK_VERSION マクロがあちこちに散らばっていたので,一カ所にまとめた上,旧バージョンのサポートと停止.だいぶコードが綺麗になる.

1.6.1187.102 にてリリース.

Clang 対応開始

Clang revision 159409 を使用して発生する warning を全て解消 (または suppress).
1.6.1187.102 にてリリース.

Visual C++ 2012 対応

ちなちまとコンパイルエラーに対処.
1.6.1187.102 にてリリース.

#include <Windows.h> 撲滅運動

実に多くのヘッダファイルが不必要に #include <Windows.h> していることに気付きあちこち改良した,というもの.logging.h が <Windows.h> に依存するとかどうかと思う.

これでビルドがちょっとは速くなってくれるといいなぁと思いつつやったものの,目立っては高速化しなかった.残念.
1.6.1187.102 にてリリース.

Ack-less IPC

Windows の IPC レイヤの改善.いままでの IPC クライアントは,
1. メッセージ送信
2. 応答受信
3. Ack 送信
という手順を踏んでいたのを,3. でいきなり名前付きパイプを切断するように変更.切断イベントはどちらにしろサーバ側で検知可能なので,これを Ack イベントの代用とする.
実際これでレイテンシが数パーセント減ったのだから儲けものである.

1.6.1187.102 にてリリース.

StringPiece の移植

Mozc の portable library に StringPiece がないのが気になっていたので,えいやっと用意した一品.StringPiece については hamaji さんの解説記事 とか参照のこと.

1.6.1187.102 にてリリース.

テンキーにあるコンマに対応

Apple 日本語キーボードのテンキーには,ピリオドキーだけでなくコンマキーもあるのですが,これに対応できていなかったという問題の修正.
Mac では kVK_JIS_KeypadComma を使えば良いのですが,困ったのが Windows.
なんと Brazilian キーボードにはテンキーにコンマがあるらしく,その仮想キーコードは VK_ABNT_C2 (0xC2) とのこと.実際,Apple 日本語キーボードを Windows 7 につなげてテンキーのコンマを押してもこの仮想キーコードが返ってきました.互換性への執念恐るべし.
https://code.google.com/p/mozc/source/browse/trunk/src/win32/ime/ime_keyevent_handler.cc?r=124#253

  // The numpad comma on the Apple Japanese 109 keyboard is somehow mapped into
  // VK_ABNT_C2, which is only defined in kbd.h.
  // See also http://blogs.msdn.com/b/michkap/archive/2006/10/07/799605.aspx
  // See also b/6639635.
  KeyEvent::COMMA,                // 0xC2: VK_ABNT_C2

1.6.1187.102 にてリリース.


2012年他にやったこと - Mozc 編 - NyaRuRuが地球にいたころに続く.


Chromium に関しては 2012年やったこと - Chromium 編 - NyaRuRuが地球にいたころ に続く.

*1:ここでは OSS Mozc に限らず,いわゆる code-name Mozc についての活動

apt-get upgrade gcc considered harmful

いまの仕事に就いたことで触れることのできた興味深いソフトウェア開発手法のひとつに,成果物に関するものであれば何であれ"ソースコード"のバージョン管理システムに関連づけるというものがある.使用するライブラリは言うに及ばず,ビルドに使用するコンパイラのバージョンまでもを,ソースコードと同列にバージョン管理するわけだ.
このような環境で仕事を続けることしばし,ふと気付けば,多くの Linux ディストリビューションで喧伝されるうたい文句,「依存関係を賢く管理し,多数のユーザーによってテストされ,コマンド一発でインストールもアップデートもできる多数の開発ツール!」,というものは酷く色あせて聞こえるようになっていた.
むしろ逆だ.ソースコードバージョン管理システムとは異なるコマンドによってコンパイラやライブラリのバージョンが変化する!? そんなものは悪い冗談にしか聞こえない.そこにはコミットログも存在しなければ,コミット前のスモークテストも存在しない.ブランチを切ることもできなければ,不具合を見つけてもソースコードのようにはロールバックすることもできない.


などというようなことを『継続的デリバリー』を読みつつうなずいていた年末.いやー,本に書いてあるようなお手本運用を間近で見つつ仕事できるってのは刺激になっていいですねー.それではみなさま,来年も良いビルドを.
継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化

サービスを最小特権で実行する

今回は Windows サービスを作成する上でのセキュリティ上のポイントを軽く紹介する.
Windows Vista では,サービスをより安全に実行するために Service Control Manager (SCM) の改善が行われている.ポイントとなるのは,必要特権リストの指定が可能になったこと,および制限された SID を割り当てられるようになったことだ.
たとえば,特定ファイルを物理メモリ上に保持し続けるサービスを作りたいとする.この処理をサービスにする必要があるのは,それが特権を必要とするからだ.VirtualLock API でロック可能なメモリ領域は通常 30 ページに制限されており,SetProcessWorkingSetSize API でその制限を拡大するには,SE_INC_BASE_PRIORITY_NAME 特権が必要である.しかし,単純に System アカウントで動くサービスを作ったのでは,余分な特権まで有効にされてしまう.これは最小特権の原則に反する.
ここで,以下のように ChangeServiceConfig2 API を利用することで,サービスに付与される特権を制限できる.

SERVICE_REQUIRED_PRIVILEGES_INFO privileges_info = {};
privileges_info.pmszRequiredPrivileges = SE_INC_BASE_PRIORITY_NAME _T("\0");
ChangeServiceConfig2(service_handle, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO,
                     &privileges_info);

また,このサービスはファイルやレジストリに書き込む必要がない.そこで,以下のように設定することで,意図せずファイルやレジストリに書き込もうとしたときに失敗するように構成できる.

SERVICE_SID_INFO sid_info = {};
sid_info.dwServiceSidType = SERVICE_SID_TYPE_RESTRICTED;
ChangeServiceConfig2(service_handle, SERVICE_CONFIG_SERVICE_SID_INFO,
                     &sid_info);

このように設定したサービスを起動し,Process Explorer でセキュリティ情報を見てみる.
f:id:NyaRuRu:20121015010639p:plain
Restricted SID が設定されていること,"NT AUTHORITY\WRITE RESTRICTED" SID が設定されていること,特権が大幅に削除されていることなどがわかる.
実際,OS 標準のサービスは概ね最小特権で実行されている一方で,(残念ながら Microsoft Office を含む) OS 非標準のサービスは,デフォルトの特権を持ったまま動作しているものがほとんどだ.例えば,Office 2010 に付属する ImeDictUpdateService (Microsoft IME Dictionary Update) のセキュリティ属性は以下のようになる.
f:id:NyaRuRu:20121015010658p:plain
デフォルトで付与される全ての特権を持ったまま実行されていることが分かる.これが本当に IME の辞書アップデートサービスであるなら,SeDebugPrivilege (スーパー特権のひとつ.プロセスのセキュリティ設定を無視して,(保護されたプロセスをのぞく) すべてのプロセスを開くことができる.) や,SeTimeZonePrivilege (文字通りタイムゾーンを設定するための特権) をはじめとした,多くの特権を削除しても恐らく動作は可能だろう.

AppContainer 導入による Windows 開発への影響

Windows 8 では,AppContainer と呼ばれる新たな Sandbox メカニズムが導入される.Windows ストアアプリ (旧名: Windows Metro アプリ) や,Immersive モードの Internet Explorerレンダリングプロセスなどが AppContainer で動作するプロセスの代表格だ.Windows ストアアプリ制作者にとって AppContainer が重要になるのはもちろんのこと,Windows ストアアプリ内で動作する必要のある IMEアクセシビリティ系ツールの制作者も,AppContainer について理解する必要がでてくる.

AppContainer プロセスを確認する

Process Explorer 15.23 を用いて,AppContainer プロセスの特徴を確認してみよう.以下は Windows 8 付属の「ミュージック」アプリを起動し,Process Explorer にて表示してみたところだ.
まず目に付く点として,WWAHost.exe プロセスの Integrity 欄に AppContainer と表示されていることが挙げられる.
f:id:NyaRuRu:20121008185343p:plain
次に WWAHost.exe プロセスのプロパティを表示し,Security Tab を選択してみる.プロセスのグループ一覧に,AppContainer と Capability という見慣れないグループがある.
f:id:NyaRuRu:20121008185402p:plain
前者は Windows ストアアプリごとに割り当てられるユニークな SID である.Android 環境でアプリケーションごとに User ID が割り当てられるのと似ている.後者の Capability は,この Windows ストアアプリに許可された動作と対応している.「ミュージック」アプリは,

  • インターネット接続へのアクセス
  • ミュージックライブラリへのアクセス

が許可されているようだ.
このように,AppContainer は,従来のトークン/SIDによるアクセス制御の拡張として実装されていることが分かる.例としては,Windows ストアアプリごとに SID が付与されることから,ある Windows ストアアプリにだけ,特定ディレクトリ以下へのアクセスを許すようなポリシーを設定することも可能である.

あるプロセスが AppContainer に属しているかどうかをプログラム的に判定する

あるプロセスが AppContainer に属しているかどうかをプログラム的に判定するには,プロセスのトークンハンドルに対して GetTokenInformation API を使用する.Windows 8 (SDK) 以降では TokenIsAppContainer フラグが使用でき,ここで 0 が返ってこなければプロセスは AppContainer で動作している.

あるプロセスが Immersive Mode かどうかをプログラム的に判定する

あるプロセスが没入型 UI を使用しているかどうかの判定には IsImmersiveProcess API を用いる.この用途で GetTokenInformation/TokenIsAppContainer フラグを使用するべきではない.なぜか?
それは Windows ストアアプリ風アプリケーション全てが AppContainer 内で動作するわけではないからだ.ブラウザという大きな例外がある.
Metro スタイル対応デスクトップ ブラウザーの開発」というホワイトペーパーに解説されているとおり,Windows 8 対応のブラウザには以下の 3 種類が存在する.

  1. Windows Store app: AppContainer 内で動作する
  2. Desktop browsers: Windows 7 までと同様のモデルで動作する.Win32 API にフルアクセスが可能で,JIT コンパイルや様々なマルチプロセス技術が利用可能.
  3. New experience enabled desktop browser: Windows ストアアプリ風の没入型 UI を備えつつ,Win32 API にフルアクセスが可能で,JIT コンパイルや様々なマルチプロセス技術が利用可能.

この 3 つ目が問題だ.結果として,没入型 UI かどうかの判定と AppContainer で動いているかどうかの判定は分けて考える必要がある.

AppContainer の SID を取得する

プロセスのトークンハンドルに対して GetTokenInformation API を使用する.Windows 8 (SDK) 以降では TokenAppContainerSid フラグが使用でき,ここで返ってきたものが AppContainer の SID である.

AppContainer プロセスのオブジェクト名前空間

引き続き,Process Explorer で AppContainer の動作を調べてみる.「View」→「Lower Pane View」から「Handles」を選択し,プロセス内で開かれているハンドル情報を調べてみよう.
開かれているハンドル名を見ていくと,セッション名前空間にさらに AppContainer SID が接頭辞として付加されていることに気付く.
f:id:NyaRuRu:20121008185545p:plain

\Sessions\1\AppContainerNamedObjects\S-1-15-2-43664394-2685677502-394080391-3933305958-4167273977-1510959782-2102270723\RPC Control\OLE36E12F064548B659D96055B91BF5

これに対応すると考えられる GetAppContainerNamedObjectPath API の Remarks が興味深い.この Remarks は,アクセシビリティ系など,別プロセス内で動作するツールに向けて書かれたものだ.

For assistive technology tools that work across Windows Store apps and desktop applications and have features that get loaded in the context of Windows Store apps, at times it may be necessary for the in-context feature to synchronize with the tool. Typically such synchronization is accomplished by establishing a named object in the user's session. Windows Store apps pose a challenge for this mechanism because, by default, named objects in the user's or global session are not accessible to Windows Store apps. We recommend that you update assistive technology tools to use UI Automation APIs or Magnification APIs to avoid such pitfalls. In the interim, it may be necessary to continue using named objects.

GetAppContainerNamedObjectPath

デフォルトでは Windows Store アプリからは従来の名前付きオブジェクトにアクセスできないものの,アクセス権を設定しさえすればデスクトップアプリと Windows Store アプリの間で名前付きオブジェクトを共有することが依然として可能であることが示唆されている.なお,これは暫定的な措置であり,本来は UI Automation API や拡大鏡 API を用いて対処して欲しいようだ.

All Application Packages グループを利用したアクセス制御

実は,Windows 8 では ALL APPLICATION PACKAGES と呼ばれる特殊なグループが追加されている.このグループへのアクセス許可を設定することで,Windows Store アプリに一括して動作の許可や拒否を設定することができる.
これについては,ファイルシステムの例がわかりやすい.%SystemRoot% や %ProgramFiles% のセキュリティ設定を見てみよう.Windows 8 では,デフォルトで ALL APPLICATION PACKAGES グループに対する「読み取りと実行」「フォルダーの内容の一覧表示」「読み取り」アクセスが許可されている.
f:id:NyaRuRu:20121008185631p:plain
仮に IME を開発するのであれば,仮に AppContainer 内で動作する場合であっても,ACL 的にはこれらのディレクトリ (以下) に配置された設定ファイルや辞書データは自由に読み取りできるものと考えられる.
また,試したわけではないが,AppContainer 内で動作する Windows Store アプリであっても,%ProgramFiles% 以下にインストールされたアプリケーション一覧や置かれたファイルの内容を取得することぐらいは可能なのかもしれない.これらの領域にセキュリティやプライバシーに関わるデータが置かれる場合は,悪意のある Windows Store アプリに読み取られる恐れがないか改めて確認されたい.
さて,ALL APPLICATION PACKAGES だが,ファイルオブジェクト以外にも当然利用されているようだ.
以下は,TSF が利用していると思われる Mutex オブジェクトのセキュリティ情報である.
f:id:NyaRuRu:20121008185714p:plain
ALL APPLICATION PACKAGES に同期とクエリ許可が与えられていることが分かる.このように,DACL を設定することで,Windows Store アプリとデスクトップアプリの間で名前付きオブジェクトを共有することが可能になるのだろう.
Windows Store アプリとデスクトップアプリの間のプロセス間通信についてもいずれいくつか書いてみたい.

参考

Google Chrome をデバッグする (1)

Google Chrome のデイリーリリースバージョンは,炭鉱にて危険をいち早く察知するカナリアにたとえられ Canary 版と呼ばれている.
(炭鉱で戦うものたちの熱い物語については『炭鉱の庭師』を参照されたい)
Google Chrome Canary 版は以下のページからインストールできる.
https://tools.google.com/dlpage/chromesxs
Canary 版と安定版は,インストール先フォルダから使用するプロファイルまで異なる別アプリケーションである (Side-by-side インストールと呼ばれている).両者を同時に起動することももちろん可能だ.また,Canary 版であっても Google Update の対象になることから,一度インストールしてしまえば後は自動で trunk を追いかけてくれる.
実は,Canary 版にはもうひとつ大きな特徴がある.それは,ビルドの副産物であるデバッグシンボルが公開されていることだ.ここで,デバッグシンボルが公開されていることで何が可能になるかについて,数回にわたって紹介してみたい.

シンボルサーバの登録

Windows エコシステムでのシンボルサーバの登録には,環境変数 _NT_SYMBOL_PATH を使用するのが一般的だ.Microsoft のシンボルサーバと Chrome のシンボルサーバを登録する場合,_NT_SYMBOL_PATH は次のように設定することになる.

_NT_SYMBOL_PATH=srv*c:\SymCache*http://msdl.microsoft.com/download/symbols;srv*C:\SymCache*http://chromium-browser-symsrv.commondatastorage.googleapis.com

"C:\SymCache" は別の名前に変更することも可能である.このフォルダにダウンロードされたシンボルデータがキャッシュされるので,なるべく高速なドライブを設定すると良い.
次に,よく利用する Sysinternals のツール群についてもシンボルパスを設定する.
f:id:NyaRuRu:20120930014804p:plain
Process Explorer と Process Monitor それぞれで,Options から Configure Symbols を選択する.Dbghelp.dll path については,Windows SDK 付属のものを選ぶとよい.64-bit 環境では x64 版の Dbghelp.dll を選択しよう.Symbol paths については先ほど同様に以下を設定する.

srv*c:\SymCache*http://msdl.microsoft.com/download/symbols;srv*C:\SymCache*http://chromium-browser-symsrv.commondatastorage.googleapis.com

Process Explorer を利用したハングアップ解析

Google Chrome Canary 版が無反応になったなら,Process Explorer を起動してみよう.デバッグシンボルが完備されていればその場でスレッドのコールスタックを見るのも容易である.(ただし,ここで最も慎重な次の一手はプロセスダンプをとることだ)
状況の保全のため,プロセスの全スレッドを中断させてみよう.一般的に,Chrome のウィンドウが無反応になったときには Chrome のブラウザプロセスの問題である.Process Explorer の "Process" 欄を何度かクリックして,表示モードをプロセスツリーに変更しよう.ここでルートに当たる chrome プロセスがブラウザプロセスである.(別の識別法として,プロセスの起動引数に --type オプションが付いていないプロセスを選ぶという方法もある)
f:id:NyaRuRu:20120930014912p:plain
ブラウザプロセスを見つけたら,コンテキストメニューから Suspend を選択する.これでブラウザプロセスの動作が中断する.動作を中断させたら,コンテキストメニューから Properties を選択し,Threads タブに移動する.
f:id:NyaRuRu:20120930014932p:plain
ここでスレッドを選択し Stack ボタンをクリックすると,該当スレッドのコールスタックが表示される.
f:id:NyaRuRu:20120930014952p:plain
コールスタックを表示すると,非同期でシンボルのダウンロードが始まる.しばらくすると,Chrome のどういった関数が呼び出されていたのかが表示されるだろう.UI スレッドを探し出し,そのコールスタックを探し当てたら,それがハングアップの現場である.

Process Monitor を利用した I/O モニタリング

Process Monitor を利用することで,以下のような動作のモニタリングが可能になる.

  • 任意のファイルアクセス
  • 任意のレジストリアクセス
  • 任意のプロセス起動/スレッドイベント/DLL のロードとアンロード
  • 任意のネットワークアクセス

シンボルがセットされていると,これらの各イベント発生時のコールスタックが取得できるようになる.また,Tools メニューの各 Summary 項目から,選択したイベントの集計やクロス集計も可能である.例えば,プロセス起動時から終了時までの間にあるファイルへ行われた全てのファイルアクセスについて,コールスタックごとにその割合を分析するといったことが可能だ.

f:id:NyaRuRu:20120930015009p:plain
Chrome を起動してあるページをブラウズし,終了するまでの間に行われた約 2000 回のファイル読み取りアクセスを,コールスタックを用いてブレイクダウンしている図

Process Monitor を用いた解析テクニックについては,例えば次の記事などが参考になる.

次回,API モニタ編に続く.