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

Commit 6b877699 authored by Venkat Yekkirala's avatar Venkat Yekkirala Committed by David S. Miller
Browse files

SELinux: Return correct context for SO_PEERSEC



Fix SO_PEERSEC for tcp sockets to return the security context of
the peer (as represented by the SA from the peer) as opposed to the
SA used by the local/source socket.

Signed-off-by: default avatarVenkat Yekkirala <vyekkirala@TrustedCS.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent c1a856c9
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -826,6 +826,8 @@ struct request_sock;
 *	Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
 * @inet_csk_clone:
 *	Sets the new child socket's sid to the openreq sid.
 * @inet_conn_established:
 *     Sets the connection's peersid to the secmark on skb.
 * @req_classify_flow:
 *	Sets the flow's sid to the openreq sid.
 *
@@ -1368,6 +1370,7 @@ struct security_operations {
	int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
					struct request_sock *req);
	void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
	void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
	void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
#endif	/* CONFIG_SECURITY_NETWORK */

@@ -2961,6 +2964,12 @@ static inline void security_inet_csk_clone(struct sock *newsk,
{
	security_ops->inet_csk_clone(newsk, req);
}

static inline void security_inet_conn_established(struct sock *sk,
			struct sk_buff *skb)
{
	security_ops->inet_conn_established(sk, skb);
}
#else	/* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
					       struct socket * other,
@@ -3110,6 +3119,11 @@ static inline void security_inet_csk_clone(struct sock *newsk,
			const struct request_sock *req)
{
}

static inline void security_inet_conn_established(struct sock *sk,
			struct sk_buff *skb)
{
}
#endif	/* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct request_sock {
	struct request_sock_ops		*rsk_ops;
	struct sock			*sk;
	u32				secid;
	u32				peer_secid;
};

static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
+2 −0
Original line number Diff line number Diff line
@@ -4230,6 +4230,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
		mb();
		tcp_set_state(sk, TCP_ESTABLISHED);

		security_inet_conn_established(sk, skb);

		/* Make sure socket is routed, for correct metrics.  */
		icsk->icsk_af_ops->rebuild_header(sk);

+6 −0
Original line number Diff line number Diff line
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk,
{
}

static inline void dummy_inet_conn_established(struct sock *sk,
			struct sk_buff *skb)
{
}

static inline void dummy_req_classify_flow(const struct request_sock *req,
			struct flowi *fl)
{
@@ -1108,6 +1113,7 @@ void security_fixup_ops (struct security_operations *ops)
	set_to_dummy_if_null(ops, sock_graft);
	set_to_dummy_if_null(ops, inet_conn_request);
	set_to_dummy_if_null(ops, inet_csk_clone);
	set_to_dummy_if_null(ops, inet_conn_established);
	set_to_dummy_if_null(ops, req_classify_flow);
 #endif	/* CONFIG_SECURITY_NETWORK */
#ifdef  CONFIG_SECURITY_NETWORK_XFRM
+17 −4
Original line number Diff line number Diff line
@@ -3535,8 +3535,10 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
	}
	else if (isec->sclass == SECCLASS_TCP_SOCKET) {
		peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
		if (peer_sid == SECSID_NULL)
			peer_sid = selinux_socket_getpeer_stream(sock->sk);
		if (peer_sid == SECSID_NULL) {
			ssec = sock->sk->sk_security;
			peer_sid = ssec->peer_sid;
		}
		if (peer_sid == SECSID_NULL) {
			err = -ENOPROTOOPT;
			goto out;
@@ -3647,11 +3649,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
		return 0;
	}

	err = selinux_xfrm_decode_session(skb, &peersid, 0);
	BUG_ON(err);
	selinux_skb_xfrm_sid(skb, &peersid);

	if (peersid == SECSID_NULL) {
		req->secid = sksec->sid;
		req->peer_secid = 0;
		return 0;
	}

@@ -3660,6 +3662,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
		return err;

	req->secid = newsid;
	req->peer_secid = peersid;
	return 0;
}

@@ -3669,6 +3672,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
	struct sk_security_struct *newsksec = newsk->sk_security;

	newsksec->sid = req->secid;
	newsksec->peer_sid = req->peer_secid;
	/* NOTE: Ideally, we should also get the isec->sid for the
	   new socket in sync, but we don't have the isec available yet.
	   So we will wait until sock_graft to do it, by which
@@ -3677,6 +3681,14 @@ static void selinux_inet_csk_clone(struct sock *newsk,
	selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
}

static void selinux_inet_conn_established(struct sock *sk,
				struct sk_buff *skb)
{
	struct sk_security_struct *sksec = sk->sk_security;

	selinux_skb_xfrm_sid(skb, &sksec->peer_sid);
}

static void selinux_req_classify_flow(const struct request_sock *req,
				      struct flowi *fl)
{
@@ -4739,6 +4751,7 @@ static struct security_operations selinux_ops = {
	.sock_graft =			selinux_sock_graft,
	.inet_conn_request =		selinux_inet_conn_request,
	.inet_csk_clone =		selinux_inet_csk_clone,
	.inet_conn_established =	selinux_inet_conn_established,
	.req_classify_flow =		selinux_req_classify_flow,

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Loading