【SELinuxポリシー追加】audit2allowの使い方/ .teの書き方, make方法, .ppの内容確認方法

SELinux のモジュールとは

SELinux のポリシールールはいくつかの種類に分かれます。ポリシーの大部分を占めるプリセットされた "Monothilic ポリシー"、必要に応じて追加できる "Loadable Module ポリシー"、条件によって(Booleanの値が0か1かによって)使われるかどうかが決まる "Conditional ポリシー" 等です。

audit2allow コマンド等を使って手動で追加する許可ルールは Loadable Module ポリシーに該当します。

例えば以下のようなログ(audit.log)が ausearch コマンドにより表示されたとします。

[root@localhost ~]# ausearch -m avc -ts today
----
time->Sun Jul 15 03:49:01 2018
type=SYSCALL msg=audit(1531594141.821:3548): arch=c000003e syscall=49 success=no exit=-13 a0=3 a1=7ffc6e936700 a2=6e a3=0 items=0 ppid=15845 pid=15846 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=426 comm="chronyc" exe="/usr/bin/chronyc" subj=system_u:system_r:logrotate_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1531594141.821:3548): avc:  denied  { write } for  pid=15846 comm="chronyc" name="chrony" dev="tmpfs" ino=14791 scontext=system_u:system_r:logrotate_t:s0-s0:c0.c1023 tcontext=system_u:object_r:chronyd_var_run_t:s0 tclass=dir

上記はSELinux により拒否された操作内容ですが、SELinux のトラブルシュートの単純な解決策の1つは、上記のログで拒否された内容を許可するルールを追加することです。具体的には、許可ルールを Loadable モジュールとしてインストールすることなのですが、結構簡単に実現できます。

まずこのログの内容を紐解きます。

操作を拒否されたプロセスは "comm=chronyc" で、このプロセスが持つコンテキスト(scontext=Source Context)は "system_u:system_r:logrotate_t:s0-s0:c0.c1023 " です。

どこに対する操作なのかというのは ino=14791 がヒントになります。これは i-node 番号ですので、 find / -inum 14791 でパスを見つけられます。この環境では、/run/chrony だとわかります。ls -Z /run | grep chrony で確認してみると、この /run/chrony のコンテキスト(tcontext)は "system_u:object_r:chronyd_var_run_t:s0" であることがわかります。

どのような操作かというと、tclass と avc denied の後の{}中カッコを見るとわかります。tclass は SELinux で定義されている操作の種類(ObjectClass), 中カッコの中身は具体的なパーミッションです。ここでは tclass=dir つまりディレクトリに対する操作、具体的なパーミッションは書き込み(write) です。

クラスとパーミッションの詳細については下記ページに載っています。

https://selinuxproject.org/page/ObjectClassesPerms

つまり、scontext=logrotate_t から tcontext=chronyd_var_run_t への許可ルールを作ればよいのです。

このあたりの意味が分からない方は、以下のSELinuxの仕組みの基礎ページをご参照下さい。

【図解】SELinuxとは?〜仕組みやメリット・効果の基礎入門解説〜
【図解】SELinuxとは?〜仕組みやメリット・効果の基礎入門解説〜
SELinuxとは ~概要と仕組み~ SELinux とはSecure-Enh...

audit2allowを使ったモジュール追加方法

この方法はとても簡単です。ログの出力を、audit2allow -M [モジュール名(名称は任意)]オプションをつけてパイプで流し込み、生成された[モジュール名].pp ファイルを semodule -i コマンドでインストールするだけです。以下は chrony-patch という名称で定義する場合の例です。

ausearch -m avc -ts today | audit2allow -M chrony-patch
[root@localhost ~]# ausearch -m avc -ts today | audit2allow -M chrony-patch
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i chrony-patch.pp

[root@localhost ~]# ls
chrony-patch.pp  chrony-patch.te
[root@localhost ~]# cat chrony-patch.te

module chrony-patch 1.0;

require {
        type logrotate_t;
        type chronyd_var_run_t;
        class dir write;
}

#============= logrotate_t ==============
allow logrotate_t chronyd_var_run_t:dir write;
[root@localhost ~]# semodule -i chrony-patch.pp
[root@localhost ~]#

まず "audit2allow -M chrony-patch" コマンドこれにより、chrony-patch.te ファイルと chrony-patch.pp ファイルが生成されます。

.teファイルはテキストベースで、人間にわかる形式での許可ルール定義が書かれており、.ppファイルはバイナリで、semodule -i コマンドでモジュールをインストールできる状態で書かれています。

ではモジュールがインストールされている状態を見てみましょう。

[root@localhost ~]# semanage module -l | grep chrony-patch
chrony-patch              400       pp
[root@localhost ~]# sesearch --allow | grep "logrotate_t chronyd_var_run_t"
   allow logrotate_t chronyd_var_run_t : dir write ;

(audit2allowを使わない) .teファイルからのモジュールルール追加方法

これは少し中級者向けですが、.teファイルを自ら作成し、コンパイルする方法です。

フォーマットは前述の通りで、まずは module [モジュール名] [モジュールバージョン]、その後に許可ルールで使うタイプやクラスをrequire { } で定義、最後に許可ルール、という流れです。

問題はコンパイル方法ですが、これには selinux-policy-devel パッケージが必要になります。

yum -y install selinux-policy-devel

そしてこの.teファイルがある場所で makeします。

[root@localhost ~]# make -f /usr/share/selinux/devel/Makefile
Compiling targeted chrony-patch module
/usr/bin/checkmodule: loading policy configuration from tmp/chrony-patch.tmp
/usr/bin/checkmodule: policy configuration loaded
/usr/bin/checkmodule: writing binary representation (version 19) to tmp/chrony-patch.mod
Creating targeted chrony-patch.pp policy package
rm tmp/chrony-patch.mod.fc tmp/chrony-patch.mod
[root@localhost ~]# ll
合計 23
-rw-------. 1 root root 1424 6月 17 20:03 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 7月 15 21:26 chrony-patch.fc
-rw-r--r--. 1 root root 23 7月 15 21:26 chrony-patch.if
-rw-r--r--. 1 root root 7006 7月 15 21:26 chrony-patch.pp
-rw-r--r--. 1 root root 191 6月 22 22:22 chrony-patch.te
drwxr-xr-x. 2 root root 75 7月 15 21:26 tmp
[root@localhost ~]#

すると .pp ファイルが生成されますので、先ほどと同じように semodule -i でインストールします。

semodule -i chrony-patch.pp

追加したモジュールの内容を確認する

semodule -i でインストールしたモジュールは、 /etc/selinux/targeted/active/modules/400/ 配下に格納されます。"400"というのは優先度で、semodule で -X オプションで指定しない限りはデフォルトで優先度は400になります。

[root@localhost ~]# ll /etc/selinux/targeted/active/modules/400/chrony-patch/
合計 12
-rw-------. 1 root root 107 7月 28 23:55 cil
-rw-------. 1 root root 1912 7月 28 23:55 hll
-rw-------. 1 root root 2 7月 28 23:55 lang_ext
[root@localhost ~]#

上記ディレクトリに格納されたモジュールは  cil と hll という中間言語(バイナリ)に変換されていますので、ポリシーの中身をテキストベースで見ることはできません。

では.pp ファイルや .teファイルを無くしてしまった場合はどのように追加したモジュールの確認をすればよいのでしょうか?

.pp ファイルを .teファイルに変換はできなそうですが、以下のように sedismod コマンドを使うことで、似た形で出力することはできました。

[root@localhost ~]# sedismod chrony-patch.pp
Reading policy...
libsepol.policydb_index_others: security:  0 users, 1 roles, 2 types, 0 bools
libsepol.policydb_index_others: security: 0 sens, 0 cats
libsepol.policydb_index_others: security:  2 classes, 0 rules, 0 cond rules
libsepol.policydb_index_others: security:  0 users, 1 roles, 2 types, 0 bools
libsepol.policydb_index_others: security: 0 sens, 0 cats
libsepol.policydb_index_others: security:  2 classes, 0 rules, 0 cond rules
Binary policy module file loaded.
Module name: chrony-patch
Module version: 1.0


Select a command:
1)  display unconditional AVTAB
2)  display conditional AVTAB
3)  display users
4)  display bools
5)  display roles
6)  display types, attributes, and aliases
7)  display role transitions
8)  display role allows
9)  Display policycon
0)  Display initial SIDs

a)  Display avrule requirements
b)  Display avrule declarations
c)  Display policy capabilities
l)  Link in a module
u)  Display the unknown handling setting
F)  Display filename_trans rules

f)  set output file
m)  display menu
q)  quit

Command ('m' for menu):  1
unconditional avtab:
--- begin avrule block ---
decl 1:
  allow [logrotate_t] [chronyd_var_run_t] : [dir] { add_name write };
  allow [logrotate_t] [chronyd_var_run_t] : [sock_file] { create };

Command ('m' for menu):  a
avrule block requirements:
--- begin avrule block ---
decl 1:
commons: 
classes: sock_file{  create } dir{  add_name  write }
roles  : 
types  : logrotate_t chronyd_var_run_t
users  : 
bools  : 
levels : 
cats   : 

Command ('m' for menu):  q
[root@localhost ~]#

なお、.ppファイルも無くしてしまった場合は、semodule -E [モジュール名]で引っ張ることができます。

[root@localhost ~]# semodule -E chrony-patch
Module 'chrony-patch' does not exist at the default priority '400'. Extracting at highest existing priority '400'.
[root@localhost ~]# ls
chrony-patch.pp

シェアする

  • このエントリーをはてなブックマークに追加

フォローする