From 1f1aaf82825865a50cef0b4722607abb12aeee52 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 16 Nov 2010 11:52:57 +0000 Subject: SELinux: return -ECONNREFUSED from ip_postroute to signal fatal error The SELinux netfilter hooks just return NF_DROP if they drop a packet. We want to signal that a drop in this hook is a permanant fatal error and is not transient. If we do this the error will be passed back up the stack in some places and applications will get a faster interaction that something went wrong. Signed-off-by: Eric Paris Signed-off-by: David S. Miller --- security/selinux/hooks.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d9154cf90ae..2c145f12d99 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4585,11 +4585,11 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, secmark_perm = PACKET__SEND; break; default: - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); } if (secmark_perm == PACKET__FORWARD_OUT) { if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); } else peer_sid = SECINITSID_KERNEL; } else { @@ -4602,28 +4602,28 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (secmark_active) if (avc_has_perm(peer_sid, skb->secmark, SECCLASS_PACKET, secmark_perm, &ad)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (peerlbl_active) { u32 if_sid; u32 node_sid; if (sel_netif_sid(ifindex, &if_sid)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (avc_has_perm(peer_sid, if_sid, SECCLASS_NETIF, NETIF__EGRESS, &ad)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (sel_netnode_sid(addrp, family, &node_sid)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (avc_has_perm(peer_sid, node_sid, SECCLASS_NODE, NODE__SENDTO, &ad)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); } return NF_ACCEPT; -- cgit v1.2.3 From 04f6d70f6e64900a5d70a5fc199dd9d5fa787738 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 23 Nov 2010 06:28:02 +0000 Subject: SELinux: Only return netlink error when we know the return is fatal Some of the SELinux netlink code returns a fatal error when the error might actually be transient. This patch just silently drops packets on potentially transient errors but continues to return a permanant error indicator when the denial was because of policy. Based-on-comments-by: Paul Moore Signed-off-by: Eric Paris Reviewed-by: Paul Moore Signed-off-by: David S. Miller --- security/selinux/hooks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2c145f12d99..f590fb8e914 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4589,7 +4589,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, } if (secmark_perm == PACKET__FORWARD_OUT) { if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) - return NF_DROP_ERR(-ECONNREFUSED); + return NF_DROP; } else peer_sid = SECINITSID_KERNEL; } else { @@ -4602,7 +4602,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) - return NF_DROP_ERR(-ECONNREFUSED); + return NF_DROP; if (secmark_active) if (avc_has_perm(peer_sid, skb->secmark, @@ -4614,13 +4614,13 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, u32 node_sid; if (sel_netif_sid(ifindex, &if_sid)) - return NF_DROP_ERR(-ECONNREFUSED); + return NF_DROP; if (avc_has_perm(peer_sid, if_sid, SECCLASS_NETIF, NETIF__EGRESS, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (sel_netnode_sid(addrp, family, &node_sid)) - return NF_DROP_ERR(-ECONNREFUSED); + return NF_DROP; if (avc_has_perm(peer_sid, node_sid, SECCLASS_NODE, NODE__SENDTO, &ad)) return NF_DROP_ERR(-ECONNREFUSED); -- cgit v1.2.3 From 2fe66ec242d3f76e3b0101f36419e7e5405bcff3 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 23 Nov 2010 06:28:08 +0000 Subject: SELinux: indicate fatal error in compat netfilter code The SELinux ip postroute code indicates when policy rejected a packet and passes the error back up the stack. The compat code does not. This patch sends the same kind of error back up the stack in the compat code. Based-on-patch-by: Paul Moore Signed-off-by: Eric Paris Reviewed-by: Paul Moore Signed-off-by: David S. Miller --- security/selinux/hooks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f590fb8e914..156ef93d6f7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4524,11 +4524,11 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, if (selinux_secmark_enabled()) if (avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); if (selinux_policycap_netpeer) if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) - return NF_DROP; + return NF_DROP_ERR(-ECONNREFUSED); return NF_ACCEPT; } -- cgit v1.2.3 From 3610cda53f247e176bcbb7a7cca64bc53b12acdb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 5 Jan 2011 15:38:53 -0800 Subject: af_unix: Avoid socket->sk NULL OOPS in stream connect security hooks. unix_release() can asynchornously set socket->sk to NULL, and it does so without holding the unix_state_lock() on "other" during stream connects. However, the reverse mapping, sk->sk_socket, is only transitioned to NULL under the unix_state_lock(). Therefore make the security hooks follow the reverse mapping instead of the forward mapping. Reported-by: Jeremy Fitzhardinge Reported-by: Linus Torvalds Signed-off-by: David S. Miller --- security/capability.c | 2 +- security/security.c | 3 +-- security/selinux/hooks.c | 10 +++++----- security/smack/smack_lsm.c | 14 +++++++------- 4 files changed, 14 insertions(+), 15 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index c773635ca3a..2a5df2b7da8 100644 --- a/security/capability.c +++ b/security/capability.c @@ -548,7 +548,7 @@ static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops, } #ifdef CONFIG_SECURITY_NETWORK -static int cap_unix_stream_connect(struct socket *sock, struct socket *other, +static int cap_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { return 0; diff --git a/security/security.c b/security/security.c index 1b798d3df71..e5fb07a3052 100644 --- a/security/security.c +++ b/security/security.c @@ -977,8 +977,7 @@ EXPORT_SYMBOL(security_inode_getsecctx); #ifdef CONFIG_SECURITY_NETWORK -int security_unix_stream_connect(struct socket *sock, struct socket *other, - struct sock *newsk) +int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { return security_ops->unix_stream_connect(sock, other, newsk); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c82538a4b1a..6f637d2678a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3921,18 +3921,18 @@ static int selinux_socket_shutdown(struct socket *sock, int how) return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); } -static int selinux_socket_unix_stream_connect(struct socket *sock, - struct socket *other, +static int selinux_socket_unix_stream_connect(struct sock *sock, + struct sock *other, struct sock *newsk) { - struct sk_security_struct *sksec_sock = sock->sk->sk_security; - struct sk_security_struct *sksec_other = other->sk->sk_security; + struct sk_security_struct *sksec_sock = sock->sk_security; + struct sk_security_struct *sksec_other = other->sk_security; struct sk_security_struct *sksec_new = newsk->sk_security; struct common_audit_data ad; int err; COMMON_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.sk = other->sk; + ad.u.net.sk = other; err = avc_has_perm(sksec_sock->sid, sksec_other->sid, sksec_other->sclass, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 489a85afa47..ccb71a044a1 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2408,22 +2408,22 @@ static int smack_setprocattr(struct task_struct *p, char *name, /** * smack_unix_stream_connect - Smack access on UDS - * @sock: one socket - * @other: the other socket + * @sock: one sock + * @other: the other sock * @newsk: unused * * Return 0 if a subject with the smack of sock could access * an object with the smack of other, otherwise an error code */ -static int smack_unix_stream_connect(struct socket *sock, - struct socket *other, struct sock *newsk) +static int smack_unix_stream_connect(struct sock *sock, + struct sock *other, struct sock *newsk) { - struct inode *sp = SOCK_INODE(sock); - struct inode *op = SOCK_INODE(other); + struct inode *sp = SOCK_INODE(sock->sk_socket); + struct inode *op = SOCK_INODE(other->sk_socket); struct smk_audit_info ad; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); - smk_ad_setfield_u_net_sk(&ad, other->sk); + smk_ad_setfield_u_net_sk(&ad, other); return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE, &ad); } -- cgit v1.2.3