|
|
|
@ -67,6 +67,38 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
|
|
|
|
|
* @sk: the socket
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct sk_security_struct *sksec = sk->sk_security;
|
|
|
|
|
struct netlbl_lsm_secattr *secattr;
|
|
|
|
|
|
|
|
|
|
if (sksec->nlbl_secattr != NULL)
|
|
|
|
|
return sksec->nlbl_secattr;
|
|
|
|
|
|
|
|
|
|
secattr = netlbl_secattr_alloc(GFP_ATOMIC);
|
|
|
|
|
if (secattr == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
|
|
|
|
|
if (rc != 0) {
|
|
|
|
|
netlbl_secattr_free(secattr);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
sksec->nlbl_secattr = secattr;
|
|
|
|
|
|
|
|
|
|
return secattr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
|
|
|
|
|
* @sk: the socket to label
|
|
|
|
@ -80,17 +112,15 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct sk_security_struct *sksec = sk->sk_security;
|
|
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
|
|
struct netlbl_lsm_secattr *secattr;
|
|
|
|
|
|
|
|
|
|
if (sksec->nlbl_state != NLBL_REQUIRE)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
|
|
|
|
|
|
|
rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr);
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
goto sock_setsid_return;
|
|
|
|
|
rc = netlbl_sock_setattr(sk, &secattr);
|
|
|
|
|
secattr = selinux_netlbl_sock_genattr(sk);
|
|
|
|
|
if (secattr == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
rc = netlbl_sock_setattr(sk, secattr);
|
|
|
|
|
switch (rc) {
|
|
|
|
|
case 0:
|
|
|
|
|
sksec->nlbl_state = NLBL_LABELED;
|
|
|
|
@ -101,8 +131,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sock_setsid_return:
|
|
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -136,6 +164,20 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
|
|
|
|
|
netlbl_skbuff_err(skb, error, gateway);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selinux_netlbl_sk_security_free - Free the NetLabel fields
|
|
|
|
|
* @sssec: the sk_security_struct
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Free all of the memory in the NetLabel fields of a sk_security_struct.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
|
|
|
|
|
{
|
|
|
|
|
if (ssec->nlbl_secattr != NULL)
|
|
|
|
|
netlbl_secattr_free(ssec->nlbl_secattr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields
|
|
|
|
|
* @ssec: the sk_security_struct
|
|
|
|
@ -209,7 +251,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
|
|
|
|
|
u32 sid)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
|
|
struct netlbl_lsm_secattr secattr_storage;
|
|
|
|
|
struct netlbl_lsm_secattr *secattr = NULL;
|
|
|
|
|
struct sock *sk;
|
|
|
|
|
|
|
|
|
|
/* if this is a locally generated packet check to see if it is already
|
|
|
|
@ -219,16 +262,21 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
if (secattr == NULL) {
|
|
|
|
|
secattr = &secattr_storage;
|
|
|
|
|
netlbl_secattr_init(secattr);
|
|
|
|
|
rc = security_netlbl_sid_to_secattr(sid, secattr);
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
goto skbuff_setsid_return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
|
|
rc = security_netlbl_sid_to_secattr(sid, &secattr);
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
goto skbuff_setsid_return;
|
|
|
|
|
rc = netlbl_skbuff_setattr(skb, family, &secattr);
|
|
|
|
|
rc = netlbl_skbuff_setattr(skb, family, secattr);
|
|
|
|
|
|
|
|
|
|
skbuff_setsid_return:
|
|
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
|
|
if (secattr == &secattr_storage)
|
|
|
|
|
netlbl_secattr_destroy(secattr);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -245,18 +293,18 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct sk_security_struct *sksec = sk->sk_security;
|
|
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
|
|
struct netlbl_lsm_secattr *secattr;
|
|
|
|
|
struct inet_sock *sk_inet = inet_sk(sk);
|
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
|
|
|
|
|
|
if (sksec->nlbl_state != NLBL_REQUIRE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
|
|
if (security_netlbl_sid_to_secattr(sksec->sid, &secattr) != 0)
|
|
|
|
|
goto inet_conn_established_return;
|
|
|
|
|
secattr = selinux_netlbl_sock_genattr(sk);
|
|
|
|
|
if (secattr == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
rc = netlbl_sock_setattr(sk, &secattr);
|
|
|
|
|
rc = netlbl_sock_setattr(sk, secattr);
|
|
|
|
|
switch (rc) {
|
|
|
|
|
case 0:
|
|
|
|
|
sksec->nlbl_state = NLBL_LABELED;
|
|
|
|
@ -266,13 +314,13 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
|
|
|
|
|
* labeling protocols */
|
|
|
|
|
if (family != PF_INET) {
|
|
|
|
|
sksec->nlbl_state = NLBL_UNSET;
|
|
|
|
|
goto inet_conn_established_return;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr.sin_family = family;
|
|
|
|
|
addr.sin_addr.s_addr = sk_inet->daddr;
|
|
|
|
|
if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
|
|
|
|
|
&secattr) != 0) {
|
|
|
|
|
secattr) != 0) {
|
|
|
|
|
/* we failed to label the connected socket (could be
|
|
|
|
|
* for a variety of reasons, the actual "why" isn't
|
|
|
|
|
* important here) so we have to go to our backup plan,
|
|
|
|
@ -300,10 +348,6 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
|
|
|
|
|
* return an error code */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inet_conn_established_return:
|
|
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -468,13 +512,12 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct sk_security_struct *sksec = sk->sk_security;
|
|
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
|
|
struct netlbl_lsm_secattr *secattr;
|
|
|
|
|
|
|
|
|
|
if (sksec->nlbl_state != NLBL_REQSKB &&
|
|
|
|
|
sksec->nlbl_state != NLBL_CONNLABELED)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
|
|
local_bh_disable();
|
|
|
|
|
bh_lock_sock_nested(sk);
|
|
|
|
|
|
|
|
|
@ -487,17 +530,17 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
|
|
|
|
|
rc = 0;
|
|
|
|
|
goto socket_connect_return;
|
|
|
|
|
}
|
|
|
|
|
rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr);
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
secattr = selinux_netlbl_sock_genattr(sk);
|
|
|
|
|
if (secattr == NULL) {
|
|
|
|
|
rc = -ENOMEM;
|
|
|
|
|
goto socket_connect_return;
|
|
|
|
|
rc = netlbl_conn_setattr(sk, addr, &secattr);
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
goto socket_connect_return;
|
|
|
|
|
sksec->nlbl_state = NLBL_CONNLABELED;
|
|
|
|
|
}
|
|
|
|
|
rc = netlbl_conn_setattr(sk, addr, secattr);
|
|
|
|
|
if (rc == 0)
|
|
|
|
|
sksec->nlbl_state = NLBL_CONNLABELED;
|
|
|
|
|
|
|
|
|
|
socket_connect_return:
|
|
|
|
|
bh_unlock_sock(sk);
|
|
|
|
|
local_bh_enable();
|
|
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|