mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
smb: server: rdma: avoid unmapping posted recv on accept failure
smb_direct_prepare_negotiation() posts a recv and then, if smb_direct_accept_client() fails, calls put_recvmsg() on the same buffer. That unmaps and recycles a buffer that is still posted on the QP., which can lead to device DMA into unmapped or reused memory. Track whether the recv was posted and only return it if it was never posted. If accept fails after a post, leave it for teardown to drain and complete safely. Signed-off-by: Joshua Rogers <linux@joshua.hu> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
committed by
Steve French
parent
e9a6fb0bcd
commit
e904d81ad1
@@ -1883,6 +1883,7 @@ static int smb_direct_accept_client(struct smbdirect_socket *sc)
|
||||
static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
|
||||
{
|
||||
struct smbdirect_recv_io *recvmsg;
|
||||
bool recv_posted = false;
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
|
||||
@@ -1899,6 +1900,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
|
||||
pr_err("Can't post recv: %d\n", ret);
|
||||
goto out_err;
|
||||
}
|
||||
recv_posted = true;
|
||||
|
||||
ret = smb_direct_accept_client(sc);
|
||||
if (ret) {
|
||||
@@ -1908,6 +1910,13 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
/*
|
||||
* If the recv was never posted, return it to the free list.
|
||||
* If it was posted, leave it alone so disconnect teardown can
|
||||
* drain the QP and complete it (flush) and the completion path
|
||||
* will unmap it exactly once.
|
||||
*/
|
||||
if (!recv_posted)
|
||||
put_recvmsg(sc, recvmsg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user