Trusted Solaris 開発ガイド

第 12 章 System V のプロセス間通信

Trusted Solaris 7 では、System V のプロセス間通信 (IPC) 機構をサポートし、System V IPC オブジェクト間、特権を持つプロセス間、および特権を持たないプロセス間のラベル付き通信に対するセキュリティ機能が用意されています。

特権の必要な処理

System V IPC オブジェクトでは、任意アクセス制御と必須アクセス制御、任意の所有権制御、情報ラベルの浮上が適用されます。

System V IPC オブジェクトはキーから作成され、IPC オブジェクトの作成時に返されるオブジェクト記述子によってアクセスされます。オブジェクト記述子は、ファイル記述子と同様に、今後オブジェクトに対して処理を行う際に使用されます。System V IPC オブジェクトの機密ラベルは、その作成プロセスが異なるラベルで System V IPC オブジェクトを作成する特権を持たないかぎり、作成プロセスの機密ラベルと同じです。プロセスは、別のラベルで System V IPC オブジェクトにアクセスする特権を持たないかぎり、同じ機密ラベルで System V IPC オブジェクトにアクセスします。キーは作成される機密ラベルによって識別されるため、同じキーを使用するオブジェクトが多数存在できますが、ある 1 つの機密ラベルにおけるキーのインスタンス (オブジェクト ID) は 1 つだけです。

必須アクセス制御と所有権制御

System V IPC オブジェクトに対する任意アクセスは、ファイルアクセスとほぼ同様に、所有者、グループ、その他ユーザーのオブジェクトに対応した読み取りモードと書き込みモードに基づいて付与または拒否されます。System V IPC オブジェクトには、属性変更要求を制御する作成者のユーザーとグループのセットもあります。System V IPC オブジェクトを作成するプロセスは所有者であり、任意アクセス権ビットをあらゆる値に設定できます。任意アクセス制限と所有者制限を無効にするには、使用しているインタフェースまたは要求されているオペレーションに応じ、プロセスの有効セットに ipc_dac_readipc_dac_writeipc_owner のいずれかの特権が必要です。

必須アクセス制御

特権を持たないプロセスは、プロセスの正しい機密ラベルにおいてのみ System V IPC オブジェクトを参照し、IPC 記述子を返すことができます。これにより、必須アクセス制御が同位読み取りと同位書き込みとなり、System V IPC を使用した未変更の基本 Solaris アプリケーションが複数の機密ラベルで動作する場合に、ファイル名やアクセスの重複が排除されます。必須アクセス制限を無効にするには、使用しているインタフェースに応じ、プロセスの有効セットに ipc_mac_read または ipc_mac_write 特権が必要です。


注 -

機密ラベルは、いったん作成されると変更できません。


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

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

#include <sys/ipcl.h>

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

-ltsol

ラベル

ラベルのデータ構造、bclabel_tbslabel_tbilabel_t については、第 5 章「ラベル」を参照してください。

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

これらのプログラミングインタフェースを使用すると、System V IPC オブジェクトのラベルを管理できます。従来のラベルなしインタフェースは、現在も有効であり使用できます。Trusted Solaris 7 のこれらの拡張機能では、ラベル情報にアクセスすることができます。

メッセージ待ち行列

getmsgqcmwlabel(2) ルーチンは、メッセージ待ち行列の CMW ラベルを取得します (情報ラベル部は未定義)。詳細は、getmsgqcmwlabel(2) のマニュアルページを参照してください。

msggetl(2) ルーチンは、指定された機密ラベルでメッセージ記述子を作成します。

詳細は、msgop(2)msgget(2)msgctl(2) のマニュアルページを参照してください。

int		getmsgqcmwlabel(					int msqid,
 							bclabel_t *cmwlabel);

 int 		msggetl(					key_t key,
 							int msgflg,
 							bslabel_t *senslabel);

 int		msgsndl(					int msqid,
 							const void *msgp,
 							size_t msgsz,
 							int msgflg,
 							bilabel_t *inflabel);

 int		msgrcvl(					int msqid,
 							void *msgp,
 							size_t msgsz,
 							long msgtyp,
 							int msgflg,
 							bilabel_t *inflabel);

セマフォセット

getsemcmwlabel(2) ルーチンは、セマフォセットの CMW ラベルを取得します。詳細は、getsemcmwlabel(2) のマニュアルページを参照してください。

semgetl(2) ルーチンは、指定された機密ラベルでセマフォセットを作成します。詳細は、semgetl(2) のマニュアルページを参照してください。

semopl(2) ルーチンは、指定されたセマフォセットに対してセマフォ処理を実行し、そのオペレーションの情報ラベルをユーザーが指定するようにします。詳細は、semopl(2) のマニュアルページを参照してください。

int		getsemcmwlabel(					int semid,
 							bclabel_t *cmwlabel);

 int		semgetl(					key_t key,
 							int nsems,
 							int semflg,
 							bslabel_t *senslabel);

 int		semopl(					int semid,
 							struct sembuf *sops,
 							size_t nsops,
 							bilable_t *inflabel);

共有メモリー領域

getshmcmwlabel(2) ルーチンは、共有メモリー領域の CMW ラベルを取得します。詳細は、getshmcmwlabel(2) のマニュアルページを参照してください。

shmgetl(2) ルーチンは、指定された機密ラベルで共有メモリー領域を作成します。詳細は、shmgetl(2) のマニュアルページを参照してください。

int		getshmcmwlabel(					int shmid,
 							bclabel_t *cmwlabel);

 int 		shmgetl(					key_t key,
 							size_t size,
 							int shmflg,
 							bslabel_t *senslabel);

メッセージ待ち行列ラベルの使用

この例は、Top Secret でメッセージ待ち行列を作成し、そのメッセージを Top Secret 待ち行列に送り、そのメッセージに Top Secret の情報ラベルを与え、fork によりプロセスを作成して、待ち行列からメッセージを取り出します。

親プロセスと子プロセスは、初め、情報ラベル Unclassified を使用して Confidential で動作しています。この例の一部のオペレーションには特権が必要です。コード内のコメントは、第 3 章「特権」で説明している特権ブラケットが必要な位置を示します。

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

 struct sndmsgbuf{
 	long mtype;
 	char mtext[80];
 } sendmsg;

 main()
 {
 	struct				msgbuf 				*rcvmsg;
 	int									id, retval, error, pid;
 	bclabel_t									cmwlabel;
 	bslabel_t									senslabel;
 	bilabel_t									inflabel;
 	char									*string,*string2, *string3 = "TOP SECRET";

/* メッセージ待ち行列用のメッセージを設定する */
 	sendmsg.mtype = 1;
 	strcpy(sendmsg.mtext, "Hello World!¥n");

/* Top Secret の機密ラベルと情報ラベルを作成する */
/* 有効セット内で sys_trans_label をオン(有効) にする */
 	retval = stobsl("TOP SECRET", &senslabel, NEW_LABEL, &error);
 	retval = stobil(string3, &inflabel, NEW_LABEL, &error);
/* sys_trans_label をオフ (無効) にする */

/* Top Secret のメッセージ待ち行列を作成する */
/* 有効セット内で ipc_mac_write をオン(有効) にする */
 	id = msggetl(IPC_PRIVATE, IPC_CREAT|0666, &senslabel);
/* ipc_mac_write をオフ (無効) にする */

/* Top Secret の情報ラベルを持つメッセージを送る*/
/* 有効セット内で ipc_upgrade_il  をオン (有効) にする */
 	msgsndl(id, (void*)&sendmsg, 80, 0, &inflabel);
/* ipc_upgrade_il  をオフ (無効) にする */

読み取りプロセスの情報ラベルは、メッセージの情報ラベルに浮上します。この例では、fork により作成された confidential で特権のないプロセスは、その情報ラベルをTop Secretに浮上させることはできません。これは、Confidential が Top Secret より優位でないためです。fork により作成されたプロセスは、次の 2 つの方法のいずれかにより特権を使用してデータの消失を防ぐ必要があります。

	pid = fork();
 	if(pid > 0)
 			exit(0);

/* fork で作成されたプロセスの機密ラベルを Top Secrete に設定する */
 	retval = stobsl(string3, &senslabel, NEW_LABEL, &error);
 	getcmwplabel(&cmwlabel);
 	setcsl(&cmwlabel, &senslabel);
/* 有効セット内で proc_setsl をオン (有効) にする */
 	setcmwplabel(&cmwlabel, SETCL_SL);
/* proc_setsl をオフ (無効) にする */

 	rcvmsg = (struct msgbuf *)malloc(sizeof(long) + 80);
 	retval = msgrcvl(id, rcvmsg, 80, 0, 0, &inflabel);

/* プロセスの CMW ラベルを得て、情報ラベルを取り出す */
 	getcmwplabel(&cmwlabel);
 	getcil(&inflabel, &cmwlabel);
 	biltos(&inflabel, &string2, 0, LONG_WORDS);

/* メッセージとプロセスの情報ラベルを出力する */
 	printf("Received message = %s¥n", rcvmsg->mtext);
 	printf("Process information label = %s¥n", string2);
 }

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

Received message = Hello World!

Process information label = TOP SECRET

セマフォセットラベルの使用

この例は、Confidential でセマフォセットの識別子を作成し、同じセマフォセットで CMW ラベルを取得します。続いてプログラムは、ロックを要求する時点で、セマフォセットの情報ラベルを変更します。このプログラムは、Top Secret で動作しています。

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

 main()
 {
 	int							id, retval, error;
 	bclabel_t							cmwlabel;
 	bslabel_t							senslabel;
 	bilabel_t							inflabel;
 	char							*string = (char *)0, *string2 = (char *)0;
 	struct sembuf							sops = {2, 1, IPC_NOWAIT};

 	retval = stobsl("CONFIDENTIAL", &senslabel, NEW_LABEL, &error);
 	retval = stobil("CONFIDENTIAL", &inflabel, NEW_LABEL, &error);

/* Confidential のセマフォセットを作成する */
/* 有効セット内で ipc_mac_write をオン (有効) にする */
 	id = semgetl(IPC_PRIVATE, 5, IPC_CREAT, &senslabel);
/* ipc_mac_write をオフ (無効) にする */

/* セマフォセットの CMW ラベルを得る */
/* 有効セット内で ipc_mac_read をオン (有効) にする */
 	retval = getsemcmwlabel(id, &cmwlabel);
/* ipc_mac_read をオフ (無効) にする */

/* CMW ラベルを出力する */
 	bcltos(&cmwlabel, &string, 0, LONG_WORDS);
 	printf("CMW label = %s¥n", string);

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

CMW label = UNCLASSIFIED[C]

プログラムは、セマフォロックを要求するとき、セマフォセットの情報ラベルを Unclassified から Confidential に変更します。

/* ロックを要求し、情報ラベルを Confidential に変更する */
/* 有効セット内で ipc_upgrade_il をオン (有効) にする */
 	retval = semopl(id, &sops, 1, &inflabel);
/* ipc_upgrade_il をオフ (無効) にする */

/* セマフォセットの CMW ラベルを得る */
/* 有効セット内で ipc_mac_read をオン (有効) にする */
 	retval = getsemcmwlabel(id, &cmwlabel);
/* ipc_mac_read をオフ (無効) にする */

 	getcil(&inflabel, &cmwlabel);

/* 情報ラベルを出力する */
 	biltos(&inflabel, &string2, 0, LONG_WORDS);
 	printf("Information label = %s¥n", string2);
 }

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

Information label = CONFIDENTIAL


注 -

情報ラベルに対する変更を確認する場合、/etc/system ファイルで System V IPC セマフォの情報ラベルの浮上がオンに設定されていること (tsol_float_sem_il = 1) を確認してください。


共有メモリーラベルの使用

この例は、Confidential で共有メモリー領域の識別子を作成し、この同じ共有メモリー領域の CMW ラベルを取得します。このプログラムは、Top Secret で動作しています。

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

 main()
 {
 	int					id, retval, error, pid;
 	bclabel_t					cmwlabel;
 	bslabel_t					senslabel;
 	char					*string = (char *)0;

 	retval = stobsl("CONFIDENTIAL", &senslabel, NEW_LABEL, &error);

/* Confidential の共有メモリー領域を作成する */
/* 有効セット内で ipc_mac_write をオン (有効) にする */
 	id = shmgetl(IPC_PRIVATE, 256, IPC_CREAT|0666, &senslabel);
/* ipc_mac_write をオフ (無効) にする */

/* 共有メモリー領域の CMW ラベルを得る */
/* 有効セット内で ipc_mac_read をオン (有効) にする */
 	retval = getshmcmwlabel(id, &cmwlabel);
/* ipc_mac_read をオフ (無効) にする */

/* CMW ラベルを出力する */
 	bcltos(&cmwlabel, &string, 0, LONG_WORDS);
 	printf("CMW label = %s¥n", string);
 }

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

CMW label = UNCLASSIFIED[C]