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.17rc-part2-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

- Fix limiting repeated connections from same IP

- Fix for extracting shortname when name begins with a dot

- Four smbdirect fixes:
- three fixes to the receive path: potential unmap bug, potential
resource leaks and stale connections, and also potential use
after free race
- cleanup to remove unneeded queue

* tag 'v6.17rc-part2-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
smb: server: Fix extension string in ksmbd_extract_shortname()
ksmbd: limit repeated connections from clients with the same IP
smb: server: let recv_done() avoid touching data_transfer after cleanup/move
smb: server: let recv_done() consistently call put_recvmsg/smb_direct_disconnect_rdma_connection
smb: server: make sure we call ib_dma_unmap_single() only if we called ib_dma_map_single already
smb: server: remove separate empty_recvmsg_queue

+54 -63
+1
fs/smb/server/connection.h
··· 46 46 struct mutex srv_mutex; 47 47 int status; 48 48 unsigned int cli_cap; 49 + __be32 inet_addr; 49 50 char *request_buf; 50 51 struct ksmbd_transport *transport; 51 52 struct nls_table *local_nls;
+1 -1
fs/smb/server/smb_common.c
··· 515 515 516 516 p = strrchr(longname, '.'); 517 517 if (p == longname) { /*name starts with a dot*/ 518 - strscpy(extension, "___", strlen("___")); 518 + strscpy(extension, "___", sizeof(extension)); 519 519 } else { 520 520 if (p) { 521 521 p++;
+35 -62
fs/smb/server/transport_rdma.c
··· 129 129 spinlock_t recvmsg_queue_lock; 130 130 struct list_head recvmsg_queue; 131 131 132 - spinlock_t empty_recvmsg_queue_lock; 133 - struct list_head empty_recvmsg_queue; 134 - 135 132 int send_credit_target; 136 133 atomic_t send_credits; 137 134 spinlock_t lock_new_recv_credits; ··· 265 268 static void put_recvmsg(struct smb_direct_transport *t, 266 269 struct smb_direct_recvmsg *recvmsg) 267 270 { 268 - ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, 269 - recvmsg->sge.length, DMA_FROM_DEVICE); 271 + if (likely(recvmsg->sge.length != 0)) { 272 + ib_dma_unmap_single(t->cm_id->device, 273 + recvmsg->sge.addr, 274 + recvmsg->sge.length, 275 + DMA_FROM_DEVICE); 276 + recvmsg->sge.length = 0; 277 + } 270 278 271 279 spin_lock(&t->recvmsg_queue_lock); 272 280 list_add(&recvmsg->list, &t->recvmsg_queue); 273 281 spin_unlock(&t->recvmsg_queue_lock); 274 - } 275 - 276 - static struct 277 - smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t) 278 - { 279 - struct smb_direct_recvmsg *recvmsg = NULL; 280 - 281 - spin_lock(&t->empty_recvmsg_queue_lock); 282 - if (!list_empty(&t->empty_recvmsg_queue)) { 283 - recvmsg = list_first_entry(&t->empty_recvmsg_queue, 284 - struct smb_direct_recvmsg, list); 285 - list_del(&recvmsg->list); 286 - } 287 - spin_unlock(&t->empty_recvmsg_queue_lock); 288 - return recvmsg; 289 - } 290 - 291 - static void put_empty_recvmsg(struct smb_direct_transport *t, 292 - struct smb_direct_recvmsg *recvmsg) 293 - { 294 - ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, 295 - recvmsg->sge.length, DMA_FROM_DEVICE); 296 - 297 - spin_lock(&t->empty_recvmsg_queue_lock); 298 - list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue); 299 - spin_unlock(&t->empty_recvmsg_queue_lock); 300 282 } 301 283 302 284 static void enqueue_reassembly(struct smb_direct_transport *t, ··· 361 385 spin_lock_init(&t->receive_credit_lock); 362 386 spin_lock_init(&t->recvmsg_queue_lock); 363 387 INIT_LIST_HEAD(&t->recvmsg_queue); 364 - 365 - spin_lock_init(&t->empty_recvmsg_queue_lock); 366 - INIT_LIST_HEAD(&t->empty_recvmsg_queue); 367 388 368 389 init_waitqueue_head(&t->wait_send_pending); 369 390 atomic_set(&t->send_pending, 0); ··· 521 548 t = recvmsg->transport; 522 549 523 550 if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { 551 + put_recvmsg(t, recvmsg); 524 552 if (wc->status != IB_WC_WR_FLUSH_ERR) { 525 553 pr_err("Recv error. status='%s (%d)' opcode=%d\n", 526 554 ib_wc_status_msg(wc->status), wc->status, 527 555 wc->opcode); 528 556 smb_direct_disconnect_rdma_connection(t); 529 557 } 530 - put_empty_recvmsg(t, recvmsg); 531 558 return; 532 559 } 533 560 ··· 541 568 switch (recvmsg->type) { 542 569 case SMB_DIRECT_MSG_NEGOTIATE_REQ: 543 570 if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) { 544 - put_empty_recvmsg(t, recvmsg); 571 + put_recvmsg(t, recvmsg); 572 + smb_direct_disconnect_rdma_connection(t); 545 573 return; 546 574 } 547 575 t->negotiation_requested = true; ··· 550 576 t->status = SMB_DIRECT_CS_CONNECTED; 551 577 enqueue_reassembly(t, recvmsg, 0); 552 578 wake_up_interruptible(&t->wait_status); 553 - break; 579 + return; 554 580 case SMB_DIRECT_MSG_DATA_TRANSFER: { 555 581 struct smb_direct_data_transfer *data_transfer = 556 582 (struct smb_direct_data_transfer *)recvmsg->packet; ··· 559 585 560 586 if (wc->byte_len < 561 587 offsetof(struct smb_direct_data_transfer, padding)) { 562 - put_empty_recvmsg(t, recvmsg); 588 + put_recvmsg(t, recvmsg); 589 + smb_direct_disconnect_rdma_connection(t); 563 590 return; 564 591 } 565 592 ··· 568 593 if (data_length) { 569 594 if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + 570 595 (u64)data_length) { 571 - put_empty_recvmsg(t, recvmsg); 596 + put_recvmsg(t, recvmsg); 597 + smb_direct_disconnect_rdma_connection(t); 572 598 return; 573 599 } 574 600 ··· 581 605 else 582 606 t->full_packet_received = true; 583 607 584 - enqueue_reassembly(t, recvmsg, (int)data_length); 585 - wake_up_interruptible(&t->wait_reassembly_queue); 586 - 587 608 spin_lock(&t->receive_credit_lock); 588 609 receive_credits = --(t->recv_credits); 589 610 avail_recvmsg_count = t->count_avail_recvmsg; 590 611 spin_unlock(&t->receive_credit_lock); 591 612 } else { 592 - put_empty_recvmsg(t, recvmsg); 593 - 594 613 spin_lock(&t->receive_credit_lock); 595 614 receive_credits = --(t->recv_credits); 596 615 avail_recvmsg_count = ++(t->count_avail_recvmsg); ··· 607 636 if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count)) 608 637 mod_delayed_work(smb_direct_wq, 609 638 &t->post_recv_credits_work, 0); 610 - break; 639 + 640 + if (data_length) { 641 + enqueue_reassembly(t, recvmsg, (int)data_length); 642 + wake_up_interruptible(&t->wait_reassembly_queue); 643 + } else 644 + put_recvmsg(t, recvmsg); 645 + 646 + return; 611 647 } 612 - default: 613 - break; 614 648 } 649 + 650 + /* 651 + * This is an internal error! 652 + */ 653 + WARN_ON_ONCE(recvmsg->type != SMB_DIRECT_MSG_DATA_TRANSFER); 654 + put_recvmsg(t, recvmsg); 655 + smb_direct_disconnect_rdma_connection(t); 615 656 } 616 657 617 658 static int smb_direct_post_recv(struct smb_direct_transport *t, ··· 653 670 ib_dma_unmap_single(t->cm_id->device, 654 671 recvmsg->sge.addr, recvmsg->sge.length, 655 672 DMA_FROM_DEVICE); 673 + recvmsg->sge.length = 0; 656 674 smb_direct_disconnect_rdma_connection(t); 657 675 return ret; 658 676 } ··· 795 811 struct smb_direct_recvmsg *recvmsg; 796 812 int receive_credits, credits = 0; 797 813 int ret; 798 - int use_free = 1; 799 814 800 815 spin_lock(&t->receive_credit_lock); 801 816 receive_credits = t->recv_credits; ··· 802 819 803 820 if (receive_credits < t->recv_credit_target) { 804 821 while (true) { 805 - if (use_free) 806 - recvmsg = get_free_recvmsg(t); 807 - else 808 - recvmsg = get_empty_recvmsg(t); 809 - if (!recvmsg) { 810 - if (use_free) { 811 - use_free = 0; 812 - continue; 813 - } else { 814 - break; 815 - } 816 - } 822 + recvmsg = get_free_recvmsg(t); 823 + if (!recvmsg) 824 + break; 817 825 818 826 recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER; 819 827 recvmsg->first_segment = false; ··· 1780 1806 1781 1807 while ((recvmsg = get_free_recvmsg(t))) 1782 1808 mempool_free(recvmsg, t->recvmsg_mempool); 1783 - while ((recvmsg = get_empty_recvmsg(t))) 1784 - mempool_free(recvmsg, t->recvmsg_mempool); 1785 1809 1786 1810 mempool_destroy(t->recvmsg_mempool); 1787 1811 t->recvmsg_mempool = NULL; ··· 1835 1863 if (!recvmsg) 1836 1864 goto err; 1837 1865 recvmsg->transport = t; 1866 + recvmsg->sge.length = 0; 1838 1867 list_add(&recvmsg->list, &t->recvmsg_queue); 1839 1868 } 1840 1869 t->count_avail_recvmsg = t->recv_credit_max;
+17
fs/smb/server/transport_tcp.c
··· 85 85 return NULL; 86 86 } 87 87 88 + conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr; 88 89 conn->transport = KSMBD_TRANS(t); 89 90 KSMBD_TRANS(t)->conn = conn; 90 91 KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops; ··· 229 228 { 230 229 struct socket *client_sk = NULL; 231 230 struct interface *iface = (struct interface *)p; 231 + struct inet_sock *csk_inet; 232 + struct ksmbd_conn *conn; 232 233 int ret; 233 234 234 235 while (!kthread_should_stop()) { ··· 248 245 schedule_timeout_interruptible(HZ / 10); 249 246 continue; 250 247 } 248 + 249 + /* 250 + * Limits repeated connections from clients with the same IP. 251 + */ 252 + csk_inet = inet_sk(client_sk->sk); 253 + down_read(&conn_list_lock); 254 + list_for_each_entry(conn, &conn_list, conns_list) 255 + if (csk_inet->inet_daddr == conn->inet_addr) { 256 + ret = -EAGAIN; 257 + break; 258 + } 259 + up_read(&conn_list_lock); 260 + if (ret == -EAGAIN) 261 + continue; 251 262 252 263 if (server_conf.max_connections && 253 264 atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {