いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.183 / 読者数:1565名

こんばんは、うすだです。

昨日、いらなくなった本を、ブックオフで買い取っていただきました。

基本的には、いろいろと残しておきたいと思うひとです。
ですが、ここ数年一度も開いていなくて、特に思い入れのない本は、 一生読まないだろうと思いまして、思い切って処分することにしました。

結局、3分の2くらいは値段がつかず、数千円にしかなりませんでしたが、 家で埃をかぶるよりも、誰か他の人に読んでもらった方が、 本にとっても幸せだろうと思いますので、よかったのだと思っています。

そしてなにより、部屋がすっきりしました。(気持ちもすっきりしました)

しかし、まだ、捨てるに捨てられないモノが、結構残っています。
ばんばん捨てる勇気があれば片付くのですが、残しておきたいという本能が邪魔をして、 勇気(と片付けようという気)がまったく芽生えません。

とにかく勇気をひねり出そうと思い、 大昔に読んだ「「捨てる!」技術」という本を再度読み返してみようと思いました。
…ですが、どこにも見当たりません。過去に処分してしまったようです。

実は、必要な本を処分して、 思い入れのあるどうでもよい本を残しているような気がしてきました。

もしそうだとすると、わたしは限りなくダメなひとですが、そうだとしても、 その本を誰かがブックオフで安く購入できたのなら、 それはそれで役に立っていると言えるのではないでしょうか。

…無理やり納得したところで、今回もはりきってまいりたいと思います。

今回のお題 - ケーパビリティ で権限を少しだけ与える

前回、upnpd を使って、UPnP経由で iptables を扱えるようにしました。

Vol.182 - Linux を UPnP 対応にする
http://www.usupi.org/sysad/182.html

その際、root じゃないユーザで upnpd を動かすこともしてみました。

通常ですと、iptable の操作には root の権限が必要です。
ですが、ケーパビリティ(capability)を使って、 それらの操作を行うのに必要な権限だけを与え、 非root ユーザでも操作できるようにしました。

ただ、前回は、こうやったら権限を与えられますよ、 という事例をご紹介しただけに過ぎませんでした。

ですので、今回は、ケーパビリティをもう少しきちんとご紹介します。

ケーパビリティを使えば、root か root じゃないか、 という究極の選択的な権限の与え方ではなく、もっと細かい単位で権限を与えられます。

もしケーパビリティを使うチャンスがなくても、 最近の Linux にこんな機能があるんだぜ、と知ったかぶれますので、 読んで損することはない…と思います。思いたいです。

はじめにお断り

ケーパビリティは、ものすごく最新のホットな機能! というわけではないのですが、 カーネルのバージョンによって微妙に(あるいは大きく)異なります。

すべてご紹介できればよいのですが、 過ぎ去った古いバージョンのことはもう忘れてもよいだろうと(勝手に)思って、 2.6.25 以降のバージョンを対象にさせていただきたいと思います。

ご使用の Linux のカーネルのバージョンを確認するには、 -r オプションをつけて uname コマンドを実行します。

  $ uname -r
  2.6.32-22-generic

残念ながら 2.6.25 より古い場合は、どこまでが同じでどこが違うのか、 実際に確認していただければと思います。あるいは、 知ったかぶるためにさらっと読んでいただくだけでもよろしいのではないかと思います。

 

それから、ケーパビリティの設定や参照には、以下のパッケージが必要になります。 各自 apt や yum などで入手しておいてください。

  libcap2-bin  (Ubuntu など)
  libcap       (Fedora など)

ケーパビリティとは

Linux には、root が持っている絶対的な権限を小分けにし、 細かくした権限をプロセスに与えられるようにする機構があります。

その細かい権限のことを、ケーパビリティと呼びます。

たとえば、手元の Ubuntu10.04 ですと、 34種類のケーパビリティが定義されています。
具体的には、/usr/include/linux/capability.h 内の、「CAP_」で始まる定義が、 ケーパビリティです。

主なケーパビリティを以下に示します。(独断と偏見でチョイス)

CAP_CHOWN
ファイルのUIDとGIDを変更できる。
CAP_DAC_OVERRIDE
ファイルにアクセス(読み書き実行)できる。
CAP_DAC_READ_SEARCH
ファイルの読み出しと実行ができる。
CAP_KILL
シグナルを送信できる。
CAP_NET_BIND_SERVICE
1024番未満のポートを使用できる。
CAP_NET_ADMIN
ネットワーク関連の操作ができる。
(インターフェース、iptables やルーティングテーブルの設定など)
CAP_NET_RAW
RAWソケットおよびPACKETソケットを使用できる。
CAP_SYS_MODULE
カーネルモジュールのロード・アンロードが行える。
CAP_SYS_CHROOT
chroot できる。
CAP_SYS_ADMIN
quota や swap、mount などなど、様々な操作が行える。
CAP_SYS_TIME
システム時間の設定が行える。

root のプロセスは、基本的にはすべてのケーパビリティを持っていますが、 必要のないケーパビリティを外していくことで、 セキュリティを向上させることができます。

また、root でないプロセスは、基本的にはどのケーパビリティも持っていません。 ですが、実行するコマンドにケーパビリティが設定されている場合は、 そのケーパビリティを持つことができます。

プロセスのケーパビリティ

さて、ここからややこしくなります。
後で、なるべくややこしくない例でご説明したいと思いますので、 いまはわからなくても気にせず読み進めてくださいませ。
(わからないのは説明が下手だからだ、と思って間違いないです。)

 

プロセスは、以下の3種類のケーパビリティ・セットというものを持っていて、 それぞれに対してケーパビリティを設定できます。
(「セット」=「集合」です。内部的にはそれぞれビット列で表されて、 ケーパビリティを持っていれば、そのビットに 1 が設定されます。)

effective (実効)
プロセスの権限をチェックするときに使われるケーパビリティセット。
カーネルがこの値を見て、その操作を許可するかどうか判断する。
permitted (許可)
プロセスが持つことを許可されているケーパビリティセット。
inheritable (継承可能)
コマンドを実行するときに継承されるケーパビリティセット。

さらに、プロセスには、 ケーパビリティ・バウンディング・セットというものもあります。
これは、プロセスのケーパビリティを制限するためのもので、 実行しようとするコマンドにケーパビリティが設定されていても、 この値が 0 だとケーパビリティが与えられません。

 

プロセスの持つケーパビリティを確認するには、 /proc//status を参照します。
たとえば、ntpd のケーパビリティは、以下の手順で確認できます。

  $ ps -C ntpd -o pid,user,comm
    PID USER     COMMAND
   3784 ntp      ntpd
  $ cat /proc/3784/status
  ...中略...
  CapInh: 0000000000000000
  CapPrm: 0000000002000400
  CapEff: 0000000002000400
  CapBnd: ffffffffffffffff
  ...後略...

inheritable(CapInh) が 0、permitted(CapPrm) と effective(CapEff)が 0x2000400、 bounding set(CapBnd) がすべて 1 になっています。

ntpd が持つケーパビリティは、CAP_NET_BIND_SERVICE と CAP_SYS_TIME です。 前者は 10、後者は 25 ですので、(1<<10)|(1<<25) == 0x2000400 となります。

あるいは、getpcaps コマンドでも確認できます。
引数にプロセスIDを指定して実行すると、 そのプロセスのケーパビリティを教えてくれます。

  $ getpcaps 3784
  Capabilities for `3784': = cap_net_bind_service,cap_sys_time+ep

最後の ep の e は effective、p は permitted ですね。

ちなみに、一般ユーザのプロセスの場合は、 bounding set がすべて 1 となっている他は、すべて 0 なのが一般的です。

  $ ps -C bash
    PID TTY          TIME CMD
   2769 pts/1    00:00:05 bash
  ...中略...
  $ cat /proc/2769/status
  ...中略...
  CapInh: 0000000000000000
  CapPrm: 0000000000000000
  CapEff: 0000000000000000
  CapBnd: ffffffffffffffff
  ...後略...

ファイル(コマンド)のケーパビリティ

というわけで、プロセスには様々なケーパビリティがあります。
ですが、コマンド等を実行していくと、 プロセスの持てるケーパビリティを増やす機会がありませんので、 徐々に減っていってしまいそうです。

もちろんそれでは困りますので、ファイルにもケーパビリティを設定することができ、 ケーパビリティを新たに与えることができます。

ファイルにも、以下の3つのケーパビリティ・セットがあります。

permitted (許可)
実行したときに許可されるケーパビリティセット。
実行前のプロセスの permitted と関係なく、プロセスに設定される。
inheritable (継承可能)
実行したときに継承されるケーパビリティセット。
effective (実効)
これは、1ビットの情報で集合ではない。
これが設定されていないと、実行したときにプロセスの permitted が設定されない。

文章だとややこしい(かつ正確でない)ですが、式で表すと、わかりやすくなります。
コマンドを実行しますと、そのプロセスのケーパビリティは、以下の式で求まります。

P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)
P'(effective) = F(effective) ? P'(permitted) : 0
P'(inheritable) = P(inheritable)

P' : コマンド実行後のプロセスのケーパビリティ・セット
P  : コマンド実行前のプロセスのケーパビリティ・セット
F  : ファイルのケーパビリティ・セット
cap_bset : プロセスのバウンディング・セット

…まだややこしいので、一般ユーザの場合だけ考えてみましょう。
一般ユーザの権限で動作しているプロセスでは、P はすべて 0、 cap_bset はすべて 1 でしたので、上記の式は以下のように変換できます。

P'(permitted) = F(permitted)
P'(effective) = F(effective) ? F(permitted) : 0

ファイルの effective が 1 の場合、 ファイルの permitted がそのままプロセスのケーパビリティとなります。

ファイルのケーパビリティの参照や設定には、 getcap や setcap というコマンドを使用しますが、以降の例でご説明します。

いよいよ実践

ファイルのケーパビリティの確認には、getcap コマンドを使用します。
…が、たいていは設定されていませんので、何も出力されません。

  $ for file in /usr/bin/*; do getcap $file; done

設定には、setcap コマンドを使用します。
たとえば、コピーした ping コマンドに CAP_NET_RAW を設定するには、 以下のように実行します。(設定には root の権限が必要です。)

  # cp `which ping` /home/usu/ping
  # setcap cap_net_raw=ep /home/usu/ping
  # getcap /home/usu/ping
  /home/usu/ping = cap_net_raw+ep

今度は、getcap の出力がちゃんと得られました。
ちなみに、各所の ep は、前述と同様 effective と permitted です。

通常、ping コマンドには root の setuid が設定されているため、 一般ユーザでも実行することができます。

  $ ls -l `which ping`
  -rwsr-xr-x 1 root root 34756 2010-03-12 08:12 /bin/ping

さきほどコピーした ping コマンドには、setuid が設定されていませんが、 CAP_NET_RAW が設定されていますので、一般ユーザも実行できます。

  $ /home/usu/ping localhost
  PING localhost (127.0.0.1) 56(84) bytes of data.
  64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.078 ms
  64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.066 ms
  ...後略...

ところで、ケーパビリティをなくすには、-r オプションを使用します。

  # setcap -r /home/usu/ping

ケーパビリティがないと、当然ですが、一般人は実行できなくなります。

  $ /home/usu/ping localhost
  ping: icmp open socket: Operation not permitted

 

もうひとつ例を示します。
どこでも参照できてしまう ls コマンドをでっちあげます。
ホンモノをコピーして、CAP_DAC_READ_SEARCH を与えます。

  # cp `which ls` /home/usu/ls
  # setcap cap_dac_read_search=ep /home/usu/ls

すると、本来なら参照できない /root などを、参照できてしまいます。

  $ ls /root
  ls: cannot open directory /root: Permission denied
  $ /home/usu/ls /root
  dead.letter  dpkg.txt  log.txt

…おそろしいので、確認した後は、跡形もなく消しておきましょう。

  # rm /home/usu/ping /home/usu/ls

おわりに

以上、ケーパビリティの概要と例を、なるべくさらりとご紹介しました。

一般ユーザなら、 ファイルの permitted がプロセスの permitted になるということだけ覚えておけば、 まあいいんじゃないかと思っています。

本当は、ケーパビリティ・セットのそれぞれの役割がわかる例を、 ご紹介したかったのですが、設定するためのコマンドが見当たらなかったため、 今回は断念しました。

また機会があれば(間に合えば次回?)、細かくご紹介したいと思います。

宿題の答え

前回の宿題は、

  iptables の設定が変更されたらメールで通知するようにしましょう。

でした。

うっかり、「iptables の設定が変更されたら」などと、 一般的に書いてしまいました。(少し後悔)

ですので、ここは、/sbin/iptables コマンドを差し替えるという強引な手口で、 実現してみたいと思います。
(乱暴ですので、ホンモノサーバでは試さないようにしてください。)

さて、まずは、iptables コマンドの代わりである iptablesもどきを作成します。

  #!/bin/sh
  REAL_IPTABLES=/sbin/iptables.org
  MAILTO=root
  BEFORE=`$REAL_IPTABLES -nL 2>&1`
  $REAL_IPTABLES $*
  AFTER=`$REAL_IPTABLES -nL 2>&1`
  if [ "$BEFORE" != "$AFTER" ]; then
      echo "$AFTER" | \
          /usr/bin/Mail -s "[linux-igd] iptables changed" $MAILTO
  fi

ホンモノの iptables (上記スクリプトでは $REAL_IPTABLES)を実行する前後で iptables の状態を記録し($BEFORE と $AFTER)、 違いがある場合には設定内容($AFTER)を $MAILTO 宛にメールします。

まず、ホンモノの iptables を iptables.org という名前に改名し、 上記の iptables もどきを /sbin/iptables という名前で作成して、 実行可能にしておきます。

  # mv /sbin/iptables /sbin/iptables.org
  (テキストエディタなどで上記を作成し、/sbin/iptables で保存)
  # chmod +x /sbin/iptables

念のため実行して、単純なミスなどないことを確かめます。

  # /sbin/iptables -nL

問題なければ、 gupnp-universal-cp などで AddPortMapping などを実行してみてください。
もれなく、root 宛に以下のようなメールが届くと思います。

  From: igd@test.usupi.org
  To: root@usupi.org
  Subject: [linux-igd] iptables changed

  Chain INPUT (policy ACCEPT)
  target   prot opt source         destination         

  Chain FORWARD (policy ACCEPT)
  target   prot opt source         destination         
  ACCEPT   tcp  --  0.0.0.0/0      192.168.1.1     tcp dpt:22

  Chain OUTPUT (policy ACCEPT)
  target   prot opt source         destination         

ちなみに、AddPortMapping で NewLeaseDuration を 0 以外の値に設定をしますと、 その時間が経過して無効になったときにも、ちゃんとメールが送られてきます。 (当たり前ですが)

 

ところで、もし、 linux-igd が設定して変更された内容だけ通知されればよいという貴兄は、 上記の iptables もどきを別のパスで作っておいて、 /etc/upnpd.conf の iptable_location に、その iptables もどきを指定しましょう。

iptables もどきの REAL_IPTABLES を /sbin/iptables にして、 たとえば /usr/local/sbin/iptables-upnpd という名前にしたとします。
その場合、/etc/upnpd.conf の iptables_location を以下のように変更して、 linux-igd を再起動します。

  iptables_location = "/usr/local/sbin/iptables-upnpd"

linux-igd の再起動の手順は、以下の通りです。

  # service upnpd start         (RedHat系の場合)
  # service linux-igd restart   (Debian系の場合)

今回の宿題

今回の宿題は、

  様々なファイルシステムでケーパビリティが使えるか、試しましょう。

です。

ファイルのケーパビリティは、拡張属性(XATTR)に記録されるようです。
それは、どんなファイルシステムでも可能なのでしょうか。
といったあたりが気になりましたので、宿題とさせていただきます。
setcap を試すだけですので、気になる貴兄は、是非お試しください。

あとがき

最近、いろいろなことがあったりなかったりで(…ってどっちなんだ!?)、 テンションやモチベーションがいつになく低空飛行な毎日です。

何かきっかけがあれば、あとは勝手に走り出すのではないかと思っているのですが、 そのきっかけがなかなかつかめていません。

そのようなモンモンとした日々を送っていたところ、以下のページに遭遇しました。

週に一度、日曜日に自問すべき20の質問 - IDEA*IDEA
http://www.ideaxidea.com/archives/2008/09/20_9.html

毎週日曜日に、上記の20の質問に答えることで、 自分の立ち位置と今後の立ち位置を確認することができる…そうです。

考えないとダメだとか言われても、 まずその糸口がないとスタート地点にすら立てません。上記の質問は、 その糸口として適切なのではないか、という気がしております。

というわけで、毎週、20の質問に答えていきたいと思います。

 

(※)…と書いただけですと、まず 120% やらないで終わってしまいます。
ですので、毎週月曜の朝にチェックして、ファイルに結果を残そうと思います。 …いえ、ファイルに残します。絶対。
(ちなみに、月曜なのは、その方がゆっくり考えられそうだからです。)

 

…とまあ、ここまで書いておいてなんですが、結局のところは、社会人になって16年間、 自分の進むべき方向ややるべきことを考えずに生きてきたツケが、 今ごろになって返ってきたのでは? という気がしています。

しかし、もし60歳で定年を迎えるとしても、まだあと20年あります。
その間に、自分にできることは何か、自分がやりたいことは何なのか、ということを、 考えてみたいと思います。

…と書いただけですと、まず 120% やらないで… (goto ※)

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、8月1日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 劇のチラシ描きました。今度こそもっと完成度を…。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本