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.19-rc1-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

- Fix set xattr name validation

- Fix session refcount leak

- Minor cleanup

- smbdirect (RDMA) fixes: improve receive completion, and connect

* tag 'v6.19-rc1-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: fix buffer validation by including null terminator size in EA length
ksmbd: Fix refcount leak when invalid session is found on session lookup
ksmbd: remove redundant DACL check in smb_check_perm_dacl
ksmbd: convert comma to semicolon
smb: server: defer the initial recv completion logic to smb_direct_negotiate_recv_work()
smb: server: initialize recv_io->cqe.done = recv_done just once
smb: smbdirect: introduce smbdirect_socket.connect.{lock,work}

+164 -36
+12
fs/smb/common/smbdirect/smbdirect_socket.h
··· 133 133 struct smbdirect_socket_parameters parameters; 134 134 135 135 /* 136 + * The state for connect/negotiation 137 + */ 138 + struct { 139 + spinlock_t lock; 140 + struct work_struct work; 141 + } connect; 142 + 143 + /* 136 144 * The state for keepalive and timeout handling 137 145 */ 138 146 struct { ··· 360 352 361 353 INIT_WORK(&sc->disconnect_work, __smbdirect_socket_disabled_work); 362 354 disable_work_sync(&sc->disconnect_work); 355 + 356 + spin_lock_init(&sc->connect.lock); 357 + INIT_WORK(&sc->connect.work, __smbdirect_socket_disabled_work); 358 + disable_work_sync(&sc->connect.work); 363 359 364 360 INIT_WORK(&sc->idle.immediate_work, __smbdirect_socket_disabled_work); 365 361 disable_work_sync(&sc->idle.immediate_work);
+3 -1
fs/smb/server/mgmt/user_session.c
··· 325 325 sess = ksmbd_session_lookup(conn, id); 326 326 if (!sess && conn->binding) 327 327 sess = ksmbd_session_lookup_slowpath(id); 328 - if (sess && sess->state != SMB2_SESSION_VALID) 328 + if (sess && sess->state != SMB2_SESSION_VALID) { 329 + ksmbd_user_session_put(sess); 329 330 sess = NULL; 331 + } 330 332 return sess; 331 333 } 332 334
+2 -2
fs/smb/server/smb2pdu.c
··· 2363 2363 int rc = 0; 2364 2364 unsigned int next = 0; 2365 2365 2366 - if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 2366 + if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 + 2367 2367 le16_to_cpu(eabuf->EaValueLength)) 2368 2368 return -EINVAL; 2369 2369 ··· 2440 2440 break; 2441 2441 } 2442 2442 2443 - if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 2443 + if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 + 2444 2444 le16_to_cpu(eabuf->EaValueLength)) { 2445 2445 rc = -EINVAL; 2446 2446 break;
-3
fs/smb/server/smbacl.c
··· 1307 1307 granted |= le32_to_cpu(ace->access_req); 1308 1308 ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size)); 1309 1309 } 1310 - 1311 - if (!pdacl->num_aces) 1312 - granted = GENERIC_ALL_FLAGS; 1313 1310 } 1314 1311 1315 1312 if (!uid)
+146 -29
fs/smb/server/transport_rdma.c
··· 242 242 * disable[_delayed]_work_sync() 243 243 */ 244 244 disable_work(&sc->disconnect_work); 245 + disable_work(&sc->connect.work); 245 246 disable_work(&sc->recv_io.posted.refill_work); 246 247 disable_delayed_work(&sc->idle.timer_work); 247 248 disable_work(&sc->idle.immediate_work); ··· 298 297 * not queued again but here we don't block and avoid 299 298 * disable[_delayed]_work_sync() 300 299 */ 300 + disable_work(&sc->connect.work); 301 301 disable_work(&sc->recv_io.posted.refill_work); 302 302 disable_work(&sc->idle.immediate_work); 303 303 disable_delayed_work(&sc->idle.timer_work); ··· 469 467 */ 470 468 smb_direct_disconnect_wake_up_all(sc); 471 469 470 + disable_work_sync(&sc->connect.work); 472 471 disable_work_sync(&sc->recv_io.posted.refill_work); 473 472 disable_delayed_work_sync(&sc->idle.timer_work); 474 473 disable_work_sync(&sc->idle.immediate_work); ··· 638 635 639 636 switch (sc->recv_io.expected) { 640 637 case SMBDIRECT_EXPECT_NEGOTIATE_REQ: 641 - if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) { 642 - put_recvmsg(sc, recvmsg); 643 - smb_direct_disconnect_rdma_connection(sc); 644 - return; 645 - } 646 - sc->recv_io.reassembly.full_packet_received = true; 647 - /* 648 - * Some drivers (at least mlx5_ib) might post a 649 - * recv completion before RDMA_CM_EVENT_ESTABLISHED, 650 - * we need to adjust our expectation in that case. 651 - */ 652 - if (!sc->first_error && sc->status == SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING) 653 - sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; 654 - if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) { 655 - put_recvmsg(sc, recvmsg); 656 - smb_direct_disconnect_rdma_connection(sc); 657 - return; 658 - } 659 - sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING; 660 - enqueue_reassembly(sc, recvmsg, 0); 661 - wake_up(&sc->status_wait); 662 - return; 638 + /* see smb_direct_negotiate_recv_done */ 639 + break; 663 640 case SMBDIRECT_EXPECT_DATA_TRANSFER: { 664 641 struct smbdirect_data_transfer *data_transfer = 665 642 (struct smbdirect_data_transfer *)recvmsg->packet; ··· 725 742 smb_direct_disconnect_rdma_connection(sc); 726 743 } 727 744 745 + static void smb_direct_negotiate_recv_work(struct work_struct *work); 746 + 747 + static void smb_direct_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc) 748 + { 749 + struct smbdirect_recv_io *recv_io = 750 + container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe); 751 + struct smbdirect_socket *sc = recv_io->socket; 752 + unsigned long flags; 753 + 754 + /* 755 + * reset the common recv_done for later reuse. 756 + */ 757 + recv_io->cqe.done = recv_done; 758 + 759 + if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { 760 + put_recvmsg(sc, recv_io); 761 + if (wc->status != IB_WC_WR_FLUSH_ERR) { 762 + pr_err("Negotiate Recv error. status='%s (%d)' opcode=%d\n", 763 + ib_wc_status_msg(wc->status), wc->status, 764 + wc->opcode); 765 + smb_direct_disconnect_rdma_connection(sc); 766 + } 767 + return; 768 + } 769 + 770 + ksmbd_debug(RDMA, "Negotiate Recv completed. status='%s (%d)', opcode=%d\n", 771 + ib_wc_status_msg(wc->status), wc->status, 772 + wc->opcode); 773 + 774 + ib_dma_sync_single_for_cpu(sc->ib.dev, 775 + recv_io->sge.addr, 776 + recv_io->sge.length, 777 + DMA_FROM_DEVICE); 778 + 779 + /* 780 + * This is an internal error! 781 + */ 782 + if (WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_NEGOTIATE_REQ)) { 783 + put_recvmsg(sc, recv_io); 784 + smb_direct_disconnect_rdma_connection(sc); 785 + return; 786 + } 787 + 788 + /* 789 + * Don't reset timer to the keepalive interval in 790 + * this will be done in smb_direct_negotiate_recv_work. 791 + */ 792 + 793 + /* 794 + * Only remember the recv_io if it has enough bytes, 795 + * this gives smb_direct_negotiate_recv_work enough 796 + * information in order to disconnect if it was not 797 + * valid. 798 + */ 799 + sc->recv_io.reassembly.full_packet_received = true; 800 + if (wc->byte_len >= sizeof(struct smbdirect_negotiate_req)) 801 + enqueue_reassembly(sc, recv_io, 0); 802 + else 803 + put_recvmsg(sc, recv_io); 804 + 805 + /* 806 + * Some drivers (at least mlx5_ib and irdma in roce mode) 807 + * might post a recv completion before RDMA_CM_EVENT_ESTABLISHED, 808 + * we need to adjust our expectation in that case. 809 + * 810 + * So we defer further processing of the negotiation 811 + * to smb_direct_negotiate_recv_work(). 812 + * 813 + * If we are already in SMBDIRECT_SOCKET_NEGOTIATE_NEEDED 814 + * we queue the work directly otherwise 815 + * smb_direct_cm_handler() will do it, when 816 + * RDMA_CM_EVENT_ESTABLISHED arrived. 817 + */ 818 + spin_lock_irqsave(&sc->connect.lock, flags); 819 + if (!sc->first_error) { 820 + INIT_WORK(&sc->connect.work, smb_direct_negotiate_recv_work); 821 + if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_NEEDED) 822 + queue_work(sc->workqueue, &sc->connect.work); 823 + } 824 + spin_unlock_irqrestore(&sc->connect.lock, flags); 825 + } 826 + 827 + static void smb_direct_negotiate_recv_work(struct work_struct *work) 828 + { 829 + struct smbdirect_socket *sc = 830 + container_of(work, struct smbdirect_socket, connect.work); 831 + const struct smbdirect_socket_parameters *sp = &sc->parameters; 832 + struct smbdirect_recv_io *recv_io; 833 + 834 + if (sc->first_error) 835 + return; 836 + 837 + ksmbd_debug(RDMA, "Negotiate Recv Work running\n"); 838 + 839 + /* 840 + * Reset timer to the keepalive interval in 841 + * order to trigger our next keepalive message. 842 + */ 843 + sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE; 844 + mod_delayed_work(sc->workqueue, &sc->idle.timer_work, 845 + msecs_to_jiffies(sp->keepalive_interval_msec)); 846 + 847 + /* 848 + * If smb_direct_negotiate_recv_done() detected an 849 + * invalid request we want to disconnect. 850 + */ 851 + recv_io = get_first_reassembly(sc); 852 + if (!recv_io) { 853 + smb_direct_disconnect_rdma_connection(sc); 854 + return; 855 + } 856 + 857 + if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) { 858 + smb_direct_disconnect_rdma_connection(sc); 859 + return; 860 + } 861 + sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING; 862 + wake_up(&sc->status_wait); 863 + } 864 + 728 865 static int smb_direct_post_recv(struct smbdirect_socket *sc, 729 866 struct smbdirect_recv_io *recvmsg) 730 867 { ··· 861 758 return ret; 862 759 recvmsg->sge.length = sp->max_recv_size; 863 760 recvmsg->sge.lkey = sc->ib.pd->local_dma_lkey; 864 - recvmsg->cqe.done = recv_done; 865 761 866 762 wr.wr_cqe = &recvmsg->cqe; 867 763 wr.next = NULL; ··· 1834 1732 struct rdma_cm_event *event) 1835 1733 { 1836 1734 struct smbdirect_socket *sc = cm_id->context; 1735 + unsigned long flags; 1837 1736 1838 1737 ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n", 1839 1738 cm_id, rdma_event_msg(event->event), event->event); ··· 1842 1739 switch (event->event) { 1843 1740 case RDMA_CM_EVENT_ESTABLISHED: { 1844 1741 /* 1845 - * Some drivers (at least mlx5_ib) might post a 1846 - * recv completion before RDMA_CM_EVENT_ESTABLISHED, 1742 + * Some drivers (at least mlx5_ib and irdma in roce mode) 1743 + * might post a recv completion before RDMA_CM_EVENT_ESTABLISHED, 1847 1744 * we need to adjust our expectation in that case. 1848 1745 * 1849 - * As we already started the negotiation, we just 1850 - * ignore RDMA_CM_EVENT_ESTABLISHED here. 1746 + * If smb_direct_negotiate_recv_done was called first 1747 + * it initialized sc->connect.work only for us to 1748 + * start, so that we turned into 1749 + * SMBDIRECT_SOCKET_NEGOTIATE_NEEDED, before 1750 + * smb_direct_negotiate_recv_work() runs. 1751 + * 1752 + * If smb_direct_negotiate_recv_done didn't happen 1753 + * yet. sc->connect.work is still be disabled and 1754 + * queue_work() is a no-op. 1851 1755 */ 1852 - if (!sc->first_error && sc->status > SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING) 1853 - break; 1854 1756 if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)) 1855 1757 break; 1856 1758 sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; 1759 + spin_lock_irqsave(&sc->connect.lock, flags); 1760 + if (!sc->first_error) 1761 + queue_work(sc->workqueue, &sc->connect.work); 1762 + spin_unlock_irqrestore(&sc->connect.lock, flags); 1857 1763 wake_up(&sc->status_wait); 1858 1764 break; 1859 1765 } ··· 2033 1921 recvmsg = get_free_recvmsg(sc); 2034 1922 if (!recvmsg) 2035 1923 return -ENOMEM; 1924 + recvmsg->cqe.done = smb_direct_negotiate_recv_done; 2036 1925 2037 1926 ret = smb_direct_post_recv(sc, recvmsg); 2038 1927 if (ret) { ··· 2452 2339 2453 2340 static int smb_direct_connect(struct smbdirect_socket *sc) 2454 2341 { 2342 + struct smbdirect_recv_io *recv_io; 2455 2343 int ret; 2456 2344 2457 2345 ret = smb_direct_init_params(sc); ··· 2466 2352 pr_err("Can't init RDMA pool: %d\n", ret); 2467 2353 return ret; 2468 2354 } 2355 + 2356 + list_for_each_entry(recv_io, &sc->recv_io.free.list, list) 2357 + recv_io->cqe.done = recv_done; 2469 2358 2470 2359 ret = smb_direct_create_qpair(sc); 2471 2360 if (ret) {
+1 -1
fs/smb/server/vfs.c
··· 702 702 rd.old_parent = NULL; 703 703 rd.new_parent = new_path.dentry; 704 704 rd.flags = flags; 705 - rd.delegated_inode = NULL, 705 + rd.delegated_inode = NULL; 706 706 err = start_renaming_dentry(&rd, lookup_flags, old_child, &new_last); 707 707 if (err) 708 708 goto out_drop_write;