Skip to content

Commit e53642b

Browse files
committed
Merge tag 'v6.18-rc3-smb-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Improve check for malformed payload - Fix free transport smbdirect potential race - Fix potential race in credit allocation during smbdirect negotiation * tag 'v6.18-rc3-smb-server-fixes' of git://git.samba.org/ksmbd: smb: server: let smb_direct_cm_handler() call ib_drain_qp() after smb_direct_disconnect_rdma_work() smb: server: call smb_direct_post_recv_credits() when the negotiation is done ksmbd: transport_ipc: validate payload size before reading handle
2 parents 8eefed8 + f574069 commit e53642b

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

fs/smb/server/transport_ipc.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,16 @@ static void ipc_msg_handle_free(int handle)
263263

264264
static int handle_response(int type, void *payload, size_t sz)
265265
{
266-
unsigned int handle = *(unsigned int *)payload;
266+
unsigned int handle;
267267
struct ipc_msg_table_entry *entry;
268268
int ret = 0;
269269

270+
/* Prevent 4-byte read beyond declared payload size */
271+
if (sz < sizeof(unsigned int))
272+
return -EINVAL;
273+
274+
handle = *(unsigned int *)payload;
275+
270276
ipc_update_last_active();
271277
down_read(&ipc_msg_table_lock);
272278
hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) {

fs/smb/server/transport_rdma.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,9 +418,6 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
418418

419419
sc->ib.dev = sc->rdma.cm_id->device;
420420

421-
INIT_WORK(&sc->recv_io.posted.refill_work,
422-
smb_direct_post_recv_credits);
423-
INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work);
424421
INIT_DELAYED_WORK(&sc->idle.timer_work, smb_direct_idle_connection_timer);
425422

426423
conn = ksmbd_conn_alloc();
@@ -469,6 +466,9 @@ static void free_transport(struct smb_direct_transport *t)
469466
disable_delayed_work_sync(&sc->idle.timer_work);
470467
disable_work_sync(&sc->idle.immediate_work);
471468

469+
if (sc->rdma.cm_id)
470+
rdma_lock_handler(sc->rdma.cm_id);
471+
472472
if (sc->ib.qp) {
473473
ib_drain_qp(sc->ib.qp);
474474
sc->ib.qp = NULL;
@@ -497,8 +497,10 @@ static void free_transport(struct smb_direct_transport *t)
497497
ib_free_cq(sc->ib.recv_cq);
498498
if (sc->ib.pd)
499499
ib_dealloc_pd(sc->ib.pd);
500-
if (sc->rdma.cm_id)
500+
if (sc->rdma.cm_id) {
501+
rdma_unlock_handler(sc->rdma.cm_id);
501502
rdma_destroy_id(sc->rdma.cm_id);
503+
}
502504

503505
smb_direct_destroy_pools(sc);
504506
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
@@ -1727,10 +1729,10 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
17271729
}
17281730
case RDMA_CM_EVENT_DEVICE_REMOVAL:
17291731
case RDMA_CM_EVENT_DISCONNECTED: {
1730-
ib_drain_qp(sc->ib.qp);
1731-
17321732
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
17331733
smb_direct_disconnect_rdma_work(&sc->disconnect_work);
1734+
if (sc->ib.qp)
1735+
ib_drain_qp(sc->ib.qp);
17341736
break;
17351737
}
17361738
case RDMA_CM_EVENT_CONNECT_ERROR: {
@@ -1904,7 +1906,6 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
19041906
goto out_err;
19051907
}
19061908

1907-
smb_direct_post_recv_credits(&sc->recv_io.posted.refill_work);
19081909
return 0;
19091910
out_err:
19101911
put_recvmsg(sc, recvmsg);
@@ -2249,8 +2250,8 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
22492250
return -ECONNABORTED;
22502251

22512252
ret = smb_direct_check_recvmsg(recvmsg);
2252-
if (ret == -ECONNABORTED)
2253-
goto out;
2253+
if (ret)
2254+
goto put;
22542255

22552256
req = (struct smbdirect_negotiate_req *)recvmsg->packet;
22562257
sp->max_recv_size = min_t(int, sp->max_recv_size,
@@ -2265,14 +2266,38 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
22652266
sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max);
22662267
sc->recv_io.credits.target = max_t(u16, sc->recv_io.credits.target, 1);
22672268

2268-
ret = smb_direct_send_negotiate_response(sc, ret);
2269-
out:
2269+
put:
22702270
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
22712271
sc->recv_io.reassembly.queue_length--;
22722272
list_del(&recvmsg->list);
22732273
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
22742274
put_recvmsg(sc, recvmsg);
22752275

2276+
if (ret == -ECONNABORTED)
2277+
return ret;
2278+
2279+
if (ret)
2280+
goto respond;
2281+
2282+
/*
2283+
* We negotiated with success, so we need to refill the recv queue.
2284+
* We do that with sc->idle.immediate_work still being disabled
2285+
* via smbdirect_socket_init(), so that queue_work(sc->workqueue,
2286+
* &sc->idle.immediate_work) in smb_direct_post_recv_credits()
2287+
* is a no-op.
2288+
*
2289+
* The message that grants the credits to the client is
2290+
* the negotiate response.
2291+
*/
2292+
INIT_WORK(&sc->recv_io.posted.refill_work, smb_direct_post_recv_credits);
2293+
smb_direct_post_recv_credits(&sc->recv_io.posted.refill_work);
2294+
if (unlikely(sc->first_error))
2295+
return sc->first_error;
2296+
INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work);
2297+
2298+
respond:
2299+
ret = smb_direct_send_negotiate_response(sc, ret);
2300+
22762301
return ret;
22772302
}
22782303

0 commit comments

Comments
 (0)