■
今日もひたすらアクセスベクタの解析。
ほとんど自分用メモ。
ネットワークとプロセス間通信の制御でSELinuxができること
このところの解析のまとめ。
SELinux Policy Editorでは,TCP/IP通信の制御を抜本的に見直す必要がありそう。
たぶん来年だな…
今のSELinuxのstrictポリシでは,ネットワークのアクセス制御設定を細かく行うのは玄人でも難しい。マクロが用意されて無いので。
その割に,「簡単」をうたっているセキュアOSでは,この辺のアクセス制御が結構できそう。
なので,これを簡単に行えるようにするだけでも,SELinux Policy Editorの存在意義が上がるはず。
LinuxケーパビリティとSELinuxケーパビリティの関係
SELinuxのcapabilityの解析。
Linuxのソースをみると,ケーパビリティ(capability)のチェックは,「capable」関数を使って行っている。
●linux/sched.h #ifdef CONFIG_SECURITY /* code is in security.c */ extern int capable(int cap); #else static inline int capable(int cap) { if (cap_raised(current->cap_effective, cap)) { current->flags |= PF_SUPERPRIV; return 1; } return 0; } #endif
security.c(LSM)を使っている時は,security.cを見ろと書いてある。
● security/security.c int capable(int cap) { if (security_ops->capable(current, cap)) {★ /* capability denied */ return 0; } /* capability granted */ current->flags |= PF_SUPERPRIV; return 1; }
LSMを使っている時は,★で,LSMのフックが呼ばれるようだ。
SELinuxを使っている場合は,以下のフックが呼ばれる。
static int selinux_capable(struct task_struct *tsk, int cap) { int rc; rc = secondary_ops->capable(tsk, cap);★ if (rc) return rc; return task_has_capability(tsk,cap);★★ }
secondary_opsには,普通はLinux capablityが入っている(security/capability.c)はずなので,★では,普通のLinux capabilityのチェックがされる。
★★にて,SELinuxのcapablityのチェックがされる。
つまり,ドメインがcapabilityを持ってるのかのチェックがされる。
確かに,この実装だと,capabilityの意味は普通のLinuxと互換性あると思ったが,
SELinuxのフック(hooks.c)内部でも「capable」が使われてる…
capabilityの詳細な意味の解析は後日にしよう…
また,capability関連のログがenforcingモードでしか出ないことがあったが,
この理由は不明。
タイプがソケットを作成したドメインになるもの
id:himainu:20051017で,一つ忘れてた。
ソケット関連のアクセスベクタで,「socket_has_perm」を使ってチェックしているものについては,ドメイン間通信の制御ができない。
read, write, create, getattr, bind, connect, listen, accep, getopt, setopt, shutdown
が該当する。
アクセス制御されるときのタイプは,ソケットを作成したドメインになる。
具体例
で,具体的に,
read, write, create, getattr, bind, connect, listen, accep, getopt, setopt, shutdown
を使って何ができるか。
ドメインa_t→b_tのTCP通信を例にして(少し簡略化してる)
1) a_tがTCPソケット作成。
ソケット(正確にはソケットのinode)のタイプは「a_t」。
2)a_tがb_tとconnectionを張ろうとする
ドメイン:a_t,
タイプ:a_t
オブジェクトクラスtcp_socket
アクセスベクタconnect
のチェックが走る
これを許可するには
allow a_t a_t:tcp_socket connect;
が必要。
allow a_t b_tではない!!
もう一つの例(あまりない例)
1) a_tがTCPソケット作成。
ソケット(正確にはソケットのinode)のタイプは「a_t」。
2)a_tがプロセスを生成,ドメイン遷移しc_tになる。
1)のソケットを継承する。そのタイプはa_t。
3)c_tがb_tとconnectionを張ろうとする
ドメイン:c_t,
タイプ:a_t
オブジェクトクラスtcp_socket
アクセスベクタconnect
のチェックが走る
これを許可するには
allow c_t a_t:tcp_socket connect;
が必要。
上のソースコード解析
これは分かりにくかった(アクセスベクタのgrepではすまなかった)。
ソースコードをちゃんと解析する必要があった。忘れそうだから載せとこう。
ソケットのrecvmsgの際のフックを例にして解析。
static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) { return socket_has_perm(current, sock, SOCKET__READ); }
socket_has_permが呼ばれる。
static int socket_has_perm(struct task_struct *task, struct socket *sock, u32 perms) struct inode_security_struct *isec; struct task_security_struct *tsec; struct avc_audit_data ad; int err = 0; tsec = task->security; isec = SOCK_INODE(sock)->i_security; if (isec->sid == SECINITSID_KERNEL) goto out; AVC_AUDIT_DATA_INIT(&ad,NET); ad.u.net.sk = sock->sk; err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad); ★↑ここでパーミッションチェック …
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
のドメイン(tsec->sid)はプロセスのドメイン。
問題は,タイプ(isec->sid)が何か。
isec = SOCK_INODE(sock)->i_security;
となっている。
ソケット構造体のiノードに付与されているタイプらしい。
次の問題は,ソケット構造体のiノードにどんなタイプが付与されるか。
ソケットのiノードのタイプ初期化は以下で行われる。
static void selinux_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { struct inode_security_struct *isec; struct task_security_struct *tsec; isec = SOCK_INODE(sock)->i_security; tsec = current->security; isec->sclass = socket_type_to_security_class(family, type, protocol); isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; ★ isec->initialized = 1; return; }
★が鍵。kernの値が気になる。
ユーザランドから使う時は,「kern」は「0」。
net/socket.c
int sock_create(int family, int type, int protocol, struct socket **res) { return __sock_create(family, type, protocol, res, 0(これが「kern」に渡る)); }
のように,「kern」が「0」でOK。kernが1になるのはカーネルが内部的に使う時のみ。
で,
isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
では,tsec->sid、「つまりソケットを作成したドメイン」が使われる。
結局,
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
では,ドメイン,ソケットを作成したドメイン,をもとにアクセス制御が行われることが分かる。