Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f662c070 authored by Allan Stephens's avatar Allan Stephens Committed by David S. Miller
Browse files

tipc: correct problems with misleading flags returned using poll()



Prevent TIPC from incorrectly setting returned flags to poll()
in the following cases:

- an unconnected socket no longer indicates that it is always readable

- an unconnected, connecting, or listening socket no longer indicates
  that it is always writable

Signed-off-by: default avatarAllan Stephens <allan.stephens@windriver.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 35997e31
Loading
Loading
Loading
Loading
+40 −21
Original line number Diff line number Diff line
@@ -429,36 +429,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
 * to handle any preventable race conditions, so TIPC will do the same ...
 *
 * TIPC sets the returned events as follows:
 * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
 *    or if a connection-oriented socket is does not have an active connection
 *    (i.e. a read operation will not block).
 * b) POLLOUT is set except when a socket's connection has been terminated
 *    (i.e. a write operation will not block).
 * c) POLLHUP is set when a socket's connection has been terminated.
 *
 * IMPORTANT: The fact that a read or write operation will not block does NOT
 * imply that the operation will succeed!
 *
 * socket state		flags set
 * ------------		---------
 * unconnected		no read flags
 *			no write flags
 *
 * connecting		POLLIN/POLLRDNORM if ACK/NACK in rx queue
 *			no write flags
 *
 * connected		POLLIN/POLLRDNORM if data in rx queue
 *			POLLOUT if port is not congested
 *
 * disconnecting	POLLIN/POLLRDNORM/POLLHUP
 *			no write flags
 *
 * listening		POLLIN if SYN in rx queue
 *			no write flags
 *
 * ready		POLLIN/POLLRDNORM if data in rx queue
 * [connectionless]	POLLOUT (since port cannot be congested)
 *
 * IMPORTANT: The fact that a read or write operation is indicated does NOT
 * imply that the operation will succeed, merely that it should be performed
 * and will not block.
 */

static unsigned int poll(struct file *file, struct socket *sock,
			 poll_table *wait)
{
	struct sock *sk = sock->sk;
	u32 mask;
	u32 mask = 0;

	poll_wait(file, sk_sleep(sk), wait);

	if (!skb_queue_empty(&sk->sk_receive_queue) ||
	    (sock->state == SS_UNCONNECTED) ||
	    (sock->state == SS_DISCONNECTING))
		mask = (POLLRDNORM | POLLIN);
	else
		mask = 0;

	if (sock->state == SS_DISCONNECTING)
		mask |= POLLHUP;
	else
	switch ((int)sock->state) {
	case SS_READY:
	case SS_CONNECTED:
		if (!tipc_sk_port(sk)->congested)
			mask |= POLLOUT;
		/* fall thru' */
	case SS_CONNECTING:
	case SS_LISTENING:
		if (!skb_queue_empty(&sk->sk_receive_queue))
			mask |= (POLLIN | POLLRDNORM);
		break;
	case SS_DISCONNECTING:
		mask = (POLLIN | POLLRDNORM | POLLHUP);
		break;
	}

	return mask;
}