aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@trustedcs.com>2006-11-08 18:04:09 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:21:33 -0500
commit6b877699c6f1efede4545bcecc367786a472eedb (patch)
treec0a60dc90578fa9f16d4496e2700bc285eab47c0 /security
parentc1a856c9640c9ff3d70bbd8214b6a0974609eef8 (diff)
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: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c6
-rw-r--r--security/selinux/hooks.c21
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/xfrm.c40
4 files changed, 32 insertions, 47 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 838d8442cf3c..0148d1518dd1 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk,
828{ 828{
829} 829}
830 830
831static inline void dummy_inet_conn_established(struct sock *sk,
832 struct sk_buff *skb)
833{
834}
835
831static inline void dummy_req_classify_flow(const struct request_sock *req, 836static inline void dummy_req_classify_flow(const struct request_sock *req,
832 struct flowi *fl) 837 struct flowi *fl)
833{ 838{
@@ -1108,6 +1113,7 @@ void security_fixup_ops (struct security_operations *ops)
1108 set_to_dummy_if_null(ops, sock_graft); 1113 set_to_dummy_if_null(ops, sock_graft);
1109 set_to_dummy_if_null(ops, inet_conn_request); 1114 set_to_dummy_if_null(ops, inet_conn_request);
1110 set_to_dummy_if_null(ops, inet_csk_clone); 1115 set_to_dummy_if_null(ops, inet_csk_clone);
1116 set_to_dummy_if_null(ops, inet_conn_established);
1111 set_to_dummy_if_null(ops, req_classify_flow); 1117 set_to_dummy_if_null(ops, req_classify_flow);
1112 #endif /* CONFIG_SECURITY_NETWORK */ 1118 #endif /* CONFIG_SECURITY_NETWORK */
1113#ifdef CONFIG_SECURITY_NETWORK_XFRM 1119#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 28ee187ed224..5bbd599a4471 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3535,8 +3535,10 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3535 } 3535 }
3536 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3536 else if (isec->sclass == SECCLASS_TCP_SOCKET) {
3537 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock); 3537 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3538 if (peer_sid == SECSID_NULL) 3538 if (peer_sid == SECSID_NULL) {
3539 peer_sid = selinux_socket_getpeer_stream(sock->sk); 3539 ssec = sock->sk->sk_security;
3540 peer_sid = ssec->peer_sid;
3541 }
3540 if (peer_sid == SECSID_NULL) { 3542 if (peer_sid == SECSID_NULL) {
3541 err = -ENOPROTOOPT; 3543 err = -ENOPROTOOPT;
3542 goto out; 3544 goto out;
@@ -3647,11 +3649,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3647 return 0; 3649 return 0;
3648 } 3650 }
3649 3651
3650 err = selinux_xfrm_decode_session(skb, &peersid, 0); 3652 selinux_skb_xfrm_sid(skb, &peersid);
3651 BUG_ON(err);
3652 3653
3653 if (peersid == SECSID_NULL) { 3654 if (peersid == SECSID_NULL) {
3654 req->secid = sksec->sid; 3655 req->secid = sksec->sid;
3656 req->peer_secid = 0;
3655 return 0; 3657 return 0;
3656 } 3658 }
3657 3659
@@ -3660,6 +3662,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3660 return err; 3662 return err;
3661 3663
3662 req->secid = newsid; 3664 req->secid = newsid;
3665 req->peer_secid = peersid;
3663 return 0; 3666 return 0;
3664} 3667}
3665 3668
@@ -3669,6 +3672,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
3669 struct sk_security_struct *newsksec = newsk->sk_security; 3672 struct sk_security_struct *newsksec = newsk->sk_security;
3670 3673
3671 newsksec->sid = req->secid; 3674 newsksec->sid = req->secid;
3675 newsksec->peer_sid = req->peer_secid;
3672 /* NOTE: Ideally, we should also get the isec->sid for the 3676 /* NOTE: Ideally, we should also get the isec->sid for the
3673 new socket in sync, but we don't have the isec available yet. 3677 new socket in sync, but we don't have the isec available yet.
3674 So we will wait until sock_graft to do it, by which 3678 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,
3677 selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family); 3681 selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
3678} 3682}
3679 3683
3684static void selinux_inet_conn_established(struct sock *sk,
3685 struct sk_buff *skb)
3686{
3687 struct sk_security_struct *sksec = sk->sk_security;
3688
3689 selinux_skb_xfrm_sid(skb, &sksec->peer_sid);
3690}
3691
3680static void selinux_req_classify_flow(const struct request_sock *req, 3692static void selinux_req_classify_flow(const struct request_sock *req,
3681 struct flowi *fl) 3693 struct flowi *fl)
3682{ 3694{
@@ -4739,6 +4751,7 @@ static struct security_operations selinux_ops = {
4739 .sock_graft = selinux_sock_graft, 4751 .sock_graft = selinux_sock_graft,
4740 .inet_conn_request = selinux_inet_conn_request, 4752 .inet_conn_request = selinux_inet_conn_request,
4741 .inet_csk_clone = selinux_inet_csk_clone, 4753 .inet_csk_clone = selinux_inet_csk_clone,
4754 .inet_conn_established = selinux_inet_conn_established,
4742 .req_classify_flow = selinux_req_classify_flow, 4755 .req_classify_flow = selinux_req_classify_flow,
4743 4756
4744#ifdef CONFIG_SECURITY_NETWORK_XFRM 4757#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 8e329ddb5e37..27502365d706 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -39,7 +39,6 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
39 struct avc_audit_data *ad); 39 struct avc_audit_data *ad);
40int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 40int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
41 struct avc_audit_data *ad); 41 struct avc_audit_data *ad);
42u32 selinux_socket_getpeer_stream(struct sock *sk);
43u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); 42u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
44int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 43int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
45#else 44#else
@@ -55,11 +54,6 @@ static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
55 return 0; 54 return 0;
56} 55}
57 56
58static inline int selinux_socket_getpeer_stream(struct sock *sk)
59{
60 return SECSID_NULL;
61}
62
63static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb) 57static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
64{ 58{
65 return SECSID_NULL; 59 return SECSID_NULL;
@@ -71,4 +65,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int
71} 65}
72#endif 66#endif
73 67
68static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
69{
70 int err = selinux_xfrm_decode_session(skb, sid, 0);
71 BUG_ON(err);
72}
73
74#endif /* _SELINUX_XFRM_H_ */ 74#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 4d5a043cdfa1..8fef74271f22 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -184,7 +184,8 @@ int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
184} 184}
185 185
186/* 186/*
187 * LSM hook implementation that determines the sid for the session. 187 * LSM hook implementation that checks and/or returns the xfrm sid for the
188 * incoming packet.
188 */ 189 */
189 190
190int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 191int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
@@ -403,43 +404,8 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
403} 404}
404 405
405/* 406/*
406 * SELinux internal function to retrieve the context of a connected
407 * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
408 * association used to connect to the remote socket.
409 *
410 * Retrieve via getsockopt SO_PEERSEC.
411 */
412u32 selinux_socket_getpeer_stream(struct sock *sk)
413{
414 struct dst_entry *dst, *dst_test;
415 u32 peer_sid = SECSID_NULL;
416
417 if (sk->sk_state != TCP_ESTABLISHED)
418 goto out;
419
420 dst = sk_dst_get(sk);
421 if (!dst)
422 goto out;
423
424 for (dst_test = dst; dst_test != 0;
425 dst_test = dst_test->child) {
426 struct xfrm_state *x = dst_test->xfrm;
427
428 if (x && selinux_authorizable_xfrm(x)) {
429 struct xfrm_sec_ctx *ctx = x->security;
430 peer_sid = ctx->ctx_sid;
431 break;
432 }
433 }
434 dst_release(dst);
435
436out:
437 return peer_sid;
438}
439
440/*
441 * SELinux internal function to retrieve the context of a UDP packet 407 * SELinux internal function to retrieve the context of a UDP packet
442 * based on its security association used to connect to the remote socket. 408 * based on its security association.
443 * 409 *
444 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message 410 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
445 * type SCM_SECURITY. 411 * type SCM_SECURITY.