aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-11-17 17:38:54 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:24:14 -0500
commit3de4bab5b9f8848a0c16a4b1ffe0452f0d670237 (patch)
treef65c12b53bf2ad02645ea31522f67e7318019498
parent9f2ad66509b182b399a5b03de487f45bde623524 (diff)
SELinux: peer secid consolidation for external network labeling
Now that labeled IPsec makes use of the peer_sid field in the sk_security_struct we can remove a lot of the special cases between labeled IPsec and NetLabel. In addition, create a new function, security_skb_extlbl_sid(), which we can use in several places to get the security context of the packet's external label which allows us to further simplify the code in a few places. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--security/selinux/hooks.c43
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/include/selinux_netlabel.h28
-rw-r--r--security/selinux/include/xfrm.h5
-rw-r--r--security/selinux/ss/services.c90
-rw-r--r--security/selinux/xfrm.c33
6 files changed, 52 insertions, 150 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 975c0dfb5a11..a29d78d3f44c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3574,27 +3574,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3574 u32 scontext_len; 3574 u32 scontext_len;
3575 struct sk_security_struct *ssec; 3575 struct sk_security_struct *ssec;
3576 struct inode_security_struct *isec; 3576 struct inode_security_struct *isec;
3577 u32 peer_sid = 0; 3577 u32 peer_sid = SECSID_NULL;
3578 3578
3579 isec = SOCK_INODE(sock)->i_security; 3579 isec = SOCK_INODE(sock)->i_security;
3580 3580
3581 /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ 3581 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
3582 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { 3582 isec->sclass == SECCLASS_TCP_SOCKET) {
3583 ssec = sock->sk->sk_security; 3583 ssec = sock->sk->sk_security;
3584 peer_sid = ssec->peer_sid; 3584 peer_sid = ssec->peer_sid;
3585 } 3585 }
3586 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3586 if (peer_sid == SECSID_NULL) {
3587 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3588 if (peer_sid == SECSID_NULL) {
3589 ssec = sock->sk->sk_security;
3590 peer_sid = ssec->peer_sid;
3591 }
3592 if (peer_sid == SECSID_NULL) {
3593 err = -ENOPROTOOPT;
3594 goto out;
3595 }
3596 }
3597 else {
3598 err = -ENOPROTOOPT; 3587 err = -ENOPROTOOPT;
3599 goto out; 3588 goto out;
3600 } 3589 }
@@ -3626,13 +3615,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3626 u32 peer_secid = SECSID_NULL; 3615 u32 peer_secid = SECSID_NULL;
3627 int err = 0; 3616 int err = 0;
3628 3617
3629 if (sock && (sock->sk->sk_family == PF_UNIX)) 3618 if (sock && sock->sk->sk_family == PF_UNIX)
3630 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3619 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3631 else if (skb) { 3620 else if (skb)
3632 peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb); 3621 security_skb_extlbl_sid(skb,
3633 if (peer_secid == SECSID_NULL) 3622 SECINITSID_UNLABELED,
3634 peer_secid = selinux_socket_getpeer_dgram(skb); 3623 &peer_secid);
3635 }
3636 3624
3637 if (peer_secid == SECSID_NULL) 3625 if (peer_secid == SECSID_NULL)
3638 err = -EINVAL; 3626 err = -EINVAL;
@@ -3693,17 +3681,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3693 u32 newsid; 3681 u32 newsid;
3694 u32 peersid; 3682 u32 peersid;
3695 3683
3696 newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid); 3684 security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
3697 if (newsid != SECSID_NULL) {
3698 req->secid = newsid;
3699 return 0;
3700 }
3701
3702 selinux_skb_xfrm_sid(skb, &peersid);
3703
3704 if (peersid == SECSID_NULL) { 3685 if (peersid == SECSID_NULL) {
3705 req->secid = sksec->sid; 3686 req->secid = sksec->sid;
3706 req->peer_secid = 0; 3687 req->peer_secid = SECSID_NULL;
3707 return 0; 3688 return 0;
3708 } 3689 }
3709 3690
@@ -3738,7 +3719,7 @@ static void selinux_inet_conn_established(struct sock *sk,
3738{ 3719{
3739 struct sk_security_struct *sksec = sk->sk_security; 3720 struct sk_security_struct *sksec = sk->sk_security;
3740 3721
3741 selinux_skb_xfrm_sid(skb, &sksec->peer_sid); 3722 security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
3742} 3723}
3743 3724
3744static void selinux_req_classify_flow(const struct request_sock *req, 3725static void selinux_req_classify_flow(const struct request_sock *req,
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1ef79172cc8c..015f697e925f 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -8,6 +8,7 @@
8#ifndef _SELINUX_SECURITY_H_ 8#ifndef _SELINUX_SECURITY_H_
9#define _SELINUX_SECURITY_H_ 9#define _SELINUX_SECURITY_H_
10 10
11#include <linux/skbuff.h>
11#include "flask.h" 12#include "flask.h"
12 13
13#define SECSID_NULL 0x00000000 /* unspecified SID */ 14#define SECSID_NULL 0x00000000 /* unspecified SID */
@@ -80,6 +81,8 @@ int security_netif_sid(char *name, u32 *if_sid,
80int security_node_sid(u16 domain, void *addr, u32 addrlen, 81int security_node_sid(u16 domain, void *addr, u32 addrlen,
81 u32 *out_sid); 82 u32 *out_sid);
82 83
84void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid);
85
83int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 86int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
84 u16 tclass); 87 u16 tclass);
85 88
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
index 57943f4a8f90..2a732c9033e3 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -38,14 +38,12 @@
38 38
39#ifdef CONFIG_NETLABEL 39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void); 40void selinux_netlbl_cache_invalidate(void);
41int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid);
41int selinux_netlbl_socket_post_create(struct socket *sock); 42int selinux_netlbl_socket_post_create(struct socket *sock);
42void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 43void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
43u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
44int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 44int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
45 struct sk_buff *skb, 45 struct sk_buff *skb,
46 struct avc_audit_data *ad); 46 struct avc_audit_data *ad);
47u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock);
48u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb);
49void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 47void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
50 int family); 48 int family);
51void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, 49void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
@@ -62,6 +60,14 @@ static inline void selinux_netlbl_cache_invalidate(void)
62 return; 60 return;
63} 61}
64 62
63static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
64 u32 base_sid,
65 u32 *sid)
66{
67 *sid = SECSID_NULL;
68 return 0;
69}
70
65static inline int selinux_netlbl_socket_post_create(struct socket *sock) 71static inline int selinux_netlbl_socket_post_create(struct socket *sock)
66{ 72{
67 return 0; 73 return 0;
@@ -73,12 +79,6 @@ static inline void selinux_netlbl_sock_graft(struct sock *sk,
73 return; 79 return;
74} 80}
75 81
76static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb,
77 u32 sock_sid)
78{
79 return SECSID_NULL;
80}
81
82static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 82static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
83 struct sk_buff *skb, 83 struct sk_buff *skb,
84 struct avc_audit_data *ad) 84 struct avc_audit_data *ad)
@@ -86,16 +86,6 @@ static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
86 return 0; 86 return 0;
87} 87}
88 88
89static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
90{
91 return SECSID_NULL;
92}
93
94static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
95{
96 return SECSID_NULL;
97}
98
99static inline void selinux_netlbl_sk_security_reset( 89static inline void selinux_netlbl_sk_security_reset(
100 struct sk_security_struct *ssec, 90 struct sk_security_struct *ssec,
101 int family) 91 int family)
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index ebd7246a4be5..161eb571c82d 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -36,7 +36,6 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
36 struct avc_audit_data *ad); 36 struct avc_audit_data *ad);
37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
38 struct avc_audit_data *ad, u8 proto); 38 struct avc_audit_data *ad, u8 proto);
39u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
40int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 39int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
41#else 40#else
42static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 41static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
@@ -51,10 +50,6 @@ static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
51 return 0; 50 return 0;
52} 51}
53 52
54static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
55{
56 return SECSID_NULL;
57}
58static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 53static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
59{ 54{
60 *sid = SECSID_NULL; 55 *sid = SECSID_NULL;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b66b454fe72b..b43dd803fd5e 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -54,6 +54,7 @@
54#include "mls.h" 54#include "mls.h"
55#include "objsec.h" 55#include "objsec.h"
56#include "selinux_netlabel.h" 56#include "selinux_netlabel.h"
57#include "xfrm.h"
57 58
58extern void selnl_notify_policyload(u32 seqno); 59extern void selnl_notify_policyload(u32 seqno);
59unsigned int policydb_loaded_version; 60unsigned int policydb_loaded_version;
@@ -2191,6 +2192,32 @@ void selinux_audit_set_callback(int (*callback)(void))
2191 aurule_callback = callback; 2192 aurule_callback = callback;
2192} 2193}
2193 2194
2195/**
2196 * security_skb_extlbl_sid - Determine the external label of a packet
2197 * @skb: the packet
2198 * @base_sid: the SELinux SID to use as a context for MLS only external labels
2199 * @sid: the packet's SID
2200 *
2201 * Description:
2202 * Check the various different forms of external packet labeling and determine
2203 * the external SID for the packet.
2204 *
2205 */
2206void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2207{
2208 u32 xfrm_sid;
2209 u32 nlbl_sid;
2210
2211 selinux_skb_xfrm_sid(skb, &xfrm_sid);
2212 if (selinux_netlbl_skbuff_getsid(skb,
2213 (xfrm_sid == SECSID_NULL ?
2214 base_sid : xfrm_sid),
2215 &nlbl_sid) != 0)
2216 nlbl_sid = SECSID_NULL;
2217
2218 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
2219}
2220
2194#ifdef CONFIG_NETLABEL 2221#ifdef CONFIG_NETLABEL
2195/* 2222/*
2196 * This is the structure we store inside the NetLabel cache block. 2223 * This is the structure we store inside the NetLabel cache block.
@@ -2408,9 +2435,7 @@ netlbl_secattr_to_sid_return_cleanup:
2408 * assign to the packet. Returns zero on success, negative values on failure. 2435 * assign to the packet. Returns zero on success, negative values on failure.
2409 * 2436 *
2410 */ 2437 */
2411static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 2438int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2412 u32 base_sid,
2413 u32 *sid)
2414{ 2439{
2415 int rc; 2440 int rc;
2416 struct netlbl_lsm_secattr secattr; 2441 struct netlbl_lsm_secattr secattr;
@@ -2616,29 +2641,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2616} 2641}
2617 2642
2618/** 2643/**
2619 * selinux_netlbl_inet_conn_request - Handle a new connection request
2620 * @skb: the packet
2621 * @sock_sid: the SID of the parent socket
2622 *
2623 * Description:
2624 * If present, use the security attributes of the packet in @skb and the
2625 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2626 * SID of the connection or SECSID_NULL on failure.
2627 *
2628 */
2629u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2630{
2631 int rc;
2632 u32 peer_sid;
2633
2634 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2635 if (rc != 0)
2636 return SECSID_NULL;
2637
2638 return peer_sid;
2639}
2640
2641/**
2642 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled 2644 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
2643 * @inode: the file descriptor's inode 2645 * @inode: the file descriptor's inode
2644 * @mask: the permission mask 2646 * @mask: the permission mask
@@ -2728,42 +2730,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2728} 2730}
2729 2731
2730/** 2732/**
2731 * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
2732 * @sock: the socket
2733 *
2734 * Description:
2735 * Examine @sock to find the connected peer's SID. Returns the SID on success
2736 * or SECSID_NULL on error.
2737 *
2738 */
2739u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2740{
2741 struct sk_security_struct *sksec = sock->sk->sk_security;
2742 return sksec->peer_sid;
2743}
2744
2745/**
2746 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2747 * @skb: the packet
2748 *
2749 * Description:
2750 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2751 * success, SECSID_NULL on error.
2752 *
2753 */
2754u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2755{
2756 int peer_sid;
2757
2758 if (selinux_netlbl_skbuff_getsid(skb,
2759 SECINITSID_UNLABELED,
2760 &peer_sid) != 0)
2761 return SECSID_NULL;
2762
2763 return peer_sid;
2764}
2765
2766/**
2767 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 2733 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2768 * @sock: the socket 2734 * @sock: the socket
2769 * @level: the socket level or protocol 2735 * @level: the socket level or protocol
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 9b777140068f..bd8d1ef40a90 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -372,39 +372,6 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
372 kfree(ctx); 372 kfree(ctx);
373} 373}
374 374
375/*
376 * SELinux internal function to retrieve the context of a UDP packet
377 * based on its security association.
378 *
379 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
380 * type SCM_SECURITY.
381 */
382u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
383{
384 struct sec_path *sp;
385
386 if (skb == NULL)
387 return SECSID_NULL;
388
389 if (skb->sk->sk_protocol != IPPROTO_UDP)
390 return SECSID_NULL;
391
392 sp = skb->sp;
393 if (sp) {
394 int i;
395
396 for (i = sp->len-1; i >= 0; i--) {
397 struct xfrm_state *x = sp->xvec[i];
398 if (selinux_authorizable_xfrm(x)) {
399 struct xfrm_sec_ctx *ctx = x->security;
400 return ctx->ctx_sid;
401 }
402 }
403 }
404
405 return SECSID_NULL;
406}
407
408 /* 375 /*
409 * LSM hook implementation that authorizes deletion of labeled SAs. 376 * LSM hook implementation that authorizes deletion of labeled SAs.
410 */ 377 */