Toward next Commit Fest

前回、pgsql-hackersに投稿したパッチに対して、Tom Laneから非常に多くのコメントが付いたが、ようやくその全てに対して修正を終えた。
(最も手間がかかったのは『ドキュメント添付してよ』というリクエストだったが…。)

コーディングスタイルや、コンパイル時の警告など、自明なものもあるが、かなり根本的な修正を迫られたものもあった。

一番大きかったのは、security_label型の廃止。

以前は、システム列 "security_context" に security_label型を与え、型入力ハンドラで 文字列形式 → SecurityID への変換を行っていた。
SecurityIDは、セキュリティコンテキストの内部表現で、userspace AVCのキーにも使っている。

しかし、Read-Onlyトランザクションの中で

SELECT 'user_u:user_r:user_t:s0:c99'::security_label;
なんて悪戯をすると、問題が発生する事に気が付いた。何も更新操作を行うつもりがないのに、pg_securityシステムカタログに行を追加してしまう。

これを改善するため、"security_context" システム列をTEXT型で定義し、INSERTやUPDATEでタプルが追記される直前に、文字列→SecurityIDの変換を行うようにした。

だが、これは別の問題を引き起こす。

全てのセキュリティコンテキスト(の文字列表現)が SecurityID を持つ事を担保できないため、場合によっては文字列をキーとしてuserspace AVC を探索できる必要がある。
そのため、インターフェースの追加を余儀なくされた。

また、文字列というのは事前に長さが決定できないため、固定長の共有メモリセグメントにこれを配置することはできない。従って、今までは共有メモリ上に配置していた AVC を、ローカルメモリ上に確保する必要がある。

ローカルメモリにAVCを配置すると、ポリシー再ロード時の Invalidation の問題がある。SELinuxは、ポリシーの再ロードやBooleanの設定変更をアプリに通知する機能を持っているが、共有メモリにAVCを配置するのに比べ、ローカルメモリの場合は Invalidation が煩雑だ。
結局、この問題は共有メモリに version カウンタを持たせて、それを atomic_read() する事で、各インスタンスが自分の AVC の有効性を確認できるようにした。

なんと言う美しき芋づる。

他には、行レベルのアクセス制御を、WHERE/ON句の書き換えでなく、ExecScanへのフックによって実現するようにした事で、コードの複雑さが大幅に小さくなったことなど。

そんな感じで、なんとか6末には間に合いそうか〜