やってみたこと
CentOS7上で、
- 独自タイプ定義
- 独自ドメイン定義
- ドメイン遷移定義
- 独自 allow ルール定義
をやってみました。
ネット上にも資料が少なく、かなり苦労しました…
#既存マクロの一部を書き換えての対応が必要だったり…
[SE Linux] 実習環境 on CentOS7
(事前準備)
関連パッケージのインストール
$ sudo yum install selinux-policy-mls
$ sudo yum install selinux-policy-devel
/etc/selinux/config書き換え
SELINUX=permissive ※絶対にenforcingのままにしないこと!
SELINUXTYPE=mls ※selinux-policy-mlsをインストールしないと起動不可になるよ!
こんな風にします(ファイルの配置とラベル)
/home/tomonobu/
+ mypolicy/ ......... 独自ポリシー置場
| + Makefile ... ビルド用メイクファイル
| + mypolicy.te ... teファイル
| + mypolicy.fc ... fcファイル
|
+ myapp/myapp ... ドメイン (my_secure_app_t) / タイプ (my_secure_app_exec_t)
+ secure_data ... タイプ (my_secure_data_t)
+ hello.txt
作業内容(ほとんど作業メモですが)
/home/tomonobu/secure_data に my_secure_data_t を付与
$ mkdir mypolicy
$ cd mypolicy
$ touch mypolicy.te
$ touch mypolicy.fc
$ cp /usr/share/selinux/devel/Makefile .
$ vi mypolicy.te
-----
module mypolicy 1.0; # mypolicyはファイル名と合わせる(合わせないとエラー)
type my_secure_data_t;
file_type(my_secure_data_t)
-----
$ vi mypolicy.fc
-----
/home/tomonobu/secure_data(/.*)? gen_context(system_u:object_r:my_secure_data_t, s0)
-----
$ make
$ tree
.
├─ Makefile
├─ mypolicy.fc
├─ mypolicy.if *
├─ mypolicy.pp *
├─ mypolicy.te
└─ tmp *
├─ all_interfaces.conf *
├─ iferror.m4 *
└─ mypolicy.tmp *
makeすると * のファイルが出来上がる
$ sudo semodule -i mypolicy.pp # ポリシーのインストール
$ cd
$ mkdir secure_data
$ restoreconf -RF .
$ ls -Z
-rwxrwxr-x. tomonobu tomonobu user_u:object_r:user_home_t:s0 a.out
-rw-rw-r--. tomonobu tomonobu user_u:object_r:user_home_t:s0 hello.c
drwxrwxr-x. tomonobu tomonobu user_u:object_r:user_home_t:s0 mypolicy
drwxrwxr-x. tomonobu tomonobu user_u:object_r:user_home_t:s0 secure_data
^^^^^^^^^^^
独自タイプ(my_secure_data_t)がついていない(想定内)
ホームディレクトリ配下に独自ラベルを付けるためには、以下の対応が必要
$ cd /etc/selinux/mls/contexts/files
^^^
SELINUXTYPEと連動する
$ vi file_contexts
$ cat file_contexts | grep tomonobu
/home/tomonobu/secure_data(/.*)? system_u:object_r:my_secure_data_t:s0
$ sudo vi file_contexts ... 上記の行を消す
$ sudo vi file_contexts.homedirs ... 上記の行を追加する
$ cd
$ restorecon -RF .
$ ls -Z
-rwxrwxr-x. tomonobu tomonobu user_u:object_r:user_home_t:s0 a.out
-rw-rw-r--. tomonobu tomonobu user_u:object_r:user_home_t:s0 hello.c
drwxrwxr-x. tomonobu tomonobu user_u:object_r:user_home_t:s0 mypolicy
drwxrwxr-x. tomonobu tomonobu system_u:object_r:my_secure_data_t:s0 secure_data
^^^^^^^^^^^^^^^^
OK!!
audit.logの確認
$ echo "hello" > secure_data/hello.txt
$ su
# cd /var/log/audit
# grep hello audit.log
type=AVC msg=audit(1516640677.824:259): avc: denied { add_name } for pid=1108 comm="bash" name="hello.txt" scontext=user_u:user_r:user_t:s0 tcontext=system_u:object_r:my_secure_data_t:s0 tclass=dir
type=AVC msg=audit(1516640677.824:259): avc: denied { create } for pid=1108 comm="bash" name="hello.txt" scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:my_secure_data_t:s0 tclass=file
type=AVC msg=audit(1516640677.824:259): avc: denied { write open } for pid=1108 comm="bash" path="/home/tomonobu/secure_data/hello.txt" dev="dm-0" ino=17104421 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:my_secure_data_t:s0 tclass=file
# grep secure_data audit.log もしてみていろいろ確認してみよう
myappの作成と audit.log の確認
$ cd
$ mkdir myapp
$ cd myapp
$ vi myapp.c
/home/tomonobu/secure_data 以下のファイルを触りに行くコードを書きます。
(hello.txtは echo "hello" > hello.txt とでもして作っておいてください)
#include <stdio.h>
#define SIZE 256
int main(int argc, char** argv) {
FILE *fp;
char buf[SIZE];
fp = fopen("/home/tomonobu/secure_data/hello.txt", "r");
if (NULL == fp) {
printf("ERROR : fopen\n");
return -1;
}
else {
while (fgets(buf, SIZE, fp) != NULL) {
printf("%s", buf);
}
}
fclose(fp);
return 0;
}
実行して、audit.log の avcエラーを確認してみます。
$ echo "hello" > /home/tomonobu/secure_data/hello.txt
$ gcc myapp.c -o myapp
$ myapp
$ su
# cd /var/log/audit
# grep myapp audit.log
type=AVC msg=audit(1516641337.815:295): avc: denied { read } for pid=1448 comm="myapp" name="hello.txt" dev="dm-0" ino=17104421 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:my_secure_data_t:s0 tclass=file
※ myapp が hello.txt を読もうとして read の avcエラー が出ている (期待動作)
myappにドメインの付与(ドメインの準備と付与)
$ cd
$ cd mypolicy
$ vi mypolicy.te
-----
policy_module(mypolicy, 2.0)
type my_secure_data_t;
files_type(my_secure_data_t)
type my_secure_app_exec_t;
files_type(my_secure_app_exec_t)
type my_secure_app_t;
domain_type(my_secure_app_t)
domain_entry_file(my_secure_app_t, my_secure_app_exec_t)
unconfined_domtrans_to(my_secure_app_t, my_secure_app_exec_t)
allow my_secure_app_t my_secure_data_t:file read_file_perms;
-----
$ vi mypolicy.fc
-----
/home/tomonobu/secure_data(/.*)? gen_context(system_u:object_r:my_secure_data_t, s0)
/home/tomonobu/myapp/myapp gen_context(system_u:object_r:my_secure_app_exec_t, s0)
-----
$ make clean
$ make
$ sudo semodule -i mypolicy.pp
Failed to resolve typeattributeset statement at /etc/selinux/mls/tmp/modules/400/mypolicy/cil:22
semodule: Failed!
※ Fail...
※ なんとなく、過去に自分で作ったラベルと当たっちゃっててエラーになっている気がする...
(事実を知った俺より過去の俺へ...)
違う
mlsには unconfied_t の定義が無いのに、
unconfied_domtrans_toマクロ内で利用しているので "Failt to resolve typeatributeset" となっている。
(エラー原因のラベル名をエラーメッセージに出してほしいよね...)
unconfined_domtrans_to(my_secure_app_t, my_secure_app_exec_t)
の行があると、上記エラーが出る。
逆にこの一行を消すと上記エラーは発生しない。(一行ずつコメントアウトして確かめたよ... orz)
http://linux.k-sakabe.com/LinuxSecurityEx.pdf
とか
https://qiita.com/bonon0/items/b027b673ef98af3ed4fd
とか
みても、正しそうだけどなぁ...
/usr/share/selinux/devel/ にて grep "unconfined_domtrans_to"
↓
./devel/include/roles/unconfineduser.if:interface(unconfined_domtrans_to',
※これを見てみると...
./devel/include/roles.xml:
./devel/policy.xml:
※マクロ定義かな??
/usr/share/selinux/devel/include/roles/unconfineduser.if
########################################
## <summary>
## Allow unconfined to execute the specified program in
## the specified domain.
## </summary>
## <desc>
## <p>
## Allow unconfined to execute the specified program in
## the specified domain.
## </p>
## <p>
## This is a interface to support third party modules
## and its use is not allowed in upstream reference
## policy.
## </p>
## </desc>
## <param name="domain">
## <summary>
## Domain to execute in.
## </summary>
## </param>
## <param name="entry_file">
## <summary>
## Domain entry point file.
## </summary>
## </param>
#
interface(`unconfined_domtrans_to',`
gen_require(`
type unconfined_t;
')
domtrans_pattern(unconfined_t,$2,$1)
')
ん?
mlsだと、unconfied_t が定義されていなくてこけている??? <-- 正解
ここを
interface(`unconfined_domtrans_to',`
gen_require(`
type user_t;
')
domtrans_pattern(user_t,$2,$1)
')
に変更してみた。(ps -Z すると、bashやpsが user_t で動作している様子なので)
==> 通った!!!
$ cd
$ cd myapp
$ ./myapp
で audit.log の確認
type=AVC msg=audit(1516646161.634:861): avc: denied { search } for pid=3023 comm="myapp" name="secure_data" dev="dm-0" ino=17104418 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=dir
type=AVC msg=audit(1516646161.634:861): avc: denied { read } for pid=3023 comm="myapp" name="hello.txt" dev="dm-0" ino=17104421 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1516646161.634:861): avc: denied { open } for pid=3023 comm="myapp" path="/home/tomonobu/secure_data/hello.txt" dev="dm-0" ino=17104421 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1516646161.636:862): avc: denied { getattr } for pid=3023 comm="myapp" path="/home/tomonobu/secure_data/hello.txt" dev="dm-0" ino=17104421 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1516646161.636:863): avc: denied { getattr } for pid=3023 comm="myapp" path="/dev/pts/0" dev="devpts" ino=3 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_devpts_t:s0 tclass=chr_file
ログアウト・ログイン で 再度試す
type=AVC msg=audit(1516646161.636:863): avc: denied { getattr } for pid=3023 comm="myapp" path="/dev/pts/0" dev="devpts" ino=3 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_devpts_t:s0 tclass=chr_file
------
type=AVC msg=audit(1516646477.318:945): avc: denied { read write } for pid=3087 comm="myapp" path="/dev/pts/0" dev="devpts" ino=3 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1516646477.321:946): avc: denied { getattr } for pid=3087 comm="myapp" path="/dev/pts/0" dev="devpts" ino=3 scontext=user_u:user_r:my_secure_app_t:s0 tcontext=user_u:object_r:user_devpts_t:s0 tclass=chr_file
------
863以降は、hello.txtに対するアクセスエラーは出ていない様子
==> 成功っぽい ★要検証
- 検証方法-1) mypolicy.teから allow 行を消して検証
- 検証方法-2) myappを無限ループさせて、ps -Z で ドメインチェック
※ dev/pts/0 についてはこちら
http://piyopiyocs.blog115.fc2.com/blog-entry-663.html