diff options
Diffstat (limited to 'security/selinux/netlabel.c')
| -rw-r--r-- | security/selinux/netlabel.c | 74 |
1 files changed, 39 insertions, 35 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 1321f15799e2..d51dfe892312 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -17,6 +17,7 @@ #include <linux/gfp.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/lsm_hooks.h> #include <net/sock.h> #include <net/netlabel.h> #include <net/ip.h> @@ -46,7 +47,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, { int rc; - rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid); + rc = security_netlbl_secattr_to_sid(secattr, sid); if (rc == 0 && (secattr->flags & NETLBL_SECATTR_CACHEABLE) && (secattr->flags & NETLBL_SECATTR_CACHE)) @@ -62,13 +63,13 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, * Description: * Generate the NetLabel security attributes for a socket, making full use of * the socket's attribute cache. Returns a pointer to the security attributes - * on success, NULL on failure. + * on success, or an ERR_PTR on failure. * */ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_secattr != NULL) @@ -76,12 +77,12 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) secattr = netlbl_secattr_alloc(GFP_ATOMIC); if (secattr == NULL) - return NULL; - rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid, - secattr); + return ERR_PTR(-ENOMEM); + + rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); if (rc != 0) { netlbl_secattr_free(secattr); - return NULL; + return ERR_PTR(rc); } sksec->nlbl_secattr = secattr; @@ -101,7 +102,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( const struct sock *sk, u32 sid) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; if (secattr == NULL) @@ -155,8 +156,12 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway) */ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) { - if (sksec->nlbl_secattr != NULL) - netlbl_secattr_free(sksec->nlbl_secattr); + if (!sksec->nlbl_secattr) + return; + + netlbl_secattr_free(sksec->nlbl_secattr); + sksec->nlbl_secattr = NULL; + sksec->nlbl_state = NLBL_UNSET; } /** @@ -195,6 +200,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, struct netlbl_lsm_secattr secattr; if (!netlbl_enabled()) { + *type = NETLBL_NLTYPE_NONE; *sid = SECSID_NULL; return 0; } @@ -236,7 +242,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, * being labeled by it's parent socket, if it is just exit */ sk = skb_to_full_sk(skb); if (sk != NULL) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (sksec->nlbl_state != NLBL_REQSKB) return 0; @@ -245,8 +251,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, if (secattr == NULL) { secattr = &secattr_storage; netlbl_secattr_init(secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, sid, - secattr); + rc = security_netlbl_sid_to_secattr(sid, secattr); if (rc != 0) goto skbuff_setsid_return; } @@ -274,7 +279,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, { int rc; struct netlbl_lsm_secattr secattr; - struct sk_security_struct *sksec = asoc->base.sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(asoc->base.sk); struct sockaddr_in addr4; struct sockaddr_in6 addr6; @@ -283,8 +288,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, - asoc->secid, &secattr); + rc = security_netlbl_sid_to_secattr(asoc->secid, &secattr); if (rc != 0) goto assoc_request_return; @@ -332,8 +336,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid, - &secattr); + rc = security_netlbl_sid_to_secattr(req->secid, &secattr); if (rc != 0) goto inet_conn_request_return; rc = netlbl_req_setattr(req, &secattr); @@ -355,9 +358,9 @@ inet_conn_request_return: */ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); - if (family == PF_INET) + if (family == PF_INET || family == PF_INET6) sksec->nlbl_state = NLBL_LABELED; else sksec->nlbl_state = NLBL_UNSET; @@ -373,8 +376,8 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) */ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) { - struct sk_security_struct *sksec = sk->sk_security; - struct sk_security_struct *newsksec = newsk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); + struct sk_security_struct *newsksec = selinux_sock(newsk); newsksec->nlbl_state = sksec->nlbl_state; } @@ -392,16 +395,19 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; if (family != PF_INET && family != PF_INET6) return 0; secattr = selinux_netlbl_sock_genattr(sk); - if (secattr == NULL) - return -ENOMEM; - rc = netlbl_sock_setattr(sk, family, secattr); + if (IS_ERR(secattr)) + return PTR_ERR(secattr); + /* On socket creation, replacement of IP options is safe even if + * the caller does not hold the socket lock. + */ + rc = netlbl_sock_setattr(sk, family, secattr, true); switch (rc) { case 0: sksec->nlbl_state = NLBL_LABELED; @@ -463,8 +469,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(&selinux_state, - sksec->sid, nlbl_sid, sksec->sclass, perm, ad); + rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); if (rc == 0) return 0; @@ -507,7 +512,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, { int rc = 0; struct sock *sk = sock->sk; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr secattr; if (selinux_netlbl_option(level, optname) && @@ -545,7 +550,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk, struct sockaddr *addr) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; /* connected sockets are allowed to disconnect when the address family @@ -558,10 +563,9 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk, return rc; } secattr = selinux_netlbl_sock_genattr(sk); - if (secattr == NULL) { - rc = -ENOMEM; - return rc; - } + if (IS_ERR(secattr)) + return PTR_ERR(secattr); + rc = netlbl_conn_setattr(sk, addr, secattr); if (rc == 0) sksec->nlbl_state = NLBL_CONNLABELED; @@ -584,7 +588,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk, int selinux_netlbl_socket_connect_locked(struct sock *sk, struct sockaddr *addr) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (sksec->nlbl_state != NLBL_REQSKB && sksec->nlbl_state != NLBL_CONNLABELED) |
