9月末または10月のリリースが予定されているFreeBSD 9.
- How to get a capability?
今回はケーパビリティを取得するためのcap_
new(2)の使い方の基本を紹介します。まず、 前回作成したソースコードを少しだけ拡張して、 テキストファイルの内容を読み込んで、 標準出力に出力するようにします。簡易版cat(1)といったところです。ここでは 「read. c」 として用意しておきます。 #include <stdlib.
h> #include <stdio. h> #include <fcntl. h> #include <unistd. h> #include <err. h> #include <errno. h> #include <sysexits. h> int main(void) { int fd, len; char bf[BUFSIZ]; fd = open("COPYRIGHT", O_ RDWR); if (-1 == fd) err(EX_ NOPERM, "open error: %d", errno); len = read(fd, bf, BUFSIZ); if (-1 == len) err(EX_ NOPERM, "read error: %d", errno); printf("%s\n", bf); return 0; } コンパイルして実行するとその通りの動作をします。
% clang read.
c % ./ a. out | head -3 # $FreeBSD: head/ COPYRIGHT 216848 2010-12-31 18:07:16Z bz $ # @(#)COPYRIGHT 8. 2 (Berkeley) 3/ 21/ 94 % 次に、
ファイルディスクリプタを開いたあとでケーパビリティモードに入った場合、 そのファイルディスクリプタが使用できるのかどうかを確認します。ファイルは 「read-cap. c」 としておきます。 #include <stdlib.
h> #include <stdio. h> #include <fcntl. h> #include <unistd. h> #include <err. h> #include <errno. h> #include <sysexits. h> #include <sys/ capability. h> int main(void) { int fd, len; char bf[BUFSIZ]; fd = open("COPYRIGHT", O_ RDWR); if (-1 == fd) err(EX_ NOPERM, "open error: %d", errno); // ファイルディスクリプタを開いたあとで、 // ケーパビリティモードへ入ります。 cap_ enter(); len = read(fd, bf, BUFSIZ); if (-1 == len) err(EX_ NOPERM, "read error: %d", errno); printf("%s\n", bf); return 0; } 次のように動作していることが確認できます。ケーパビリティモードに入る前に用意したファイルディスクリプタはそのまま利用でき。
% clang read-cap.
c % ./ a. out | head -3 # $FreeBSD: head/ COPYRIGHT 216848 2010-12-31 18:07:16Z bz $ # @(#)COPYRIGHT 8. 2 (Berkeley) 3/ 21/ 94 % 次にcap_
new(2)でケーパビリティを作成して利用する基本的な方法を説明します。cap_ new(2)には既存のファイルディスクリプタと、 どの権限を与えるのかの指定を与えます。下記の例ではCAP_ READとCAP_ SEEKを許可しています。どのシステムコールを許可するのか指定するようなものです。 もとのファイルディスクリプタは、
ケーパビリティを取得したあとには使いませんので、 通常はdup(2)で複製したファイルディスクリプタを渡しておき、 ケーパビリティ取得後にはclose(2)しておくのが通例といえます。ファイルは 「read-cap2. c」 としておきます。 #include <stdlib.
h> #include <stdio. h> #include <fcntl. h> #include <unistd. h> #include <err. h> #include <errno. h> #include <sysexits. h> #include <sys/ capability. h> int main(void) { int fd, cap, len; char bf[BUFSIZ]; fd = open("COPYRIGHT", O_ RDWR); if (-1 == fd) err(EX_ NOPERM, "open error: %d", errno); // dup()で複製したファイルディスクリプタを渡して // ファイルディスクリプタからケーパビリティを作成 // します。ここでは読み書き可能なファイルディスクリプタ // から、読み込みのみ許可したケーパビリティを作成 // しているところがポイントです。次回、この権限指定が // 機能していることを確認します。 cap = cap_ new(dup(fd), CAP_ READ | CAP_ SEEK); if (-1 == cap) err(EX_ NOPERM, "cap_ new error: %d", errno); // 元のファイルディスクリプタはもう使わないので // 閉じておきます。 close(fd); // ケーパビリティモードへ入ります。 cap_ enter(); len = read(cap, bf, BUFSIZ); if (-1 == len) err(EX_ NOPERM, "read error: %d", errno); printf("%s\n", bf); return 0; } 実行すると次のように動作します。
% clang read-cap2.
c % ./ a. out | head -3 # $FreeBSD: head/ COPYRIGHT 216848 2010-12-31 18:07:16Z bz $ # @(#)COPYRIGHT 8. 2 (Berkeley) 3/ 21/ 94 % これがcap_
new(2)の基本的な使い方です。cap_ new(2)で権限を絞り込み、 cap_ enter(2)でケーパビリティモードに入ってより制限の厳しい状況で動作する、 これがCapsicumの提供する基本的なセキュリティ機能となります。