Re: [PATCH 1/1] vsock: fix the race conditions in multi-transport support

2 messages, 2 authors, 2021-02-01 · open the first message on its own page

Re: [PATCH 1/1] vsock: fix the race conditions in multi-transport support

From: Stefano Garzarella <sgarzare@redhat.com>
Date: 2021-02-01 08:28:33

On Sun, Jan 31, 2021 at 01:59:14PM +0300, Alexander Popov wrote:
There are multiple similar bugs implicitly introduced by the
commit c0cfa2d8a788fcf4 ("vsock: add multi-transports support") and
commit 6a2c0962105ae8ce ("vsock: prevent transport modules unloading").

The bug pattern:
[1] vsock_sock.transport pointer is copied to a local variable,
[2] lock_sock() is called,
[3] the local variable is used.
VSOCK multi-transport support introduced the race condition:
vsock_sock.transport value may change between [1] and [2].

Let's copy vsock_sock.transport pointer to local variables after
the lock_sock() call.
We can add:

Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
quoted hunk
Signed-off-by: Alexander Popov <redacted>
---
net/vmw_vsock/af_vsock.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index d10916ab4526..28edac1f9aa6 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -997,9 +997,12 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
			mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;

	} else if (sock->type == SOCK_STREAM) {
-		const struct vsock_transport *transport = vsk->transport;
+		const struct vsock_transport *transport = NULL;
I think we can avoid initializing to NULL since we assign it shortly 
after.
quoted hunk
+
		lock_sock(sk);

+		transport = vsk->transport;
+
		/* Listening sockets that have connections in their accept
		 * queue can be read.
		 */
@@ -1082,10 +1085,11 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
	err = 0;
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;

	lock_sock(sk);

+	transport = vsk->transport;
+
	err = vsock_auto_bind(vsk);
	if (err)
		goto out;
@@ -1544,10 +1548,11 @@ static int vsock_stream_setsockopt(struct 
socket *sock,
	err = 0;
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;

	lock_sock(sk);

+	transport = vsk->transport;
+
	switch (optname) {
	case SO_VM_SOCKETS_BUFFER_SIZE:
		COPY_IN(val);
@@ -1680,7 +1685,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;
	total_written = 0;
	err = 0;
@@ -1689,6 +1693,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
	lock_sock(sk);

+	transport = vsk->transport;
+
	/* Callers should not provide a destination with stream sockets. */
	if (msg->msg_namelen) {
		err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
@@ -1823,11 +1829,12 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;
	err = 0;

	lock_sock(sk);

+	transport = vsk->transport;
+
	if (!transport || sk->sk_state != TCP_ESTABLISHED) {
		/* Recvmsg is supposed to return 0 if a peer performs an
		 * orderly shutdown. Differentiate between that case and when a
-- 
2.26.2
Thanks for fixing this issues. With the small changes applied:

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>

Thanks,
Stefano

Re: [PATCH 1/1] vsock: fix the race conditions in multi-transport support

From: Alexander Popov <hidden>
Date: 2021-02-01 08:53:29

On 01.02.2021 11:26, Stefano Garzarella wrote:
On Sun, Jan 31, 2021 at 01:59:14PM +0300, Alexander Popov wrote:
quoted
There are multiple similar bugs implicitly introduced by the
commit c0cfa2d8a788fcf4 ("vsock: add multi-transports support") and
commit 6a2c0962105ae8ce ("vsock: prevent transport modules unloading").

The bug pattern:
[1] vsock_sock.transport pointer is copied to a local variable,
[2] lock_sock() is called,
[3] the local variable is used.
VSOCK multi-transport support introduced the race condition:
vsock_sock.transport value may change between [1] and [2].

Let's copy vsock_sock.transport pointer to local variables after
the lock_sock() call.
We can add:

Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
quoted
Signed-off-by: Alexander Popov <redacted>
---
net/vmw_vsock/af_vsock.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index d10916ab4526..28edac1f9aa6 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -997,9 +997,12 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
			mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;

	} else if (sock->type == SOCK_STREAM) {
-		const struct vsock_transport *transport = vsk->transport;
+		const struct vsock_transport *transport = NULL;
I think we can avoid initializing to NULL since we assign it shortly 
after.
quoted
+
		lock_sock(sk);

+		transport = vsk->transport;
+
		/* Listening sockets that have connections in their accept
		 * queue can be read.
		 */
@@ -1082,10 +1085,11 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
	err = 0;
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;

	lock_sock(sk);

+	transport = vsk->transport;
+
	err = vsock_auto_bind(vsk);
	if (err)
		goto out;
@@ -1544,10 +1548,11 @@ static int vsock_stream_setsockopt(struct 
socket *sock,
	err = 0;
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;

	lock_sock(sk);

+	transport = vsk->transport;
+
	switch (optname) {
	case SO_VM_SOCKETS_BUFFER_SIZE:
		COPY_IN(val);
@@ -1680,7 +1685,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;
	total_written = 0;
	err = 0;
@@ -1689,6 +1693,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
	lock_sock(sk);

+	transport = vsk->transport;
+
	/* Callers should not provide a destination with stream sockets. */
	if (msg->msg_namelen) {
		err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
@@ -1823,11 +1829,12 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
	sk = sock->sk;
	vsk = vsock_sk(sk);
-	transport = vsk->transport;
	err = 0;

	lock_sock(sk);

+	transport = vsk->transport;
+
	if (!transport || sk->sk_state != TCP_ESTABLISHED) {
		/* Recvmsg is supposed to return 0 if a peer performs an
		 * orderly shutdown. Differentiate between that case and when a
-- 
2.26.2
Thanks for fixing this issues. With the small changes applied:

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Hello Stefano,

Thanks for the review.

I've just sent the v2.

Best regards,
Alexander
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help