netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jason Baron <jbaron@akamai.com>
To: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Cc: Dmitry Vyukov <dvyukov@google.com>,
	syzkaller <syzkaller@googlegroups.com>,
	Michal Kubecek <mkubecek@suse.cz>,
	Al Viro <viro@zeniv.linux.org.uk>,
	"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	David Miller <davem@davemloft.net>,
	Hannes Frederic Sowa <hannes@stressinduktion.org>,
	David Howells <dhowells@redhat.com>,
	Paul Moore <paul@paul-moore.com>,
	salyzyn@android.com, sds@tycho.nsa.gov, ying.xue@windriver.com,
	netdev <netdev@vger.kernel.org>,
	Kostya Serebryany <kcc@google.com>,
	Alexander Potapenko <glider@google.com>,
	Andrey Konovalov <andreyknvl@google.com>,
	Sasha Levin <sasha.levin@oracle.com>,
	Julien Tinnes <jln@google.com>, Kees Cook <keescook@google.com>,
	Mathias Krause <minipli@googlemail.com>
Subject: Re: [PATCH] unix: avoid use-after-free in ep_remove_wait_queue
Date: Wed, 11 Nov 2015 12:35:37 -0500	[thread overview]
Message-ID: <56437C69.6090009@akamai.com> (raw)
In-Reply-To: <877flp34fl.fsf@doppelsaurus.mobileactivedefense.com>

Hi Rainer,

> +
> +/* Needs sk unix state lock. After recv_ready indicated not ready,
> + * establish peer_wait connection if still needed.
> + */
> +static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
> +{
> +	int connected;
> +
> +	connected = unix_dgram_peer_wake_connect(sk, other);
> +
> +	if (unix_recvq_full(other))
> +		return 1;
> +
> +	if (connected)
> +		unix_dgram_peer_wake_disconnect(sk, other);
> +
> +	return 0;
> +}
> +

So the comment above this function says 'needs unix state lock', however
the usage in unix_dgram_sendmsg() has the 'other' lock, while the usage
in unix_dgram_poll() has the 'sk' lock. So this looks racy.

Also, another tweak on this scheme: Instead of calling
'__remove_wait_queue()' in unix_dgram_peer_wake_relay(). We could
instead simply mark each item in the queue as 'WQ_FLAG_EXCLUSIVE'. Then,
since 'unix_dgram_recvmsg()' does an exclusive wakeup the queue has
effectively been disabled (minus the first exlusive item in the list
which can just return if its marked exclusive). This means that in
dgram_poll(), we add to the list if we have not yet been added, and if
we are on the list, we do a remove and then add removing the exclusive
flag. Thus, all the waiters that need a wakeup are at the beginning of
the queue, and the disabled ones are at the end with the
'WQ_FLAG_EXCLUSIVE' flag set.

This does make the list potentially long, but if we only walk it to the
point we are doing the wakeup, it has no impact. I like the fact that in
this scheme the wakeup doesn't have to call remove against a long of
waiters - its just setting the exclusive flag.

Thanks,

-Jason





>  static inline int unix_writable(struct sock *sk)
>  {
>  	return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
> @@ -430,6 +546,8 @@ static void unix_release_sock(struct sock *sk, int embrion)
>  			skpair->sk_state_change(skpair);
>  			sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
>  		}
> +
> +		unix_dgram_peer_wake_disconnect(sk, skpair);
>  		sock_put(skpair); /* It may now die */
>  		unix_peer(sk) = NULL;
>  	}
> @@ -664,6 +782,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
>  	INIT_LIST_HEAD(&u->link);
>  	mutex_init(&u->readlock); /* single task reading lock */
>  	init_waitqueue_head(&u->peer_wait);
> +	init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
>  	unix_insert_socket(unix_sockets_unbound(sk), sk);
>  out:
>  	if (sk == NULL)
> @@ -1031,6 +1150,13 @@ restart:
>  	if (unix_peer(sk)) {
>  		struct sock *old_peer = unix_peer(sk);
>  		unix_peer(sk) = other;
> +
> +		if (unix_dgram_peer_wake_disconnect(sk, other))
> +			wake_up_interruptible_poll(sk_sleep(sk),
> +						   POLLOUT |
> +						   POLLWRNORM |
> +						   POLLWRBAND);
> +
>  		unix_state_double_unlock(sk, other);
>  
>  		if (other != old_peer)
> @@ -1565,6 +1691,13 @@ restart:
>  		unix_state_lock(sk);
>  		if (unix_peer(sk) == other) {
>  			unix_peer(sk) = NULL;
> +
> +			if (unix_dgram_peer_wake_disconnect(sk, other))
> +				wake_up_interruptible_poll(sk_sleep(sk),
> +							   POLLOUT |
> +							   POLLWRNORM |
> +							   POLLWRBAND);
> +
>  			unix_state_unlock(sk);
>  
>  			unix_dgram_disconnected(sk, other);
> @@ -1590,19 +1723,21 @@ restart:
>  			goto out_unlock;
>  	}
>  
> -	if (unix_peer(other) != sk && unix_recvq_full(other)) {
> -		if (!timeo) {
> -			err = -EAGAIN;
> -			goto out_unlock;
> -		}
> +	if (!unix_dgram_peer_recv_ready(sk, other)) {
> +		if (timeo) {
> +			timeo = unix_wait_for_peer(other, timeo);
>  
> -		timeo = unix_wait_for_peer(other, timeo);
> +			err = sock_intr_errno(timeo);
> +			if (signal_pending(current))
> +				goto out_free;
>  
> -		err = sock_intr_errno(timeo);
> -		if (signal_pending(current))
> -			goto out_free;
> +			goto restart;
> +		}
>  
> -		goto restart;
> +		if (unix_dgram_peer_wake_me(sk, other)) {
> +			err = -EAGAIN;
> +			goto out_unlock;
> +		}
>  	}
>  
>  	if (sock_flag(other, SOCK_RCVTSTAMP))
> @@ -2453,14 +2588,16 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
>  		return mask;
>  
>  	writable = unix_writable(sk);
> -	other = unix_peer_get(sk);
> -	if (other) {
> -		if (unix_peer(other) != sk) {
> -			sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
> -			if (unix_recvq_full(other))
> -				writable = 0;
> -		}
> -		sock_put(other);
> +	if (writable) {
> +		unix_state_lock(sk);
> +
> +		other = unix_peer(sk);
> +		if (other &&
> +		    !unix_dgram_peer_recv_ready(sk, other) &&
> +		    unix_dgram_peer_wake_me(sk, other))
> +			writable = 0;
> +
> +		unix_state_unlock(sk);
>  	}
>  
>  	if (writable)
> 

  parent reply	other threads:[~2015-11-11 17:35 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-12 11:07 Use-after-free in ep_remove_wait_queue Dmitry Vyukov
2015-10-12 12:02 ` Michal Kubecek
2015-10-12 12:14   ` Eric Dumazet
2015-10-12 12:17     ` Dmitry Vyukov
2015-11-06 13:06       ` Dmitry Vyukov
2015-11-06 14:58         ` Jason Baron
2015-11-06 15:15           ` Rainer Weikusat
2015-11-09 14:40             ` [PATCH] unix: avoid use-after-free " Rainer Weikusat
2015-11-09 18:25               ` David Miller
2015-11-10 17:16                 ` Rainer Weikusat
2015-11-09 22:44               ` Jason Baron
2015-11-10 17:38                 ` Rainer Weikusat
2015-11-22 21:43                   ` alternate queueing mechanism (was: [PATCH] unix: avoid use-after-free in ep_remove_wait_queue) Rainer Weikusat
2015-11-10 21:55               ` [PATCH] unix: avoid use-after-free in ep_remove_wait_queue Rainer Weikusat
2015-11-11 12:28                 ` Hannes Frederic Sowa
2015-11-11 16:12                   ` Rainer Weikusat
2015-11-11 18:52                     ` Hannes Frederic Sowa
2015-11-13 19:06                       ` Rainer Weikusat
2015-11-11 17:35                 ` Jason Baron [this message]
2015-11-12 19:11                   ` Rainer Weikusat
2015-11-13 18:51                 ` Rainer Weikusat
2015-11-13 22:17                   ` Jason Baron
2015-11-15 18:32                     ` Rainer Weikusat
2015-11-17 16:08                       ` Jason Baron
2015-11-17 18:38                         ` Rainer Weikusat
2015-11-16 22:15                   ` Rainer Weikusat
2015-11-16 22:28                     ` [PATCH] unix: avoid use-after-free in ep_remove_wait_queue (w/ Fixes:) Rainer Weikusat
2015-11-17 16:13                       ` Jason Baron
2015-11-17 20:14                       ` David Miller
2015-11-17 21:37                         ` Rainer Weikusat
2015-11-17 22:09                           ` Rainer Weikusat
2015-11-19 23:48                             ` Rainer Weikusat
2015-11-17 22:48                           ` Rainer Weikusat
2015-11-18 18:15                         ` Rainer Weikusat
2015-11-18 23:39                           ` more statistics (was: [PATCH] unix: avoid use-after-free in ep_remove_wait_queue (w/ Fixes:)) Rainer Weikusat
2015-11-19 23:52                       ` [PATCH] unix: avoid use-after-free in ep_remove_wait_queue (w/ Fixes:) Rainer Weikusat
2015-11-20 16:03                         ` Jason Baron
2015-11-20 16:21                           ` Rainer Weikusat
2015-11-20 22:07                         ` [PATCH] unix: avoid use-after-free in ep_remove_wait_queue Rainer Weikusat
2015-11-23 16:21                           ` Jason Baron
2015-11-23 17:30                           ` David Miller
2015-11-23 21:37                             ` Rainer Weikusat
2015-11-23 23:06                               ` Rainer Weikusat

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56437C69.6090009@akamai.com \
    --to=jbaron@akamai.com \
    --cc=andreyknvl@google.com \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=dvyukov@google.com \
    --cc=glider@google.com \
    --cc=hannes@stressinduktion.org \
    --cc=jln@google.com \
    --cc=kcc@google.com \
    --cc=keescook@google.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=minipli@googlemail.com \
    --cc=mkubecek@suse.cz \
    --cc=netdev@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=rweikusat@mobileactivedefense.com \
    --cc=salyzyn@android.com \
    --cc=sasha.levin@oracle.com \
    --cc=sds@tycho.nsa.gov \
    --cc=syzkaller@googlegroups.com \
    --cc=viro@zeniv.linux.org.uk \
    --cc=ying.xue@windriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).