diff options
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r-- | security/selinux/netlabel.c | 85 |
1 files changed, 49 insertions, 36 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index bf8750791dd1..051b14c88e2d 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,8 +36,8 @@ #include "security.h" /** - * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism - * @sock: the socket to label + * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism + * @sk: the socket to label * @sid: the SID to use * * Description: @@ -47,17 +47,17 @@ * this function and rcu_read_unlock() after this function returns. * */ -static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) +static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) { int rc; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; rc = security_netlbl_sid_to_secattr(sid, &secattr); if (rc != 0) return rc; - rc = netlbl_socket_setattr(sock, &secattr); + rc = netlbl_sock_setattr(sk, &secattr); if (rc == 0) { spin_lock_bh(&sksec->nlbl_lock); sksec->nlbl_state = NLBL_LABELED; @@ -155,12 +155,15 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) int rc; struct netlbl_lsm_secattr secattr; + if (!netlbl_enabled()) { + *sid = SECSID_NULL; + return 0; + } + netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, &secattr); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) - rc = security_netlbl_secattr_to_sid(&secattr, - base_sid, - sid); + rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); else *sid = SECSID_NULL; netlbl_secattr_destroy(&secattr); @@ -198,7 +201,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) if (netlbl_sock_getattr(sk, &secattr) == 0 && secattr.flags != NETLBL_SECATTR_NONE && security_netlbl_secattr_to_sid(&secattr, - SECINITSID_UNLABELED, + SECINITSID_NETMSG, &nlbl_peer_sid) == 0) sksec->peer_sid = nlbl_peer_sid; netlbl_secattr_destroy(&secattr); @@ -206,7 +209,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) /* Try to set the NetLabel on the socket to save time later, if we fail * here we will pick up the pieces in later calls to * selinux_netlbl_inode_permission(). */ - selinux_netlbl_socket_setsid(sock, sksec->sid); + selinux_netlbl_sock_setsid(sk, sksec->sid); rcu_read_unlock(); } @@ -223,14 +226,15 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) int selinux_netlbl_socket_post_create(struct socket *sock) { int rc = 0; + struct sock *sk = sock->sk; struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; sksec->sclass = isec->sclass; rcu_read_lock(); if (sksec->nlbl_state == NLBL_REQUIRE) - rc = selinux_netlbl_socket_setsid(sock, sksec->sid); + rc = selinux_netlbl_sock_setsid(sk, sksec->sid); rcu_read_unlock(); return rc; @@ -251,14 +255,16 @@ int selinux_netlbl_socket_post_create(struct socket *sock) int selinux_netlbl_inode_permission(struct inode *inode, int mask) { int rc; - struct sk_security_struct *sksec; + struct sock *sk; struct socket *sock; + struct sk_security_struct *sksec; if (!S_ISSOCK(inode->i_mode) || ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) return 0; sock = SOCKET_I(inode); - sksec = sock->sk->sk_security; + sk = sock->sk; + sksec = sk->sk_security; rcu_read_lock(); if (sksec->nlbl_state != NLBL_REQUIRE) { @@ -266,9 +272,9 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) return 0; } local_bh_disable(); - bh_lock_sock_nested(sock->sk); - rc = selinux_netlbl_socket_setsid(sock, sksec->sid); - bh_unlock_sock(sock->sk); + bh_lock_sock_nested(sk); + rc = selinux_netlbl_sock_setsid(sk, sksec->sid); + bh_unlock_sock(sk); local_bh_enable(); rcu_read_unlock(); @@ -292,38 +298,42 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct avc_audit_data *ad) { int rc; - u32 netlbl_sid; - u32 recv_perm; + u32 nlbl_sid; + u32 perm; + struct netlbl_lsm_secattr secattr; - rc = selinux_netlbl_skbuff_getsid(skb, - SECINITSID_UNLABELED, - &netlbl_sid); + if (!netlbl_enabled()) + return 0; + + netlbl_secattr_init(&secattr); + rc = netlbl_skbuff_getattr(skb, &secattr); + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) + rc = security_netlbl_secattr_to_sid(&secattr, + SECINITSID_NETMSG, + &nlbl_sid); + else + nlbl_sid = SECINITSID_UNLABELED; + netlbl_secattr_destroy(&secattr); if (rc != 0) return rc; - if (netlbl_sid == SECSID_NULL) - return 0; - switch (sksec->sclass) { case SECCLASS_UDP_SOCKET: - recv_perm = UDP_SOCKET__RECVFROM; + perm = UDP_SOCKET__RECVFROM; break; case SECCLASS_TCP_SOCKET: - recv_perm = TCP_SOCKET__RECVFROM; + perm = TCP_SOCKET__RECVFROM; break; default: - recv_perm = RAWIP_SOCKET__RECVFROM; + perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(sksec->sid, - netlbl_sid, - sksec->sclass, - recv_perm, - ad); + rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); if (rc == 0) return 0; - netlbl_skbuff_err(skb, rc); + if (nlbl_sid != SECINITSID_UNLABELED) + netlbl_skbuff_err(skb, rc); return rc; } @@ -345,14 +355,17 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, int optname) { int rc = 0; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sock *sk = sock->sk; + struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; rcu_read_lock(); if (level == IPPROTO_IP && optname == IP_OPTIONS && sksec->nlbl_state == NLBL_LABELED) { netlbl_secattr_init(&secattr); - rc = netlbl_socket_getattr(sock, &secattr); + lock_sock(sk); + rc = netlbl_sock_getattr(sk, &secattr); + release_sock(sk); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = -EACCES; netlbl_secattr_destroy(&secattr); |