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

Pull smb server updates from Steve French:

- Two fixes for bounds checks of open contexts

- Two multichannel fixes, including one for important UAF

- Oplock/lease break fix for potential ksmbd connection refcount leak

- Security fix to free crypto data more securely

- Fix to enable allowing Kerberos authentication by default

- Two RDMA/smbdirect fixes

- Minor cleanup

* tag 'v6.15rc-part1-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: fix r_count dec/increment mismatch
ksmbd: fix multichannel connection failure
ksmbd: fix use-after-free in ksmbd_sessions_deregister()
ksmbd: use ib_device_get_netdev() instead of calling ops.get_netdev
ksmbd: use aead_request_free to match aead_request_alloc
Revert "ksmbd: fix missing RDMA-capable flag for IPoIB device in ksmbd_rdma_capable_netdev()"
ksmbd: add bounds check for create lease context
ksmbd: add bounds check for durable handle context
ksmbd: make SMB_SERVER_KERBEROS5 enable by default
ksmbd: Use str_read_write() and str_true_false() helpers

+68 -43
+1 -1
fs/smb/server/Kconfig
··· 70 70 config SMB_SERVER_KERBEROS5 71 71 bool "Support for Kerberos 5" 72 72 depends on SMB_SERVER 73 - default n 73 + default y
+1 -1
fs/smb/server/auth.c
··· 1218 1218 free_sg: 1219 1219 kfree(sg); 1220 1220 free_req: 1221 - kfree(req); 1221 + aead_request_free(req); 1222 1222 free_ctx: 1223 1223 ksmbd_release_crypto_ctx(ctx); 1224 1224 return rc;
+19
fs/smb/server/mgmt/user_session.c
··· 230 230 if (!ksmbd_chann_del(conn, sess) && 231 231 xa_empty(&sess->ksmbd_chann_list)) { 232 232 hash_del(&sess->hlist); 233 + down_write(&conn->session_lock); 234 + xa_erase(&conn->sessions, sess->id); 235 + up_write(&conn->session_lock); 233 236 ksmbd_session_destroy(sess); 234 237 } 235 238 } ··· 257 254 } 258 255 up_write(&conn->session_lock); 259 256 up_write(&sessions_table_lock); 257 + } 258 + 259 + bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, 260 + unsigned long long id) 261 + { 262 + struct ksmbd_session *sess; 263 + 264 + down_read(&conn->session_lock); 265 + sess = xa_load(&conn->sessions, id); 266 + if (sess) { 267 + up_read(&conn->session_lock); 268 + return true; 269 + } 270 + up_read(&conn->session_lock); 271 + 272 + return false; 260 273 } 261 274 262 275 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
+2
fs/smb/server/mgmt/user_session.h
··· 87 87 struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id); 88 88 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, 89 89 unsigned long long id); 90 + bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, 91 + unsigned long long id); 90 92 int ksmbd_session_register(struct ksmbd_conn *conn, 91 93 struct ksmbd_session *sess); 92 94 void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
+10 -2
fs/smb/server/oplock.c
··· 724 724 work->conn = conn; 725 725 work->sess = opinfo->sess; 726 726 727 + ksmbd_conn_r_count_inc(conn); 727 728 if (opinfo->op_state == OPLOCK_ACK_WAIT) { 728 - ksmbd_conn_r_count_inc(conn); 729 729 INIT_WORK(&work->work, __smb2_oplock_break_noti); 730 730 ksmbd_queue_work(work); 731 731 ··· 833 833 work->conn = conn; 834 834 work->sess = opinfo->sess; 835 835 836 + ksmbd_conn_r_count_inc(conn); 836 837 if (opinfo->op_state == OPLOCK_ACK_WAIT) { 837 - ksmbd_conn_r_count_inc(conn); 838 838 INIT_WORK(&work->work, __smb2_lease_break_noti); 839 839 ksmbd_queue_work(work); 840 840 wait_for_break_ack(opinfo); ··· 1505 1505 if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) { 1506 1506 struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; 1507 1507 1508 + if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) < 1509 + sizeof(struct create_lease_v2) - 4) 1510 + return NULL; 1511 + 1508 1512 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); 1509 1513 lreq->req_state = lc->lcontext.LeaseState; 1510 1514 lreq->flags = lc->lcontext.LeaseFlags; ··· 1520 1516 lreq->version = 2; 1521 1517 } else { 1522 1518 struct create_lease *lc = (struct create_lease *)cc; 1519 + 1520 + if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) < 1521 + sizeof(struct create_lease)) 1522 + return NULL; 1523 1523 1524 1524 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); 1525 1525 lreq->req_state = lc->lcontext.LeaseState;
+25 -8
fs/smb/server/smb2pdu.c
··· 1707 1707 1708 1708 if (conn->dialect != sess->dialect) { 1709 1709 rc = -EINVAL; 1710 - ksmbd_user_session_put(sess); 1711 1710 goto out_err; 1712 1711 } 1713 1712 1714 1713 if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) { 1715 1714 rc = -EINVAL; 1716 - ksmbd_user_session_put(sess); 1717 1715 goto out_err; 1718 1716 } 1719 1717 1720 1718 if (strncmp(conn->ClientGUID, sess->ClientGUID, 1721 1719 SMB2_CLIENT_GUID_SIZE)) { 1722 1720 rc = -ENOENT; 1723 - ksmbd_user_session_put(sess); 1724 1721 goto out_err; 1725 1722 } 1726 1723 1727 1724 if (sess->state == SMB2_SESSION_IN_PROGRESS) { 1728 1725 rc = -EACCES; 1729 - ksmbd_user_session_put(sess); 1730 1726 goto out_err; 1731 1727 } 1732 1728 1733 1729 if (sess->state == SMB2_SESSION_EXPIRED) { 1734 1730 rc = -EFAULT; 1735 - ksmbd_user_session_put(sess); 1736 1731 goto out_err; 1737 1732 } 1738 - ksmbd_user_session_put(sess); 1739 1733 1740 1734 if (ksmbd_conn_need_reconnect(conn)) { 1741 1735 rc = -EFAULT; 1736 + ksmbd_user_session_put(sess); 1742 1737 sess = NULL; 1743 1738 goto out_err; 1744 1739 } 1745 1740 1746 - sess = ksmbd_session_lookup(conn, sess_id); 1747 - if (!sess) { 1741 + if (is_ksmbd_session_in_connection(conn, sess_id)) { 1748 1742 rc = -EACCES; 1749 1743 goto out_err; 1750 1744 } ··· 1904 1910 1905 1911 sess->last_active = jiffies; 1906 1912 sess->state = SMB2_SESSION_EXPIRED; 1913 + ksmbd_user_session_put(sess); 1914 + work->sess = NULL; 1907 1915 if (try_delay) { 1908 1916 ksmbd_conn_set_need_reconnect(conn); 1909 1917 ssleep(5); ··· 2704 2708 goto out; 2705 2709 } 2706 2710 2711 + if (le16_to_cpu(context->DataOffset) + 2712 + le32_to_cpu(context->DataLength) < 2713 + sizeof(struct create_durable_reconn_v2_req)) { 2714 + err = -EINVAL; 2715 + goto out; 2716 + } 2717 + 2707 2718 recon_v2 = (struct create_durable_reconn_v2_req *)context; 2708 2719 persistent_id = recon_v2->Fid.PersistentFileId; 2709 2720 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); ··· 2744 2741 goto out; 2745 2742 } 2746 2743 2744 + if (le16_to_cpu(context->DataOffset) + 2745 + le32_to_cpu(context->DataLength) < 2746 + sizeof(struct create_durable_reconn_req)) { 2747 + err = -EINVAL; 2748 + goto out; 2749 + } 2750 + 2747 2751 recon = (struct create_durable_reconn_req *)context; 2748 2752 persistent_id = recon->Data.Fid.PersistentFileId; 2749 2753 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); ··· 2772 2762 2773 2763 if (dh_info->type == DURABLE_RECONN || 2774 2764 dh_info->type == DURABLE_RECONN_V2) { 2765 + err = -EINVAL; 2766 + goto out; 2767 + } 2768 + 2769 + if (le16_to_cpu(context->DataOffset) + 2770 + le32_to_cpu(context->DataLength) < 2771 + sizeof(struct create_durable_req_v2)) { 2775 2772 err = -EINVAL; 2776 2773 goto out; 2777 2774 }
+10 -31
fs/smb/server/transport_rdma.c
··· 14 14 #include <linux/mempool.h> 15 15 #include <linux/highmem.h> 16 16 #include <linux/scatterlist.h> 17 + #include <linux/string_choices.h> 17 18 #include <rdma/ib_verbs.h> 18 19 #include <rdma/rdma_cm.h> 19 20 #include <rdma/rw.h> ··· 1397 1396 } 1398 1397 1399 1398 ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n", 1400 - is_read ? "read" : "write", buf_len, credits_needed); 1399 + str_read_write(is_read), buf_len, credits_needed); 1401 1400 1402 1401 ret = wait_for_rw_credits(t, credits_needed); 1403 1402 if (ret < 0) ··· 2242 2241 for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) { 2243 2242 struct net_device *ndev; 2244 2243 2245 - if (smb_dev->ib_dev->ops.get_netdev) { 2246 - ndev = smb_dev->ib_dev->ops.get_netdev( 2247 - smb_dev->ib_dev, i + 1); 2248 - if (!ndev) 2249 - continue; 2244 + ndev = ib_device_get_netdev(smb_dev->ib_dev, i + 1); 2245 + if (!ndev) 2246 + continue; 2250 2247 2251 - if (ndev == netdev) { 2252 - dev_put(ndev); 2253 - rdma_capable = true; 2254 - goto out; 2255 - } 2248 + if (ndev == netdev) { 2256 2249 dev_put(ndev); 2257 - /* if ib_dev does not implement ops.get_netdev 2258 - * check for matching infiniband GUID in hw_addr 2259 - */ 2260 - } else if (netdev->type == ARPHRD_INFINIBAND) { 2261 - struct netdev_hw_addr *ha; 2262 - union ib_gid gid; 2263 - u32 port_num; 2264 - int ret; 2265 - 2266 - netdev_hw_addr_list_for_each( 2267 - ha, &netdev->dev_addrs) { 2268 - memcpy(&gid, ha->addr + 4, sizeof(gid)); 2269 - ret = ib_find_gid(smb_dev->ib_dev, &gid, 2270 - &port_num, NULL); 2271 - if (!ret) { 2272 - rdma_capable = true; 2273 - goto out; 2274 - } 2275 - } 2250 + rdma_capable = true; 2251 + goto out; 2276 2252 } 2253 + dev_put(ndev); 2277 2254 } 2278 2255 } 2279 2256 out: ··· 2268 2289 } 2269 2290 2270 2291 ksmbd_debug(RDMA, "netdev(%s) rdma capable : %s\n", 2271 - netdev->name, rdma_capable ? "true" : "false"); 2292 + netdev->name, str_true_false(rdma_capable)); 2272 2293 2273 2294 return rdma_capable; 2274 2295 }