diff options
author | Paul Moore <paul.moore@hp.com> | 2006-11-17 17:38:54 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:24:14 -0500 |
commit | 3de4bab5b9f8848a0c16a4b1ffe0452f0d670237 (patch) | |
tree | f65c12b53bf2ad02645ea31522f67e7318019498 | |
parent | 9f2ad66509b182b399a5b03de487f45bde623524 (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.c | 43 | ||||
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/include/selinux_netlabel.h | 28 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 5 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 90 | ||||
-rw-r--r-- | security/selinux/xfrm.c | 33 |
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 | ||
3744 | static void selinux_req_classify_flow(const struct request_sock *req, | 3725 | static 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, | |||
80 | int security_node_sid(u16 domain, void *addr, u32 addrlen, | 81 | int security_node_sid(u16 domain, void *addr, u32 addrlen, |
81 | u32 *out_sid); | 82 | u32 *out_sid); |
82 | 83 | ||
84 | void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid); | ||
85 | |||
83 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 86 | int 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 |
40 | void selinux_netlbl_cache_invalidate(void); | 40 | void selinux_netlbl_cache_invalidate(void); |
41 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid); | ||
41 | int selinux_netlbl_socket_post_create(struct socket *sock); | 42 | int selinux_netlbl_socket_post_create(struct socket *sock); |
42 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); | 43 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); |
43 | u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid); | ||
44 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 44 | int 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); |
47 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock); | ||
48 | u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb); | ||
49 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, | 47 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, |
50 | int family); | 48 | int family); |
51 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | 49 | void 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 | ||
63 | static 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 | |||
65 | static inline int selinux_netlbl_socket_post_create(struct socket *sock) | 71 | static 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 | ||
76 | static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, | ||
77 | u32 sock_sid) | ||
78 | { | ||
79 | return SECSID_NULL; | ||
80 | } | ||
81 | |||
82 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 82 | static 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 | ||
89 | static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | ||
90 | { | ||
91 | return SECSID_NULL; | ||
92 | } | ||
93 | |||
94 | static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | ||
95 | { | ||
96 | return SECSID_NULL; | ||
97 | } | ||
98 | |||
99 | static inline void selinux_netlbl_sk_security_reset( | 89 | static 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); |
37 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 37 | int 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); |
39 | u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); | ||
40 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 39 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
41 | #else | 40 | #else |
42 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 41 | static 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 | ||
54 | static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb) | ||
55 | { | ||
56 | return SECSID_NULL; | ||
57 | } | ||
58 | static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | 53 | static 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 | ||
58 | extern void selnl_notify_policyload(u32 seqno); | 59 | extern void selnl_notify_policyload(u32 seqno); |
59 | unsigned int policydb_loaded_version; | 60 | unsigned 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 | */ | ||
2206 | void 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 | */ |
2411 | static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 2438 | int 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 | */ | ||
2629 | u32 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 | */ | ||
2739 | u32 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 | */ | ||
2754 | u32 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 | */ | ||
382 | u32 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 | */ |