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

Commit da8ded40 authored by Tariq Saeed's avatar Tariq Saeed Committed by Linus Torvalds
Browse files

ocfs2/o2net: o2net_listen_data_ready should do nothing if socket state is not TCP_LISTEN



Orabug: 17330860

When accepting an incomming connection o2net_accept_one clones a child
data socket from the parent listening socket.  It then proceeds to setup
the child with callback o2net_data_ready() and sk_user_data to NULL.  If
data arrives in this window, o2net_listen_data_ready will be called with
some non-deterministic value in sk_user_data (not inherited).  We panic
when we page fault on sk_user_data -- in parent it is
sock_def_readable().

The fix is to recognize that this is a data socket being set up by
looking at the socket state and do nothing.

Signed-off-by: default avatarTariq Saseed <tariq.x.saeed@oracle.com>
Signed-off-by: default avatarSrinivas Eeda <srinivas.eeda@oracle.com>
Reviewed-by: default avatarMark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent db66c715
Loading
Loading
Loading
Loading
+17 −5
Original line number Original line Diff line number Diff line
@@ -1964,17 +1964,29 @@ static void o2net_listen_data_ready(struct sock *sk, int bytes)
		goto out;
		goto out;
	}
	}


	/* ->sk_data_ready is also called for a newly established child socket
	/* This callback may called twice when a new connection
	 * before it has been accepted and the acceptor has set up their
	 * is  being established as a child socket inherits everything
	 * data_ready.. we only want to queue listen work for our listening
	 * from a parent LISTEN socket, including the data_ready cb of
	 * socket */
	 * the parent. This leads to a hazard. In o2net_accept_one()
	 * we are still initializing the child socket but have not
	 * changed the inherited data_ready callback yet when
	 * data starts arriving.
	 * We avoid this hazard by checking the state.
	 * For the listening socket,  the state will be TCP_LISTEN; for the new
	 * socket, will be  TCP_ESTABLISHED. Also, in this case,
	 * sk->sk_user_data is not a valid function pointer.
	 */

	if (sk->sk_state == TCP_LISTEN) {
	if (sk->sk_state == TCP_LISTEN) {
		mlog(ML_TCP, "bytes: %d\n", bytes);
		mlog(ML_TCP, "bytes: %d\n", bytes);
		queue_work(o2net_wq, &o2net_listen_work);
		queue_work(o2net_wq, &o2net_listen_work);
	} else {
		ready = NULL;
	}
	}


out:
out:
	read_unlock(&sk->sk_callback_lock);
	read_unlock(&sk->sk_callback_lock);
	if (ready != NULL)
		ready(sk, bytes);
		ready(sk, bytes);
}
}