aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2013-12-12 21:27:55 -0500
committerJames Morris <james.l.morris@oracle.com>2013-12-12 21:27:55 -0500
commitd93aca6050b10cd7d8b491637c3b5344c5680cac (patch)
tree216cf72ea9fc6e7e1f995029cf5ead4a4aeb3301 /security/selinux/hooks.c
parent54fb723cc48db2fde964fb9bb0eaaccf2cf31a9f (diff)
parentc0828e50485932b7e019df377a6b0a8d1ebd3080 (diff)
Merge branch 'master' of git://git.infradead.org/users/pcmoore/selinux_fixes into for-linus
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c137
1 files changed, 112 insertions, 25 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 794c3ca49eac..bff7791bb65b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -53,6 +53,7 @@
53#include <net/ip.h> /* for local_port_range[] */ 53#include <net/ip.h> /* for local_port_range[] */
54#include <net/sock.h> 54#include <net/sock.h>
55#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 55#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
56#include <net/inet_connection_sock.h>
56#include <net/net_namespace.h> 57#include <net/net_namespace.h>
57#include <net/netlabel.h> 58#include <net/netlabel.h>
58#include <linux/uaccess.h> 59#include <linux/uaccess.h>
@@ -3828,7 +3829,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3828 u32 nlbl_sid; 3829 u32 nlbl_sid;
3829 u32 nlbl_type; 3830 u32 nlbl_type;
3830 3831
3831 err = selinux_skb_xfrm_sid(skb, &xfrm_sid); 3832 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
3832 if (unlikely(err)) 3833 if (unlikely(err))
3833 return -EACCES; 3834 return -EACCES;
3834 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); 3835 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3846,6 +3847,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3846 return 0; 3847 return 0;
3847} 3848}
3848 3849
3850/**
3851 * selinux_conn_sid - Determine the child socket label for a connection
3852 * @sk_sid: the parent socket's SID
3853 * @skb_sid: the packet's SID
3854 * @conn_sid: the resulting connection SID
3855 *
3856 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3857 * combined with the MLS information from @skb_sid in order to create
3858 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3859 * of @sk_sid. Returns zero on success, negative values on failure.
3860 *
3861 */
3862static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3863{
3864 int err = 0;
3865
3866 if (skb_sid != SECSID_NULL)
3867 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3868 else
3869 *conn_sid = sk_sid;
3870
3871 return err;
3872}
3873
3849/* socket security operations */ 3874/* socket security operations */
3850 3875
3851static int socket_sockcreate_sid(const struct task_security_struct *tsec, 3876static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -4452,7 +4477,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4452 struct sk_security_struct *sksec = sk->sk_security; 4477 struct sk_security_struct *sksec = sk->sk_security;
4453 int err; 4478 int err;
4454 u16 family = sk->sk_family; 4479 u16 family = sk->sk_family;
4455 u32 newsid; 4480 u32 connsid;
4456 u32 peersid; 4481 u32 peersid;
4457 4482
4458 /* handle mapped IPv4 packets arriving via IPv6 sockets */ 4483 /* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -4462,16 +4487,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4462 err = selinux_skb_peerlbl_sid(skb, family, &peersid); 4487 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
4463 if (err) 4488 if (err)
4464 return err; 4489 return err;
4465 if (peersid == SECSID_NULL) { 4490 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4466 req->secid = sksec->sid; 4491 if (err)
4467 req->peer_secid = SECSID_NULL; 4492 return err;
4468 } else { 4493 req->secid = connsid;
4469 err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4494 req->peer_secid = peersid;
4470 if (err)
4471 return err;
4472 req->secid = newsid;
4473 req->peer_secid = peersid;
4474 }
4475 4495
4476 return selinux_netlbl_inet_conn_request(req, family); 4496 return selinux_netlbl_inet_conn_request(req, family);
4477} 4497}
@@ -4731,6 +4751,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
4731static unsigned int selinux_ip_output(struct sk_buff *skb, 4751static unsigned int selinux_ip_output(struct sk_buff *skb,
4732 u16 family) 4752 u16 family)
4733{ 4753{
4754 struct sock *sk;
4734 u32 sid; 4755 u32 sid;
4735 4756
4736 if (!netlbl_enabled()) 4757 if (!netlbl_enabled())
@@ -4739,8 +4760,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
4739 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path 4760 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4740 * because we want to make sure we apply the necessary labeling 4761 * because we want to make sure we apply the necessary labeling
4741 * before IPsec is applied so we can leverage AH protection */ 4762 * before IPsec is applied so we can leverage AH protection */
4742 if (skb->sk) { 4763 sk = skb->sk;
4743 struct sk_security_struct *sksec = skb->sk->sk_security; 4764 if (sk) {
4765 struct sk_security_struct *sksec;
4766
4767 if (sk->sk_state == TCP_LISTEN)
4768 /* if the socket is the listening state then this
4769 * packet is a SYN-ACK packet which means it needs to
4770 * be labeled based on the connection/request_sock and
4771 * not the parent socket. unfortunately, we can't
4772 * lookup the request_sock yet as it isn't queued on
4773 * the parent socket until after the SYN-ACK is sent.
4774 * the "solution" is to simply pass the packet as-is
4775 * as any IP option based labeling should be copied
4776 * from the initial connection request (in the IP
4777 * layer). it is far from ideal, but until we get a
4778 * security label in the packet itself this is the
4779 * best we can do. */
4780 return NF_ACCEPT;
4781
4782 /* standard practice, label using the parent socket */
4783 sksec = sk->sk_security;
4744 sid = sksec->sid; 4784 sid = sksec->sid;
4745 } else 4785 } else
4746 sid = SECINITSID_KERNEL; 4786 sid = SECINITSID_KERNEL;
@@ -4810,27 +4850,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4810 * as fast and as clean as possible. */ 4850 * as fast and as clean as possible. */
4811 if (!selinux_policycap_netpeer) 4851 if (!selinux_policycap_netpeer)
4812 return selinux_ip_postroute_compat(skb, ifindex, family); 4852 return selinux_ip_postroute_compat(skb, ifindex, family);
4853
4854 secmark_active = selinux_secmark_enabled();
4855 peerlbl_active = selinux_peerlbl_enabled();
4856 if (!secmark_active && !peerlbl_active)
4857 return NF_ACCEPT;
4858
4859 sk = skb->sk;
4860
4813#ifdef CONFIG_XFRM 4861#ifdef CONFIG_XFRM
4814 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4862 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4815 * packet transformation so allow the packet to pass without any checks 4863 * packet transformation so allow the packet to pass without any checks
4816 * since we'll have another chance to perform access control checks 4864 * since we'll have another chance to perform access control checks
4817 * when the packet is on it's final way out. 4865 * when the packet is on it's final way out.
4818 * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4866 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4819 * is NULL, in this case go ahead and apply access control. */ 4867 * is NULL, in this case go ahead and apply access control.
4820 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) 4868 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4869 * TCP listening state we cannot wait until the XFRM processing
4870 * is done as we will miss out on the SA label if we do;
4871 * unfortunately, this means more work, but it is only once per
4872 * connection. */
4873 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4874 !(sk != NULL && sk->sk_state == TCP_LISTEN))
4821 return NF_ACCEPT; 4875 return NF_ACCEPT;
4822#endif 4876#endif
4823 secmark_active = selinux_secmark_enabled();
4824 peerlbl_active = selinux_peerlbl_enabled();
4825 if (!secmark_active && !peerlbl_active)
4826 return NF_ACCEPT;
4827 4877
4828 /* if the packet is being forwarded then get the peer label from the
4829 * packet itself; otherwise check to see if it is from a local
4830 * application or the kernel, if from an application get the peer label
4831 * from the sending socket, otherwise use the kernel's sid */
4832 sk = skb->sk;
4833 if (sk == NULL) { 4878 if (sk == NULL) {
4879 /* Without an associated socket the packet is either coming
4880 * from the kernel or it is being forwarded; check the packet
4881 * to determine which and if the packet is being forwarded
4882 * query the packet directly to determine the security label. */
4834 if (skb->skb_iif) { 4883 if (skb->skb_iif) {
4835 secmark_perm = PACKET__FORWARD_OUT; 4884 secmark_perm = PACKET__FORWARD_OUT;
4836 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) 4885 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4839,7 +4888,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4839 secmark_perm = PACKET__SEND; 4888 secmark_perm = PACKET__SEND;
4840 peer_sid = SECINITSID_KERNEL; 4889 peer_sid = SECINITSID_KERNEL;
4841 } 4890 }
4891 } else if (sk->sk_state == TCP_LISTEN) {
4892 /* Locally generated packet but the associated socket is in the
4893 * listening state which means this is a SYN-ACK packet. In
4894 * this particular case the correct security label is assigned
4895 * to the connection/request_sock but unfortunately we can't
4896 * query the request_sock as it isn't queued on the parent
4897 * socket until after the SYN-ACK packet is sent; the only
4898 * viable choice is to regenerate the label like we do in
4899 * selinux_inet_conn_request(). See also selinux_ip_output()
4900 * for similar problems. */
4901 u32 skb_sid;
4902 struct sk_security_struct *sksec = sk->sk_security;
4903 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4904 return NF_DROP;
4905 /* At this point, if the returned skb peerlbl is SECSID_NULL
4906 * and the packet has been through at least one XFRM
4907 * transformation then we must be dealing with the "final"
4908 * form of labeled IPsec packet; since we've already applied
4909 * all of our access controls on this packet we can safely
4910 * pass the packet. */
4911 if (skb_sid == SECSID_NULL) {
4912 switch (family) {
4913 case PF_INET:
4914 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4915 return NF_ACCEPT;
4916 break;
4917 case PF_INET6:
4918 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4919 return NF_ACCEPT;
4920 default:
4921 return NF_DROP_ERR(-ECONNREFUSED);
4922 }
4923 }
4924 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4925 return NF_DROP;
4926 secmark_perm = PACKET__SEND;
4842 } else { 4927 } else {
4928 /* Locally generated packet, fetch the security label from the
4929 * associated socket. */
4843 struct sk_security_struct *sksec = sk->sk_security; 4930 struct sk_security_struct *sksec = sk->sk_security;
4844 peer_sid = sksec->sid; 4931 peer_sid = sksec->sid;
4845 secmark_perm = PACKET__SEND; 4932 secmark_perm = PACKET__SEND;