Esempio n. 1
0
/**
 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
 * @sk: the new connection
 *
 * Description:
 * A new connection has been established on @sk so make sure it is labeled
 * correctly with the NetLabel susbsystem.
 *
 */
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 inet_sock *sk_inet = inet_sk(sk);
	struct sockaddr_in addr;

	if (sksec->nlbl_state != NLBL_REQUIRE)
		return;

	secattr = selinux_netlbl_sock_genattr(sk);
	if (secattr == NULL)
		return;

	rc = netlbl_sock_setattr(sk, secattr);
	switch (rc) {
	case 0:
		sksec->nlbl_state = NLBL_LABELED;
		break;
	case -EDESTADDRREQ:
		/* no PF_INET6 support yet because we don't support any IPv6
		 * labeling protocols */
		if (family != PF_INET) {
			sksec->nlbl_state = NLBL_UNSET;
			return;
		}

		addr.sin_family = family;
		addr.sin_addr.s_addr = sk_inet->daddr;
		if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
					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,
			 * labeling the packets individually in the netfilter
			 * local output hook.  this is okay but we need to
			 * adjust the MSS of the connection to take into
			 * account any labeling overhead, since we don't know
			 * the exact overhead at this point we'll use the worst
			 * case value which is 40 bytes for IPv4 */
			struct inet_connection_sock *sk_conn = inet_csk(sk);
			sk_conn->icsk_ext_hdr_len += 40 -
				      (sk_inet->opt ? sk_inet->opt->optlen : 0);
			sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);

			sksec->nlbl_state = NLBL_REQSKB;
		} else
			sksec->nlbl_state = NLBL_CONNLABELED;
		break;
	default:
		/* note that we are failing to label the socket which could be
		 * a bad thing since it means traffic could leave the system
		 * without the desired labeling, however, all is not lost as
		 * we have a check in selinux_netlbl_inode_permission() to
		 * pick up the pieces that we might drop here because we can't
		 * return an error code */
		break;
	}
}
Esempio n. 2
0
/**
 * selinux_netlbl_socket_connect - Label a client-side socket on connect
 * @sk: the socket to label
 * @addr: the destination address
 *
 * Description:
 * Attempt to label a connected socket with NetLabel using the given address.
 * Returns zero values on success, negative values on failure.
 *
 */
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;

	if (sksec->nlbl_state != NLBL_REQSKB &&
	    sksec->nlbl_state != NLBL_CONNLABELED)
		return 0;

	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
	 * the socket */
	if (addr->sa_family == AF_UNSPEC) {
		netlbl_sock_delattr(sk);
		sksec->nlbl_state = NLBL_REQSKB;
		rc = 0;
		goto socket_connect_return;
	}
	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)
		sksec->nlbl_state = NLBL_CONNLABELED;

socket_connect_return:
	release_sock(sk);
	return rc;
}