めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

SELinux 入門 (2) - ポリシーソースを眺めてみる

RHEL6 の targeted ポリシーのソース全体(マクロ展開した後の生のポリシー)を眺めます。

※ 実際にポリシーを書く時はマクロを駆使するので、以下の生ポリシーを書く必要はありません。

ポリシーソースの入手

# rpm -Uvh selinux-policy-3.7.19-54.el6.src.rpm
# cd rpmbuild
# rpmbuild -bi SPECS/selinux-policy.spec --define "BUILD_STRICT 0" --define "BUILD_MLS 0"
# cd BUILD/serefpolicy-3.7.19/
# cp build.conf build.conf.orig
# vi build.conf
# diff build.conf build.conf.orig
15c15
< TYPE = mcs
---
> TYPE = standard
21c21
< NAME = targeted
---
> NAME = refpolicy
30c30
< DISTRO = redhat
---
> #DISTRO = redhat
45c45
< DIRECT_INITRC = y
---
> DIRECT_INITRC = n
49c49
< MONOLITHIC = n
---
> MONOLITHIC = y

# make install-src
rm -rf /etc/selinux/targeted/src/policy.old
mv /etc/selinux/targeted/src/policy /etc/selinux/targeted/src/policy.old
mv: cannot stat `/etc/selinux/targeted/src/policy': そのようなファイルやディレクトリはありません
make: [install-src] エラー 1 (無視されました)
mkdir -p /etc/selinux/targeted/src/policy
cp -R . /etc/selinux/targeted/src/policy

# cd /etc/selinux/targeted/src/policy
# make policy

このとき、以下のファイルができている

・/etc/selinux/targeted/src/policy/base.conf : すべてのポリシーを一つにまとめたファイル(cf ファイル相当)
・/etc/selinux/targeted/src/policy/base.fc : ファイルに設定する SID の定義ファイル

※この他にモジュールとしてコンパイルされるポリシーもあり、それらは、base.conf に含まれていないので要注意。

base.conf を眺める。

最初は、オブジェクトクラスの宣言

# Classes marked as userspace are classes
# for userspace object managers

class security
class process
class system
class capability

# file-related classes
class filesystem
class file
class dir
class fd
class lnk_file
class chr_file
class blk_file
class sock_file
class fifo_file
...

続いて、初期 SID の宣言。これは、カーネル内部のオブジェクトに割り当てるものなので、開発者以外は気にしなくてよい。

#
# Define initial security identifiers
#

sid kernel
sid security
sid unlabeled
sid fs
sid file
...

# 具体的な SID はポリシーファイルの後半部分に記載
sid netmsg system_u:object_r:netlabel_peer_t:s0
sid port system_u:object_r:port_t:s0
sid node system_u:object_r:node_t:s0
sid netif system_u:object_r:netif_t:s0
sid devnull system_u:object_r:null_device_t:s0
sid file system_u:object_r:file_t:s0
sid fs system_u:object_r:fs_t:s0
sid kernel system_u:system_r:kernel_t:s0
...

common は、アクセスベクタのグループを定義するもの。(このあとで、オブジェクトクラスにアクセスベクタを割り当てる時に、アクセスベクタをまとめて指定するのに使う。)

#
# Define a common prefix for file access vectors.
#

common file
{
        ioctl
        read
        write
        create
        getattr
        setattr
        lock
        relabelfrom
        relabelto
        append
        unlink
        link
        rename
        execute
        swapon
        quotaon
        mounton
}
...

class で、オブジェクトクラスにアクセスベクタを割り当てる。inherits で common 定義したアクセスベクタ群を指定して、{}で個別のアクセスベクタを追加。

class dir
inherits file
{
        add_name
        remove_name
        reparent
        search
        rmdir
        open
}
...

attribute は、タイプ属性のグループにつける名前。後ほどタイプ属性を定義するときに、それが属する attribute を複数指定できる。

attribute admindomain;
attribute application_domain_type;
attribute application_exec_type;
attribute boolean_type;
attribute can_change_object_identity;
attribute can_change_process_identity;
...

bool は、ダイナミックに On/Off できるパラメータ。この後の定義内で、if () { } という条件設定ができる。

bool allow_daemons_dump_core true;
bool allow_daemons_use_tty false;
bool allow_domain_fd_use true;
bool allow_gssd_read_tmp true;
...

type で、タイプ属性を宣言する。type <タイプ属性名> [, 所属する attribute, ...] というフォーマット

type ping_exec_t;
type ping_t;
type pingd_client_packet_t, packet_type, client_packet_type;
type pingd_port_t, port_type;
...

typeattribute で後から所属する attribute を追加することも可能

        typeattribute acct_t application_domain_type;
        typeattribute acct_t domain;
...

typealias は、タイプ属性に(複数の)別名をつける。

typealias ssh_tmpfs_t alias { auditadm_ssh_tmpfs_t secadm_ssh_tmpfs_t };
typealias ssh_tmpfs_t alias { user_ssh_tmpfs_t staff_ssh_tmpfs_t sysadm_ssh_tmpfs_t };
typealias system_conf_t alias iptables_conf_t;
...

optional は、require で指定された要素が定義されている場合にのみ有効になるという意味。
allow は、アクションの許可を定義。この例では、『acct_t ドメインのサブジェクトが、タイプ unconfined_t のオブジェクトに対して、オブジェクトクラス fd としてのアクション use の実行を許可する』という意味。

optional {
  require {
    type unconfined_t;
  } # end require
  allow acct_t unconfined_t:fd use;
} # end optional

dontaudit は、アクションは禁止するがログには記録しないという指示。

dontaudit acct_t security_t:filesystem getattr;

user は、ユーザ属性が利用可能なロール属性を指定

# grep -E "^\s*user" base.conf
user system_u roles { system_r unconfined_r } level s0 range s0 - s0:c0.c255;
user user_u roles { user_r } level s0 range s0;
user staff_u roles { staff_r system_r sysadm_r unconfined_r } level s0 range s0 - s0:c0.c255;
user sysadm_u roles { sysadm_r } level s0 range s0 - s0:c0.c255;
user root roles { unconfined_r sysadm_r staff_r system_r } level s0 range s0 - s0:c0.c255;

role は、ロール属性が利用可能なドメインを指定

# grep -E "^role" base.conf
role system_r types alsa_t;
role system_r types anaconda_t;
role system_r types apm_t;
role system_r types chkpwd_t;
role system_r types pam_console_t;
role system_r types pam_t;
...

type_transition は、ドメイン遷移の指定。プロセスがファイルを実行して、新しいプロセスを起動する時のドメイン遷移は、以下の4つの設定が必要。

allow initrc_t acct_exec_t:file { getattr open read execute };
# initrc_t ドメインのプロセスが acct_exec_t タイプのファイルを実行(execute)することを許可。

type_transition initrc_t acct_exec_t:process acct_t;
# initrc_t ドメインのプロセスが acct_exec_t タイプのファイルを実行して生成したプロセスのドメインを acct_t に指定。

allow acct_t acct_exec_t:file entrypoint;
# acct_exec_t タイプのファイルから acct_t ドメインのプロセスを生成することを許可。

allow initrc_t acct_t:process transition;
# initrc_t ドメインのプロセスが acct_t ドメインのプロセスを生成することを許可。

新しく作成するファイルの SID も type_transition で指定。

allow acct_t var_log_t:dir { open read getattr lock search ioctl add_name remove_name write };
# acct_t ドメインのプロセスが var_log_t タイプのディレクトリにファイルを作成(add_name)することを許可。

type_transition acct_t var_log_t:file wtmp_t;
# acct_t ドメインのプロセスが var_log_t タイプのディレクトリに作成したファイルのタイプを wtmp_t に指定。

allow は、タイプ属性で許可するが、constrain は、SID の 3 つ組すべての条件で許可を出す。

constrain dir { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton add_name remove_name reparent search rmdir open }
(
     u1 == u2
  or u1 == system_u
  or u2 == system_u
  or t1 != ubac_constrained_type
  or t2 != ubac_constrained_type
  or t1 == ubacfile
);

getfscon は、procfs などの仮想ファイルシステム(もしくは、SID を永続的に保持できないファイルシステム)の SID を設定する

# grep genfscon base.conf2 | grep proc
genfscon proc /mtrr system_u:object_r:mtrr_device_t:s0
genfscon proc /kallsyms system_u:object_r:system_map_t:s0
genfscon proc / system_u:object_r:proc_t:s0
genfscon proc /sysvipc system_u:object_r:proc_t:s0
genfscon proc /fs/openafs system_u:object_r:proc_afs_t:s0
genfscon proc /kmsg system_u:object_r:proc_kmsg_t:s0
genfscon proc /kcore system_u:object_r:proc_kcore_t:s0
genfscon proc /mdstat system_u:object_r:proc_mdstat_t:s0
genfscon proc /net system_u:object_r:proc_net_t:s0
genfscon proc /xen system_u:object_r:proc_xen_t:s0
genfscon proc /sys system_u:object_r:sysctl_t:s0
genfscon proc /irq system_u:object_r:sysctl_irq_t:s0
genfscon proc /net/rpc system_u:object_r:sysctl_rpc_t:s0
genfscon proc /sys/crypto system_u:object_r:sysctl_crypto_t:s0
genfscon proc /sys/fs system_u:object_r:sysctl_fs_t:s0
genfscon proc /sys/kernel system_u:object_r:sysctl_kernel_t:s0
genfscon proc /sys/kernel/modprobe system_u:object_r:sysctl_modprobe_t:s0
genfscon proc /sys/kernel/hotplug system_u:object_r:sysctl_hotplug_t:s0
genfscon proc /sys/net system_u:object_r:sysctl_net_t:s0
genfscon proc /sys/net/unix system_u:object_r:sysctl_net_unix_t:s0
genfscon proc /sys/vm system_u:object_r:sysctl_vm_t:s0
genfscon proc /sys/dev system_u:object_r:sysctl_dev_t:s0

portcon は、ソケットの SID を指定する。

portcon udp 7007 system_u:object_r:afs_bos_port_t:s0
portcon udp 7001 system_u:object_r:afs_client_port_t:s0
portcon tcp 2040 system_u:object_r:afs_fs_port_t:s0
portcon udp 7000 system_u:object_r:afs_fs_port_t:s0
portcon udp 7005 system_u:object_r:afs_fs_port_t:s0
portcon udp 7004 system_u:object_r:afs_ka_port_t:s0
...