Merge tag 'v6.18-rc5-smb-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

 - Fix smbdirect (RDMA) disconnect hang bug

 - Fix potential Denial of Service when connection limit exceeded

 - Fix smbdirect (RDMA) connection (potentially accessing freed memory)
   bug

* tag 'v6.18-rc5-smb-server-fixes' of git://git.samba.org/ksmbd:
  smb: server: let smb_direct_disconnect_rdma_connection() turn CREATED into DISCONNECTED
  ksmbd: close accepted socket when per-IP limit rejects connection
  smb: server: rdma: avoid unmapping posted recv on accept failure
This commit is contained in:
Linus Torvalds
2025-11-13 04:57:38 -08:00
2 changed files with 17 additions and 2 deletions
+13 -1
View File
@@ -334,6 +334,9 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
break;
case SMBDIRECT_SOCKET_CREATED:
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
break;
case SMBDIRECT_SOCKET_CONNECTED:
sc->status = SMBDIRECT_SOCKET_ERROR;
break;
@@ -1883,6 +1886,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 +1903,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,7 +1913,14 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
return 0;
out_err:
put_recvmsg(sc, recvmsg);
/*
* 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;
}
+4 -1
View File
@@ -290,8 +290,11 @@ static int ksmbd_kthread_fn(void *p)
}
}
up_read(&conn_list_lock);
if (ret == -EAGAIN)
if (ret == -EAGAIN) {
/* Per-IP limit hit: release the just-accepted socket. */
sock_release(client_sk);
continue;
}
skip_max_ip_conns_limit:
if (server_conf.max_connections &&