Capability audit_writeとaudit_controlの解析
まずは結論から。
- audit_writeの意味:
- ユーザスペースのAVCのログをカーネルに送る(拒否,許可されてもログ出ない)
- audit_controlの意味:
- LAuS(Linux Auditing System)の設定を変えるために必要(拒否,許可されてもログでない)
- /proc/self/loginuidの変更(これは何意味するのだろう?)
結構困った仕様?になってるなぁ。詳しくは下を。
解析
これはトリッキーな実装。
MLでStephen Smalley氏に聞いて始めて分かった…ありがたや。
SELinuxと普通のLinuxのcapabilityが依存しているとは。
まずhooks.cから。
static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { struct task_security_struct *tsec; struct av_decision avd; int err; err = secondary_ops->netlink_send(sk, skb); if (err) return err; tsec = current->security; avd.allowed = 0; avc_has_perm_noaudit(tsec->sid, tsec->sid, SECCLASS_CAPABILITY, ~0, &avd);★1 cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed); ★2
★1で,プロセスがどんなcapabilityをallowされてるかをavdにセット。
★2で, NETLINK_CB(skb).eff_capに,★1の値をセット。既存のcapabilityがあっても,SELinuxのavd.allowedをandを取る。
確か既存のcapabilityはデフォルト全ビット1なので,上書きということになる。
cap_maskは↓参照。
●capability.h #define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0)
ここまでは気づいていた。この後の使われ方が難しい。
kernel/audit.cにワープ。
static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type) { int err = 0; switch (msg_type) { case AUDIT_GET: case AUDIT_LIST: case AUDIT_SET: case AUDIT_ADD: case AUDIT_DEL: case AUDIT_SIGNAL_INFO: if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))★3 err = -EPERM; break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))★4 err = -EPERM; break; …… …省略 … static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { … err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);★5 if (err) return err;
さて,auditメッセージをカーネルが受信するときに,★5が呼ばれる。
でこの中で★3,★4のように,
なんと★1,2でセットされた値を使ってチェックをしている!
SELinuxに関係ない場所で,SELinuxの値を使っているのはよくない気がする。
なぜなら,permissiveモードとselinux無効な場合の振る舞いが違ってくるから。
例:
1)permissiveモードで,capability:audit_control権限が足りないポリシーを書く。
2)★1、2で,capability:audit_controlがセットされない。
3)★3,4で,拒否される。しかもログも出ない
のようにpermissiveモードにも関わらず、アクセス拒否され,さらにはログが出ないという状態が発生。
ただ,
★4は,滅多に呼ばれない(つまりaudit_writeはほとんど使われない)気がする。
AUDIT_USERは,すでに廃止されてるし,
AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSGは、ユーザスペースのAVCのメッセージ(使われてないし)
★3はauditctlコマンドぐらいしかチェックされないかなぁ。
他にaudit_controlが使われてる場所
fs/proc/base.c
if (!capable(CAP_AUDIT_CONTROL))
Smalley氏いわく,
/proc/self/loginuidに書き込む時にチェックされるそうだ。
なんかaudit_controlと意味が違う気がするが…
Capability周りは厄介だ…
追記:
Smalley氏によると,上の問題(permissiveでも拒否される恐れがある)
は以前discussされたことがあるとか。
で,パッチが出てるそうだが,なぜか本流に入ってないとか…