FreeBSD Daily Topics

2011年9月9日Capsicumを知る - ケーパビリティからケーパビリティを作成

9月末または10月のリリースが予定されているFreeBSD 9.0-RELEASEには新しいセキュリティ機能「Capsicum」が登場します。FDTではしばらく概念的な説明や、実際の実装例などを紹介して「Capsicum」の機能を紹介していきます。

New capability from capability

既存のケーパビリティをベースに新しいケーパビリティを作成することもできます。ここで注目すべきは、既存のケーパビリティが持っていない権限を新しく付与することはできない、ということです。権限を狭くしていくことはできますが、広げることはできません。

たとえば次のように読み書きを与えたケーパビリティから、読み込みのみを許可したケーばビリティを作成してみます。ファイルは「read-cap4.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, cap2, len;
	char bf[BUFSIZ];


	fd = open("COPYRIGHT", O_RDWR);
	if (-1 == fd)
		err(EX_NOPERM, "open error: %d", errno);

	// 読み書きを許可してケーパビリティを作成
	cap = cap_new(dup(fd), CAP_READ | CAP_WRITE | CAP_SEEK);
	if (-1 == cap)
		err(EX_NOPERM, "cap_new(1) error: %d", errno);

	close(fd);

	cap_enter();

	// ケーパビリティモードに入ってから、今度は
	// 読み込みのみを許可したケーパビリティを
	// さらに作成する。
	cap2 = cap_new(dup(cap), CAP_READ | CAP_SEEK);
	if (-1 == cap2)
		err(EX_NOPERM, "cap_new(2) error: %d", errno);

	close(cap);

 	len = read(cap2, bf, BUFSIZ);
	if (-1 == len)
		err(EX_NOPERM, "read error: %d", errno);

	printf("%s\n", bf);

	return 0;
}

読み込み処理が実行されることがわかります。この使い方は問題ありません。

% clang read-cap4.c 
% ./a.out | head -3
# $FreeBSD: head/COPYRIGHT 216848 2010-12-31 18:07:16Z bz $
#       @(#)COPYRIGHT   8.2 (Berkeley) 3/21/94

%

次に、読み込みのみを許可したケーパビリティから、書き込みも許可したケーパビリティを作成してみます。⁠read-cap5.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, cap2, len;
	char bf[BUFSIZ];


	fd = open("COPYRIGHT", O_RDWR);
	if (-1 == fd)
		err(EX_NOPERM, "open error: %d", errno);

	// 読み込みのみを許可したケーパビリティを作成
	cap = cap_new(dup(fd), CAP_READ | CAP_SEEK);
	if (-1 == cap)
		err(EX_NOPERM, "cap_new(1) error: %d", errno);

	close(fd);

	cap_enter();

	// ケーパビリティに入ってから、今度は逆に
	// 書き込み許可を持ったケーパビリティをつくってみようと
	// してみる。
	cap2 = cap_new(dup(cap), CAP_READ | CAP_WRITE | CAP_SEEK);
	if (-1 == cap2)
		err(EX_NOPERM, "cap_new(2) error: %d", errno);

	close(cap);

 	len = read(cap2, bf, BUFSIZ);
	if (-1 == len)
		err(EX_NOPERM, "read error: %d", errno);

	printf("%s\n", bf);

	return 0;
}

次のように実行は実現しません。

% clang read-cap5.c
% ./a.out | head -3
a.out: cap_new(2) error: 93: Capabilities insufficient
%

ケーパビリティは権限を減らす方向へのみ新しく作成することができます。必要な処理が終わったら、不要な権限は削除していくということができます。

おすすめ記事

記事・ニュース一覧