Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14a72f53 authored by Paul Moore's avatar Paul Moore Committed by David S. Miller
Browse files

[NetLabel]: correct improper handling of non-NetLabel peer contexts



Fix a problem where NetLabel would always set the value of 
sk_security_struct->peer_sid in selinux_netlbl_sock_graft() to the context of
the socket, causing problems when users would query the context of the
connection.  This patch fixes this so that the value in
sk_security_struct->peer_sid is only set when the connection is NetLabel based,
otherwise the value is untouched.

Signed-off-by: default avatarPaul Moore <paul.moore@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 597811ec
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
int cipso_v4_socket_setattr(const struct socket *sock,
			    const struct cipso_v4_doi *doi_def,
			    const struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
int cipso_v4_socket_getattr(const struct socket *sock,
			    struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
@@ -225,6 +226,12 @@ static inline int cipso_v4_socket_setattr(const struct socket *sock,
	return -ENOSYS;
}

static inline int cipso_v4_sock_getattr(struct sock *sk,
					struct netlbl_lsm_secattr *secattr)
{
	return -ENOSYS;
}

static inline int cipso_v4_socket_getattr(const struct socket *sock,
					  struct netlbl_lsm_secattr *secattr)
{
+8 −0
Original line number Diff line number Diff line
@@ -238,6 +238,8 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr,
#ifdef CONFIG_NETLABEL
int netlbl_socket_setattr(const struct socket *sock,
			  const struct netlbl_lsm_secattr *secattr);
int netlbl_sock_getattr(struct sock *sk,
			struct netlbl_lsm_secattr *secattr);
int netlbl_socket_getattr(const struct socket *sock,
			  struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -250,6 +252,12 @@ static inline int netlbl_socket_setattr(const struct socket *sock,
	return -ENOSYS;
}

static inline int netlbl_sock_getattr(struct sock *sk,
				      struct netlbl_lsm_secattr *secattr)
{
	return -ENOSYS;
}

static inline int netlbl_socket_getattr(const struct socket *sock,
					struct netlbl_lsm_secattr *secattr)
{
+33 −15
Original line number Diff line number Diff line
@@ -1486,43 +1486,40 @@ int cipso_v4_socket_setattr(const struct socket *sock,
}

/**
 * cipso_v4_socket_getattr - Get the security attributes from a socket
 * @sock: the socket
 * cipso_v4_sock_getattr - Get the security attributes from a sock
 * @sk: the sock
 * @secattr: the security attributes
 *
 * Description:
 * Query @sock to see if there is a CIPSO option attached to the socket and if
 * there is return the CIPSO security attributes in @secattr.  Returns zero on
 * success and negative values on failure.
 * Query @sk to see if there is a CIPSO option attached to the sock and if
 * there is return the CIPSO security attributes in @secattr.  This function
 * requires that @sk be locked, or privately held, but it does not do any
 * locking itself.  Returns zero on success and negative values on failure.
 *
 */
int cipso_v4_socket_getattr(const struct socket *sock,
			    struct netlbl_lsm_secattr *secattr)
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
{
	int ret_val = -ENOMSG;
	struct sock *sk;
	struct inet_sock *sk_inet;
	unsigned char *cipso_ptr;
	u32 doi;
	struct cipso_v4_doi *doi_def;

	sk = sock->sk;
	lock_sock(sk);
	sk_inet = inet_sk(sk);
	if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
		goto socket_getattr_return;
		return -ENOMSG;
	cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
		sizeof(struct iphdr);
	ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
	if (ret_val == 0)
		goto socket_getattr_return;
		return ret_val;

	doi = ntohl(*(u32 *)&cipso_ptr[2]);
	rcu_read_lock();
	doi_def = cipso_v4_doi_getdef(doi);
	if (doi_def == NULL) {
		rcu_read_unlock();
		goto socket_getattr_return;
		return -ENOMSG;
	}
	switch (cipso_ptr[6]) {
	case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1530,29 @@ int cipso_v4_socket_getattr(const struct socket *sock,
	}
	rcu_read_unlock();

socket_getattr_return:
	release_sock(sk);
	return ret_val;
}

/**
 * cipso_v4_socket_getattr - Get the security attributes from a socket
 * @sock: the socket
 * @secattr: the security attributes
 *
 * Description:
 * Query @sock to see if there is a CIPSO option attached to the socket and if
 * there is return the CIPSO security attributes in @secattr.  Returns zero on
 * success and negative values on failure.
 *
 */
int cipso_v4_socket_getattr(const struct socket *sock,
			    struct netlbl_lsm_secattr *secattr)
{
	int ret_val;

	lock_sock(sock->sk);
	ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
	release_sock(sock->sk);

	return ret_val;
}

+23 −0
Original line number Diff line number Diff line
@@ -84,6 +84,29 @@ int netlbl_socket_setattr(const struct socket *sock,
	return ret_val;
}

/**
 * netlbl_sock_getattr - Determine the security attributes of a sock
 * @sk: the sock
 * @secattr: the security attributes
 *
 * Description:
 * Examines the given sock to see any NetLabel style labeling has been
 * applied to the sock, if so it parses the socket label and returns the
 * security attributes in @secattr.  Returns zero on success, negative values
 * on failure.
 *
 */
int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
{
	int ret_val;

	ret_val = cipso_v4_sock_getattr(sk, secattr);
	if (ret_val == 0)
		return 0;

	return netlbl_unlabel_getattr(secattr);
}

/**
 * netlbl_socket_getattr - Determine the security attributes of a socket
 * @sock: the socket
+11 −1
Original line number Diff line number Diff line
@@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
{
	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
	struct sk_security_struct *sksec = sk->sk_security;
	struct netlbl_lsm_secattr secattr;
	u32 nlbl_peer_sid;

	sksec->sclass = isec->sclass;

	if (sk->sk_family != PF_INET)
		return;

	netlbl_secattr_init(&secattr);
	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
	    selinux_netlbl_secattr_to_sid(NULL,
					  &secattr,
					  sksec->sid,
					  &nlbl_peer_sid) == 0)
		sksec->peer_sid = nlbl_peer_sid;
	netlbl_secattr_destroy(&secattr, 0);

	sksec->nlbl_state = NLBL_REQUIRE;
	sksec->peer_sid = sksec->sid;

	/* 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