diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fc926d3cac6e..ad3abd48eed1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4590,14 +4590,10 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, secclass, NULL, socksid); } -static int sock_has_perm(struct sock *sk, u32 perms) +static bool sock_skip_has_perm(u32 sid) { - struct sk_security_struct *sksec = selinux_sock(sk); - struct common_audit_data ad; - struct lsm_network_audit net; - - if (sksec->sid == SECINITSID_KERNEL) - return 0; + if (sid == SECINITSID_KERNEL) + return true; /* * Before POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, sockets that @@ -4611,7 +4607,19 @@ static int sock_has_perm(struct sock *sk, u32 perms) * setting. */ if (!selinux_policycap_userspace_initial_context() && - sksec->sid == SECINITSID_INIT) + sid == SECINITSID_INIT) + return true; + return false; +} + + +static int sock_has_perm(struct sock *sk, u32 perms) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct common_audit_data ad; + struct lsm_network_audit net; + + if (sock_skip_has_perm(sksec->sid)) return 0; ad_net_init_from_sk(&ad, &net, sk); @@ -5920,6 +5928,26 @@ static unsigned int selinux_ip_postroute(void *priv, } #endif /* CONFIG_NETFILTER */ +static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_type) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct common_audit_data ad; + struct lsm_network_audit net; + u8 driver; + u8 xperm; + + if (sock_skip_has_perm(sksec->sid)) + return 0; + + ad_net_init_from_sk(&ad, &net, sk); + + driver = nlmsg_type >> 8; + xperm = nlmsg_type & 0xff; + + return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass, + perms, driver, xperm, &ad); +} + static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { int rc = 0; @@ -5945,7 +5973,12 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); if (rc == 0) { - rc = sock_has_perm(sk, perm); + if (selinux_policycap_netlink_xperm()) { + rc = nlmsg_sock_has_extended_perms( + sk, perm, nlh->nlmsg_type); + } else { + rc = sock_has_perm(sk, perm); + } if (rc) return rc; } else if (rc == -EINVAL) { |