Trusted Solaris 開発ガイド

第 8 章 マルチレベルディレクトリ

Trusted Solaris 7 では、通常の UNIX ディレクトリとマルチレベルディレクトリ (MLD) が使用できます。MLD を使用すると、1 つのプログラムが複数の異なる機密ラベルで動作する場合でも、1 つのディレクトリを共通して使用でき、そのディレクトリ中にあるファイルの中でも現在のプログラムの機密ラベルと同等のものだけにアクセスすることができます。MLD にはシングルレベルディレクトリ (SLD) だけが含まれ、各 SLD はその SLD の機密ラベルでファイルを格納します。1 つの MLD 内では、同じ名前の複数のファイルを別々の SLD に格納できます。同じファイルのそれぞれのインスタンスは、格納先の SLD の機密ラベルに適したデータを含みます。これを、「ディレクトリとファイルの多重インスタンス化」と言います。

ディレクトリ構造

tmp ディレクトリとすべてのホームディレクトリは、システム管理者がユーザーマネージャでユーザー設定を行う際に、自動的に ADMIN_LOW の MLD になります。また、mkdir(1) にも MLD を作成するオプションがあります。図 8-1 は Zelda のホームディレクトリのディレクトリ構造を示しています。この図の MLD は ADMIN_LOW であり、機密ラベル Top Secret、Secret、Confidential の 3 つの SLD が入っています。

SLD は、必要に応じ、パス名ルックアップ時に、getsldname(2)fgetsldname(2) システムコールを使用して作成されます。SLD の機密ラベルは、システムにとって常に有効な機密ラベルです。

図 8-1 マルチレベルディレクトリ

Graphic

Secret で動作しているアプリケーションは、ADMIN_LOW のディレクトリパス /export/home/.MLD.zelda よりも優位で、Secret と Confidential の SLD よりも優位です。しかし、Top Secret の SLD よりは優位でありません。特権がなく任意アクセスがある場合、Secret で動作しているプロセスには次のアクセスがあります。

図 8-1 のディレクトリ構造において Confidential で動作しているプロセスは、次のファイルにアクセスできます。

.login

conf_proj

図 8-1 のディレクトリ構造において Secret で動作しているプロセスは、次のファイルにアクセスできます。

.login

secret_proj1

secret_proj2

図 8-1 のディレクトリ構造において Top Secret で動作しているプロセスは、次のファイルにアクセスできます。

.login

ts_proj

一時ディレクトリ

多くのアプリケーションは、/tmp ディレクトリにファイルを作成します。/tmp が機密ラベルを持つ通常の UNIX ディレクトリである場合、ほかの機密ラベルで動作している特権のないプロセスは /tmp にファイルを作成できません。Trusted Solaris 7 は、プロセスの機密ラベルに対応した SLD にアプリケーションがファイルを作成できるように、/tmp を MLD に設定します。

シンボリックリンク

MLD とシンボリックリンクは、組み合わせて使用できます。たとえば、リンク先パス名が MLD に存在するシンボリックリンクのリンク先ファイルは、機密ラベルごとに異なります。SLD 内のシンボリックリンクは、通常のディレクトリ内のパス名を指すことができます。その場合は、異なる機密レベルで参照されるときでも MLD 内のパス名からその同じファイルを参照できるようになります。

装飾名

プロセスがパス名の中で MLD を参照する場合、システムは、そのプロセスの機密ラベルに対応する SLD を含むように参照を透過的に拡張します。この操作を、「パス名変換」と言います。たとえば、Confidential で動作しているプロセスが /export/home/zelda を参照する場合、このプロセスは /export/home/zelda の Confidential の SLD にアクセスします。パス名変換は透過的であるため、プロセスはこの SLD を明示的に参照しません。

すべての MLD には、装飾があります。装飾は、システム管理者によって変更されないかぎり、.MLD. です。装飾を使用すると、プロセスは、プロセスと同じ機密ラベルの SLD を透過的に参照するのではなく、MLD を直接参照できます。プロセスは、次の処理を実行する場合、ls(1) コマンドを使用して装飾名を参照します。

%ls /.MLD.tmp
%ls /.MLD.tmp/.SLD.3

特権オペレーション

MLD または SLD の情報を取得したり、完全な装飾パス名を使用して SLD 内のオブジェクトにアクセスするには、必須アクセスと任意アクセスが必要です。

第 1 章「API とセキュリティポリシーの紹介」に示されている必須アクセスと任意アクセスの規則から言えば、SLD は、目的のファイルシステムオブジェクトが含まれるパス名の中の 1 要素と言えます。呼び出し元プロセスは、SLD に対する必須検索アクセスと任意検索アクセス、および目的のオブジェクトに対する適切なアクセスを必要とします。アクセスが拒否される場合は、特権が必要になる場合があります。

MLD 内の、指定された機密ラベルの SLD 名を取得する場合、呼び出し元プロセスは次の特権を必要とします。

データ型、ヘッダーファイル、ライブラリ

この章で説明しているプログラミングインタフェースを使用するには、次のヘッダーファイルが必要です。

#include <tsol/mld.h>

この章の例は、次のライブラリを使用してコンパイルしています。

-ltsol

機密ラベル

bslabel_t 型の定義は、バイナリ CMW ラベルの機密ラベル部を示します。getsldname(2) システムコールは、bslabel_t 型の変数を受け取ります。

状態

stat 構造体は、指定された MLD、SLD、シンボリックリンクのいずれかの情報を含みます。この構造体は、mldstat(2)mldlstat(2) システムコールによって返されます。

型 

フィールド 

内容 

デフォルト 

mode_t 

st_mode

ファイル形式とアクセス権 

nlink_t 

st_nlink

ハードリンクの数 

uid_t 

st_uid

所有者のユーザー ID 

gid_t 

st_gid

所有者のグループ ID 

time_t 

st_atime

示す最後のアクセス時間 (秒単位) 

現在の時間 

time_t 

st_mtime

示す最後の変更時間 (秒単位) 

現在の時間 

time_t 

st_ctime

示す最後の i ノード変更時間 (秒単位) 

現在の時間 

プログラミングインタフェース宣言

次に、MLD と SLD の情報を取得するプログラミングインタフェースを示します。

システムコール

システムコールを使用して、SLD 名、MLD 装飾、SLD または MLD のファイル属性情報などを取得できます。

SLD 名の取得

getsldname(2) システムコールは、 path_name (パス名) に対する SLD 名を、指定された slabel (機密ラベル) で取得します。詳細は、getsldname(2) のマニュアルページを参照してください。fgetsldname(2) システムコールは、ファイル記述子を使用します。

int		getsldname(				const char *path_name,
 						const bslabel_t *slabel,
 						char *name_buf,
 						const int len);

 int		fgetsldname(				const int fd,
 						const bslabel_t *slabel_p,
 						char *name_buf,
 						const int len);

MLD 装飾の取得

getmldadorn(2) システムコールは、path_name に対する完全な装飾名を取得します。fgetmldadorn(2) システムコールは、ファイル記述子を使用します。詳細は、getmldadorn(2) のマニュアルページを参照してください。

int		getmldadorn(					const char *path_name,
 							char *adorn_buf[MLD_ADORN_MAX]);
 int		fgetmldadorn(					const int fd,
 							char adorn_buf[MLD_ADORN_MAX]);

SLD または MLD の属性情報の取得

mldstat(2) システムコールは、path_name によって指定された MLD のファイル属性情報を返します。mldlstat(2) システムコールは、MLD シンボリックリンクの情報を返します。詳細は、mldstat(2) のマニュアルページを参照してください。

int		mldstat(					const char *path_name,
 							struct stat *stat_buf);

 int		mldlstat(					const char *path_name,
 							struct stat *stat_buf);

MLD の属性フラグの取得

次のシステムコールの詳細は、第 2 章「プログラミングインタフェースの概要」「ファイルシステムのセキュリティ属性フラグの取得と設定」を参照してください。また、getfattrflag(2) のマニュアルページも参照してください。

int			mldgetfattrflag(								const char *path, secflgs_t *flags)
 int			mldsetfattrflag(								const char * path,
 											secflgs_t which,
 											secflgs_t flags))

ライブラリルーチン

ライブラリルーチンを使用して、現在の作業ディレクトリのパス名取得や、装飾を使用したパス名表示が行えます。

現在の作業ディレクトリの取得

次のルーチンは、現在の作業ディレクトリの完全な装飾名を取得します。詳細は、mldgetcwd(3) のマニュアルページを参照してください。

char*		mldgetcwd(				char *buf, size_t size);

装飾名の取得

次のルーチンは、path_name で指定された MLD に対する装飾名を取得します。詳細は、adornfc(3) のマニュアルページを参照してください。

int		adornfc(				const char *path_name,
 						char *adorned_name);

実際のパス名の検索

次のルーチンは、path_name で指定されたパス名を受け取り、すべてのシンボリックリンクを展開し、現在のディレクトリと親ディレクトリに対する相対パス名の参照を解決し、余分なスラッシュ文字を削除し、正しい MLD および SLD 装飾を加え、最終結果を resolved_path (解決済みパス) に格納します。この結果は、プロセスが動作している SLD、または指定された SLD のパス名を示します。詳細は、mldrealpath(3) のマニュアルページを参照してください。

char*		mldrealpath(				const char *path_name,
 						char *resolved_path);

 char	*	mldrealpathl(				const char *path_name,
 						char *resolved_path,
 						const bslabel_t *senslabel);

MLD 名と SLD 名の照会

次のコードは、getmldadorn(2) システムコールを使用して MLD 装飾を照会し、getsldname(2) システムコールを使用して Top Secret SLD の SLD 名を照会します。この例では、Top Secret の SLD はまだ存在しないため、getsldname(2) に対する呼び出しがこれを作成します。

プロセスは、認可上限 Top Secret を使用して Confidential で動作しています。このプロセスは、Top Secret ラベルの変換に sys_trans_label 特権、Top Secret SLD の作成に file_upgrade_sl 特権、そして Top Secret SLD 情報のアクセスに file_mac_search 特権と file_mac_read 特権を必要とします。

#include <tsol/label.h>

 main()
 {	
 	int			retval, error, length;
 	bslabel_t			label;
 	char	 		*buffer[1025], *buf[1025], *string = "TOP SECRET";
 	char			*file = "/export/home/zelda";

 	retval = getmldadorn(file, buffer);
 	printf("MLD adornment = %s¥n", buffer);

/* 有効セット内で sys_trans_label をオン (有効) にする */
 	retval = stobsl(string, &label, NEW_LABEL, &error);
/* sys_trans_label をオフ (無効) にする */

 	length = sizeof(buf);

/* file_upgrade_sl、file_mac_search、file_mac_read */
/*をオン (有効) にする */
 	retval = getsldname(file, &label, buf, length);
/* file_upgrade_sl、file_mac_search、file_mac_read */
/*をオフ (無効) にする*/

 	printf("SLD name = %s¥n", buf);
 }

printf(1) 文によって、次のように出力されます

MLD adornment = .MLD.

SLD name = .SLD.3

次の例は、mldgetcwd(3) ルーチンを使用して現在の作業ディレクトリ (MLD と現在の SLD) を照会し、adornfc(1) ルーチンを使用してこの MLD の装飾名を取得します。続いて、mldrealpath(1) ルーチンを使用して resolvefile (解決済みファイル) に格納されたパス名内の余分なスラッシュを削除し、実際のパスを見つけます。このプロセスは、Confidential で動作しています。

#include <tsol/label.h>
 #include <sys/types.h>

 main()
 {	
 	int			 retval;
 	char	 		*buffer[1025];
 	char			*file = "/export/home/zelda";
 	char			*string2, *name[1025], *string3, *resolved[1025];
 	size_t			size;

/* 文字列のエラーを解決する */
 	char			*resolvefile = "./";

 	size = sizeof(buffer);
 	string2 = (char *)mldgetcwd(buffer, size);
 	printf("Current working directory = %s¥n", buffer);

 	retval = adornfc(file, name);
 	printf("Adorned name = %s¥n", name);

 	string3 = (char *)mldrealpath(resolvefile, resolved);
 	printf("Real path = %s¥n", resolved);
 }

printf 文によって、次のように出力されます。


注 -

adornfc(1) ルーチンに対するファイルパラメータに SLD 名が含められる場合、装飾名は /export/home/zelda/.MLD..SLD.1 のように SLD が追加された形式で返されます。


Current working directory = /export/home/.MLD.zelda/.SLD.2

Adorned name = /export/home/.MLD.zelda

Real path = /export/home/.MLD.zelda/.SLD.2

次の例は、/export/home/zelda MLD の属性情報を取得します。stat(2) システムコールマクロは、printf(1) 文で MLD がディレクトリであるか通常のファイルであるかを確認します。そして、ctime(3C) ルーチンによって、返された秒単位の時間がユーザーが読める形式に変換されます (詳細は、ctime(3C) のマニュアルページを参照)。

#include <tsol/label.h>
 #include <sys/stat.h>

 main()
 {	
 	int 			retval;
 	struct			stat statbuf;
 	char			*file = "/export/home/zelda";

 	retval = mldstat(file, &statbuf);

 	printf("Is file system object a directory? = %d¥n", S_ISDIR(statbuf.st_mode));

 	printf("Is file system object a regular file? = %d¥n", S_ISREG(statbuf.st_mode));

 	printf("Number of links = %d¥n", statbuf.st_nlink);
 	printf("Owner's user ID = %d¥n", statbuf.st_uid);
 	printf("Owner's group Id = %d¥n", statbuf.st_gid);
 	printf("Last access time = %s¥n", ctime(&statbuf.st_atime));
 	printf("Last modify time = %s¥n", ctime(&statbuf.st_mtime));
 	printf("Last status change = %s¥n", ctime(&statbuf.st_ctime));
 }

printf 文によって、次のように出力されます。

Is file system object a directory? = 1

Is file system object a regular file? = 0

Number of links = 6

Owner's user ID = 29378

Owner's group Id = 10

Last access time = Wed May 28 10:58:25 1997

Last modify time = Wed May 28 09:39:18 1997

Last status change = Wed May 28 09:39:18 1997

装飾パス名の使用

open(2)creat(2) のような、パス名を受け入れる UNIX システムコールは、通常のパス名に代わって完全な装飾パス名が渡されないかぎり、プロセスと同じ機密ラベルの SLD をアクセスします。完全な装飾パス名には、次のコード例に示すように、MLD の装飾と SLD のディレクトリ名が入ります。プロセスは、mkdir(1) システムコールを使用しても、MLD または SLD 内にファイルやディレクトリを作成できません。

「セキュリティポリシー」で説明している必須アクセス権制御と任意アクセス権制御が適用されます。

ファイルを開く

次の例では、プロセスは認可上限 Top Secret を使用して Confidential で動作しています。この Confidential プロセスは、Top Secret の SLD にアクセスするためには、有効セットに file_mac_search 特権を必要とします。ファイルが書き込みのために開かれており、セキュリティポリシーによって上位書き込みが許容されるため、この処理がすべての任意アクセス検査の条件を満たすのであれば、ほかに必要な特権はありません。

#include <tsol/label.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

 main()
 {	
 	int		filedes;

/* プロセスが実行されている SLD でファイルを開く */
 	filedes = open("/export/home/zelda/afile", O_WRONLY);
 	printf("File descriptor for regular path = %d¥n", filedes);

/* Top Secret の SLD でファイルを開く */
/* 有効セット内で file_mac_search をオン (有効) にする */
 	filedes = open("/export/home/.MLD.zelda/.SLD.3/afile", O_WRONLY);
/* file_mac_search をオフ (無効) にする */

 	printf("File descriptor for adorned path = %d¥n", filedes);
 }

printf 文によって、次のように出力されます。

File descriptor for regular path = 3

File descriptor for adorned path = 4

ファイルの作成

次の例では、プロセスは認可上限 Top Secret を使用して Confidential で動作しています。 Confidential プロセスは、Top Secret の SLD にアクセスするためには、有効セットに file_mac_search 特権を必要とします。Top Secret SLD 内にまだ afile が存在しない場合、プロセスは file_mac_write 特権を必要とします。これは、このプロセスの機密ラベルが SLD の機密ラベルと同等でないためです。afile がすでに存在する場合は、file_mac_write 特権は必要ありません。

#include <tsol/label.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

 main()
 {	
 	int		filedes;

/* プロセスが実行されている SLD でファイルを開く */
 	filedes = creat("/export/home/zelda/afile", 660);

 	printf("File descriptor for regular path = %d¥n", filedes);

/* Top Secret の SLD でファイルを作成する */
/* 有効セット内で file_mac_search をオン (有効) にする */
 	filedes = creat("/export/home/.MLD.zelda/.SLD.3/afile", 660);
/* file_mac_search をオフ (無効) にする */

 	printf("File descriptor for adorned path = %d¥n", filedes);
 }

printf 文によって、次のように出力されます。

File descriptor for regular path = 3

File descriptor for adorned path = 4