summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-01-05 15:38:53 -0800
committerDavid S. Miller <davem@davemloft.net>2011-01-05 15:38:53 -0800
commit3610cda53f247e176bcbb7a7cca64bc53b12acdb (patch)
treed780bc1e405116e75a194b2f4693a6f9bbe9f58f /security
parent44b8288308ac9da27eab7d7bdbf1375a568805c3 (diff)
downloadlinux-3610cda53f247e176bcbb7a7cca64bc53b12acdb.tar.gz
linux-3610cda53f247e176bcbb7a7cca64bc53b12acdb.tar.bz2
linux-3610cda53f247e176bcbb7a7cca64bc53b12acdb.zip
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 <jeremy@goop.org> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'security')
-rw-r--r--security/capability.c2
-rw-r--r--security/security.c3
-rw-r--r--security/selinux/hooks.c10
-rw-r--r--security/smack/smack_lsm.c14
4 files changed, 14 insertions, 15 deletions
diff --git a/security/capability.c b/security/capability.c
index c773635ca3a0..2a5df2b7da83 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 1b798d3df710..e5fb07a3052d 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 c82538a4b1a4..6f637d2678ac 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 489a85afa477..ccb71a044a1a 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);
}