diff options
Diffstat (limited to 'security/selinux/netlabel.c')
| -rw-r--r-- | security/selinux/netlabel.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 1c2fc46544b..0364120d1ec 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -4,7 +4,7 @@ * This file provides the necessary glue to tie NetLabel into the SELinux * subsystem. * - * Author: Paul Moore <paul.moore@hp.com> + * Author: Paul Moore <paul@paul-moore.com> * */ @@ -101,6 +101,32 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) } /** + * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr + * @sk: the socket + * @sid: the SID + * + * Query the socket's cached secattr and if the SID matches the cached value + * return the cache, otherwise return NULL. + * + */ +static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( + const struct sock *sk, + u32 sid) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; + + if (secattr == NULL) + return NULL; + + if ((secattr->flags & NETLBL_SECATTR_SECID) && + (secattr->attr.secid == sid)) + return secattr; + + return NULL; +} + +/** * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache * * Description: @@ -151,7 +177,7 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) * * Description: * Called when the NetLabel state of a sk_security_struct needs to be reset. - * The caller is responsibile for all the NetLabel sk_security_struct locking. + * The caller is responsible for all the NetLabel sk_security_struct locking. * */ void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) @@ -224,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, struct sk_security_struct *sksec = sk->sk_security; if (sksec->nlbl_state != NLBL_REQSKB) return 0; - secattr = sksec->nlbl_secattr; + secattr = selinux_netlbl_sock_getattr(sk, sid); } if (secattr == NULL) { secattr = &secattr_storage; @@ -410,6 +436,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, sksec->nlbl_state == NLBL_CONNLABELED)) { netlbl_secattr_init(&secattr); lock_sock(sk); + /* call the netlabel function directly as we want to see the + * on-the-wire label that is assigned via the socket's options + * and not the cached netlabel/lsm attributes */ rc = netlbl_sock_getattr(sk, &secattr); release_sock(sk); if (rc == 0) @@ -442,8 +471,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state != NLBL_CONNLABELED) return 0; - local_bh_disable(); - bh_lock_sock_nested(sk); + lock_sock(sk); /* connected sockets are allowed to disconnect when the address family * is set to AF_UNSPEC, if that is what is happening we want to reset @@ -464,7 +492,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state = NLBL_CONNLABELED; socket_connect_return: - bh_unlock_sock(sk); - local_bh_enable(); + release_sock(sk); return rc; } |
