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_read、ipc_dac_write、ipc_owner のいずれかの特権が必要です。
特権を持たないプロセスは、プロセスの正しい機密ラベルにおいてのみ System V IPC オブジェクトを参照し、IPC 記述子を返すことができます。これにより、必須アクセス制御が同位読み取りと同位書き込みとなり、System V IPC を使用した未変更の基本 Solaris アプリケーションが複数の機密ラベルで動作する場合に、ファイル名やアクセスの重複が排除されます。必須アクセス制限を無効にするには、使用しているインタフェースに応じ、プロセスの有効セットに ipc_mac_read または ipc_mac_write 特権が必要です。
機密ラベルは、いったん作成されると変更できません。
この章で説明しているプログラミングインタフェースを使用するには、次のヘッダーファイルが必要です。
#include <sys/ipcl.h>
この章の例は、次のライブラリを使用してコンパイルしています。
-ltsol
ラベルのデータ構造、bclabel_t、bslabel_t、bilabel_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 つの方法のいずれかにより特権を使用してデータの消失を防ぐ必要があります。
ipc_mac_read と proc_nofloat 特権を使用し、上位読み取り処理を有効にし、情報ラベルの浮上を停止する
proc_setsl 特権を使用し、必須アクセスが許容されるように、読み取りプロセスの機密ラベルを Top Secret に変更する (コードを参照)
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]