labeled-ipsec: Return correct context for SO_PEERSEC
Subsystems (5)
PATCH 2/3 labeled-ipsec: 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 Venkat Yekkirala <[email protected]>
--- include/linux/security.h | 14 ++++++++++ include/net/request_sock.h | 1 net/ipv4/tcp_input.c | 2 + security/dummy.c | 6 ++++ security/selinux/hooks.c | 21 ++++++++++++--- security/selinux/include/xfrm.h | 12 ++++----- security/selinux/xfrm.c | 40 ++---------------------------- 7 files changed, 49 insertions(+), 47 deletions(-)
include/linux/security.h +14 -0
@@ -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_clo { 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_clo 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
include/net/request_sock.h +1 -0
@@ -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)
net/ipv4/tcp_input.c +2 -0
@@ -4230,6 +4230,8 @@ static int tcp_rcv_synsent_state_processmb ();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);
security/dummy.c +6 -0
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone( { } +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 securityset_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
security/selinux/include/xfrm.h +6 -6
@@ -39,7 +39,6 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, s struct avc_audit_data *ad);int selinux_xfrm_postroute_last (u32 isec_sid,struct sk_buff *skb,struct avc_audit_data *ad); -u32 selinux_socket_getpeer_stream (struct sock *sk);u32 selinux_socket_getpeer_dgram (struct sk_buff *skb);int selinux_xfrm_decode_session (struct sk_buff *skb,u32 *sid,int ckall);#else
@@ -55,11 +54,6 @@ static inline int selinux_xfrm_postroutereturn 0 ; } -static inline int selinux_socket_getpeer_stream (struct sock *sk) -{ -return SECSID_NULL ; -} -static inline int selinux_socket_getpeer_dgram (struct sk_buff *skb) {return SECSID_NULL ;
@@ -71,4 +65,10 @@ static inline int selinux_xfrm_decode_se }#endif +static inline void selinux_skb_xfrm_sid (struct sk_buff *skb,u32 *sid) +{ +int err =selinux_xfrm_decode_session (skb, sid,0 ); +BUG_ON (err); +} +#endif /* _SELINUX_XFRM_H_ */
security/selinux/hooks.c +17 -4
@@ -3534,8 +3534,10 @@ static int selinux_socket_getpeersec_str }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;
@@ -3646,11 +3648,11 @@ static int selinux_inet_conn_request(strreturn 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 ; }
@@ -3659,6 +3661,7 @@ static int selinux_inet_conn_request(strreturn err; req->secid = newsid; + req->peer_secid = peersid;return 0 ; }
@@ -3668,6 +3671,7 @@ static void selinux_inet_csk_clone(strucstruct 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
@@ -3676,6 +3680,14 @@ static void selinux_inet_csk_clone(strucselinux_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) {
@@ -4738,6 +4750,7 @@ static struct security_operations selinu .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
security/selinux/xfrm.c +3 -37
@@ -184,7 +184,8 @@ int selinux_xfrm_flow_state_match(struct }/* -* LSM hook implementation that determines the sid for the session. +* LSM hook implementation that checks and/or returns the xfrm sid for the +* incoming packet. */ int selinux_xfrm_decode_session (struct sk_buff *skb,u32 *sid,int ckall)
@@ -403,43 +404,8 @@ void selinux_xfrm_state_free(struct xfrm }/* -* SELinux internal function to retrieve the context of a connected -* (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security -* association used to connect to the remote socket. -* -* Retrieve via getsockopt SO_PEERSEC. -*/ -u32 selinux_socket_getpeer_stream (struct sock *sk) -{ -struct dst_entry *dst, *dst_test; -u32 peer_sid =SECSID_NULL ; - -if (sk->sk_state !=TCP_ESTABLISHED ) - goto out; - - dst =sk_dst_get (sk); -if (!dst) - goto out; - -for (dst_test = dst; dst_test !=0 ; - dst_test = dst_test->child) { -struct xfrm_state *x = dst_test->xfrm; - -if (x &&selinux_authorizable_xfrm (x)) { -struct xfrm_sec_ctx *ctx = x->security; - peer_sid = ctx->ctx_sid; -break ; - } - } -dst_release (dst); - -out: -return peer_sid; -} - -/* * SELinux internal function to retrieve the context of a UDP packet -* based on its security association used to connect to the remote socket. +* based on its security association. * * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message * type SCM_SECURITY.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.