diff options
author | David S. Miller <davem@davemloft.net> | 2011-01-06 00:38:53 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-06 00:38:53 +0100 |
commit | 3610cda53f247e176bcbb7a7cca64bc53b12acdb (patch) | |
tree | d780bc1e405116e75a194b2f4693a6f9bbe9f58f /security/selinux/hooks.c | |
parent | net_sched: pfifo_head_drop problem (diff) | |
download | linux-3610cda53f247e176bcbb7a7cca64bc53b12acdb.tar.xz 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/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 10 |
1 files changed, 5 insertions, 5 deletions
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, |