Trusted Procedure

カラム毎のアクセス権を設定し、一部のカラムを読み出し不能とすることができる。が、全く使えないでは意味がない。
そういう時には、Trusted Procedure経由でアクセスすることができる。

例えば、以下のようなテーブルがあるとする。

person表
uid serial primary key ... (user_u:object_r:sepgsql_table_t:s0)
uname text ... (user_u:object_r:sepgsql_table_t:s0)
passwd varchar(32) ... (user_u:object_r:sepgsql_table_t:s0:c0.c255)<||
この場合、例えばCGIプロセスなど、権限の低いクライアントからは passwd カラムを参照できないが、このテーブルを認証に使いたい場合は passwd カラムを利用する必要がある。
こういった場合に trusted procedure を利用して、生のパスワードを参照することなく passwd カラムの参照が可能になる。

まず、関数を定義する。
>||
# create function check_person_passwd(integer, text)
returns boolean language 'sql'
as 'select count(*)<>0 from person where uid = $1 and passwd = $2';

そして、この関数の実行時にドメイン遷移を発生させるように設定する。今のところ、sepgsql_trusted_proc_tというタイプを持っていると、実行時に s0:c0.c1023 のMCSカテゴリを持って実行する。
check_person_passwd関数にこのタイプを付与する。

すると、以下のようになる。

# select uid,uname,passwd from person where passwd='aaa';
ERROR:  SELinux: denied { select } 
  scontext=user_u:system_r:unconfined_t:s0-s0:c0.c255 
  tcontext=user_u:object_r:sepgsql_table_t:s0:c0.c1023
  tclass=column name=passwd
#
# select uid,uname,check_person_passwd(uid,'aaa') from person;
 uid | uname  | check_person_passwd
-----+--------+---------------------
   1 | KaiGai | t
   2 | ymj    | f
   3 | tak    | f
(3 rows)

とにかく、passwdカラムの内容を読み出すことはできないが、入力されたパスワード文字列にマッチすることは確認できる。

現状、これが有効に機能するのは SQL で記述された関数のみ。
C言語実装の関数などでは、原理的に強制アクセス制御を適用するのは不可能だ。これは別に日和っているわけではなく、リファレンスモニタ型のアクセス制御を行う限りは不可避の性質なのでしょうがない。そもそも、正体のわからないバイナリモジュールなんかをぶち込むなと。

実装を見てないので何とも言えないが、せめて pl/pgSQL のレベルまでは適用できるといいなぁ。