diff options
Diffstat (limited to 'security/selinux/netlabel.c')
| -rw-r--r-- | security/selinux/netlabel.c | 37 | 
1 files changed, 32 insertions, 5 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index da4b8b23328..0364120d1ec 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -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: @@ -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;  }  | 
