hogeとはワイルドカードのようなものです。日々起こった、さまざまなこと −すなわちワイルドカード− を取り上げて日記を書く、という意味で名付けたのかというとそうでもありません。適当に決めたらこんな理由が浮かんできました。
10/26/2011 ふむ [長年日記]
■ [Linux] capabilities
いつまでも最新がうんこの話ではみっともないのでまともな話で埋めるべく立ち上がった 1 人の戦士 atzm がちょっくら調べてみたことをとりとめもなく特に何のまとめもせずつらつらと書いてみる.
さて Linux には root という奴がいてこの人は何でもできちゃうスーパーマンなのだということは語るに及ばずなのだけれど,実はこのスーパーな特権を root から剥奪したり,別のプロセス (スレッド) に付与したりできる capability (ケーパビリティ) というものがある.
capability はいくつかの種類に分かれていて,例えば「任意のファイルを chown できる」とか「mount できる」とか,普通 root でしかできないような操作をその種類毎にプロセス (スレッド) に設定できる.
ただしこの機能が off のような扱いになっているシステムも多い (2.6.24 より前のカーネルなら殆ど).capability の種類の中に「許可する capability を変更できる」というものがあるのだけれど,そのようなシステムではこれが全てのプロセスに与えられていないからだ. なおこのようなシステムで capability を実質的に使えるようにする手段はぐぐれば大量に出てくる.
...のだけれど,日本語で得られる情報の多くが 2.6.24 より前のやり方なので注意. 2.6.24 で file capability がサポートされ,2.6.25 以降から /proc/sys/kernel/cap-bound はなくなった. 2.6.24 以降では file capability がサポートされているので,あるファイルに対する execve 時にセットする capability を設定できる. 2.6.25 以降では capability bounding set はスレッド単位の概念になり,システム全体で共通のものは消え去った.
例えば cat /proc/self/status とかしたときに出てくる Cap*** の値が,その cat プロセスの持っている capability の集合を示す (スレッドなら 更に下の task/TID を見る). より分かりやすい表示を求めるなら libcap や libcap-ng といったツールの getpcaps や pscap 等を使う. セットしたい場合は,2.6.25 以降なら,呼び出し元プロセスの capability bounding set が full であれば,setcap 等で実行ファイルに許可したい capability を permitted/effective にセットしてやれば良さそうだ.試してないけど.
追記
2.6.39 で file capability を試してみた.ファイルシステム依存なのではまって,カーネルのコードを流し読むはめに... 拡張属性サポートを入れてない reiserfs 上で試してて「あれー使えない」とはまっていただけだったくさい.
で拡張属性サポートの入った ext3 上の実行ファイルに capset コマンドで設定しておき,capability bounding set が full の一般ユーザ (のスレッド) が実行したら,通常は EPERM る処理を実行することができた.
10/27/2011 うむ [長年日記]
■ [Linux] smp_affinity
うんこを流す計画その 2.
最近のハードウェアなら CPU コアが沢山乗っているのが当たり前なわけだけど,さて,例えば NIC にパケットが届いた際にシステムがどういう動きをするかというと,簡単に言えば,ハードウェア割り込みが発生して,それをシステムがハンドルするという流れになる.Linux ではこの割り込みをハンドルするのをある CPU だけに固定してしまったりすることができる.
例えば /proc/interrupts を見てみると,以下のようなものが出てくる.
$ cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 (略) 47: 5517603 28 30 31 PCI-MSI-edge eth0 (略)
これは IRQ 47 eth0 からの割り込みを CPU0 が 5517603 回処理したということを表す.その他の CPU も同様.
で,じゃあ現在 IRQ 47 からの割り込みをハンドルする CPU の設定はどうなっているかというと,
# cat /proc/irq/47/smp_affinity f
f つまり 15,2 進数で表せば 1111 となる. この値はビットマスクであり,下位から 1 ビット目が CPU0,2 ビット目が CPU1,... というように対応付けられていて,ビットが立っていればハンドル可能という意味になる.
全部の CPU がハンドル可能だなんて許さん! CPU3 だけが処理しとけばいいんだ! という怒りっぽいあなたは以下のようにマスクを設定すれば良い.
# echo 8 > /proc/irq/47/smp_affinity
8 つまり 2 進数で表せば 1000 なので,CPU3 だけがハンドルを許可された状態となる. この状態になった後でしばらく /proc/interrupts を眺めていると,カウンタの増加が CPU3 にだけ起こっているということを確認できる.
なおこの辺の話はカーネルのコードに付属の Documentation/filesystems/proc.txt 辺りにごにょごにょと書いてある.
ちなみに Linux では何かを特定の CPU に縛り付けたりする時に affinity mask という概念をよく使う. 例えば sched_setaffinity(2) システムコールはあるプロセス (スレッド) の実行を許す CPU の集合を設定するのだけれど,これも同じく affinity mask を使う.というか使うというより affinity mask を設定するというイメージになるのだけれど.
例えばあるプロセスの実行を許可された CPU は /proc/PID/status の Cpus_allowed 項または Cpus_allowed_list 項を見れば分かる. これら 2 つの項の意味は一緒で,前者は mask 値で,後者は CPU 番号リストで得られる.
あるプロセスの実行許可をシェルから変更したい場合は,taskset(1) を使うことができる.