Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+43 -12
+7 -1
fs/smb/server/transport_ipc.c
··· 263 263 264 264 static int handle_response(int type, void *payload, size_t sz) 265 265 { 266 - unsigned int handle = *(unsigned int *)payload; 266 + unsigned int handle; 267 267 struct ipc_msg_table_entry *entry; 268 268 int ret = 0; 269 + 270 + /* Prevent 4-byte read beyond declared payload size */ 271 + if (sz < sizeof(unsigned int)) 272 + return -EINVAL; 273 + 274 + handle = *(unsigned int *)payload; 269 275 270 276 ipc_update_last_active(); 271 277 down_read(&ipc_msg_table_lock);
+36 -11
fs/smb/server/transport_rdma.c
··· 418 418 419 419 sc->ib.dev = sc->rdma.cm_id->device; 420 420 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); 424 421 INIT_DELAYED_WORK(&sc->idle.timer_work, smb_direct_idle_connection_timer); 425 422 426 423 conn = ksmbd_conn_alloc(); ··· 466 469 disable_delayed_work_sync(&sc->idle.timer_work); 467 470 disable_work_sync(&sc->idle.immediate_work); 468 471 472 + if (sc->rdma.cm_id) 473 + rdma_lock_handler(sc->rdma.cm_id); 474 + 469 475 if (sc->ib.qp) { 470 476 ib_drain_qp(sc->ib.qp); 471 477 sc->ib.qp = NULL; ··· 497 497 ib_free_cq(sc->ib.recv_cq); 498 498 if (sc->ib.pd) 499 499 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); 501 502 rdma_destroy_id(sc->rdma.cm_id); 503 + } 502 504 503 505 smb_direct_destroy_pools(sc); 504 506 ksmbd_conn_free(KSMBD_TRANS(t)->conn); ··· 1729 1727 } 1730 1728 case RDMA_CM_EVENT_DEVICE_REMOVAL: 1731 1729 case RDMA_CM_EVENT_DISCONNECTED: { 1732 - ib_drain_qp(sc->ib.qp); 1733 - 1734 1730 sc->status = SMBDIRECT_SOCKET_DISCONNECTED; 1735 1731 smb_direct_disconnect_rdma_work(&sc->disconnect_work); 1732 + if (sc->ib.qp) 1733 + ib_drain_qp(sc->ib.qp); 1736 1734 break; 1737 1735 } 1738 1736 case RDMA_CM_EVENT_CONNECT_ERROR: { ··· 1906 1904 goto out_err; 1907 1905 } 1908 1906 1909 - smb_direct_post_recv_credits(&sc->recv_io.posted.refill_work); 1910 1907 return 0; 1911 1908 out_err: 1912 1909 put_recvmsg(sc, recvmsg); ··· 2250 2249 return -ECONNABORTED; 2251 2250 2252 2251 ret = smb_direct_check_recvmsg(recvmsg); 2253 - if (ret == -ECONNABORTED) 2254 - goto out; 2252 + if (ret) 2253 + goto put; 2255 2254 2256 2255 req = (struct smbdirect_negotiate_req *)recvmsg->packet; 2257 2256 sp->max_recv_size = min_t(int, sp->max_recv_size, ··· 2266 2265 sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max); 2267 2266 sc->recv_io.credits.target = max_t(u16, sc->recv_io.credits.target, 1); 2268 2267 2269 - ret = smb_direct_send_negotiate_response(sc, ret); 2270 - out: 2268 + put: 2271 2269 spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); 2272 2270 sc->recv_io.reassembly.queue_length--; 2273 2271 list_del(&recvmsg->list); 2274 2272 spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); 2275 2273 put_recvmsg(sc, recvmsg); 2274 + 2275 + if (ret == -ECONNABORTED) 2276 + return ret; 2277 + 2278 + if (ret) 2279 + goto respond; 2280 + 2281 + /* 2282 + * We negotiated with success, so we need to refill the recv queue. 2283 + * We do that with sc->idle.immediate_work still being disabled 2284 + * via smbdirect_socket_init(), so that queue_work(sc->workqueue, 2285 + * &sc->idle.immediate_work) in smb_direct_post_recv_credits() 2286 + * is a no-op. 2287 + * 2288 + * The message that grants the credits to the client is 2289 + * the negotiate response. 2290 + */ 2291 + INIT_WORK(&sc->recv_io.posted.refill_work, smb_direct_post_recv_credits); 2292 + smb_direct_post_recv_credits(&sc->recv_io.posted.refill_work); 2293 + if (unlikely(sc->first_error)) 2294 + return sc->first_error; 2295 + INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work); 2296 + 2297 + respond: 2298 + ret = smb_direct_send_negotiate_response(sc, ret); 2276 2299 2277 2300 return ret; 2278 2301 }