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

Pull more smb server updates from Steve French:

- move fs/smb/common/smbdirect to fs/smb/smbdirect

- change signature calc to use AES-CMAC library, simpler and faster

- invalid signature fix

- multichannel fix

- open create options fix

- fix durable handle leak

- cap maximum lock count to avoid potential denial of service

- four connection fixes: connection free and session destroy IDA fixes,
refcount fix, connection leak fix, max_connections off by one fix

- IPC validation fix

- fix out of bounds write in getting xattrs

- fix use after free in durable handle reconnect

- three ACL fixes: fix potential ACL overflow, harden num_aces check,
and fix minimum ACE size check

* tag 'v7.1-rc-part2-ksmbd-fixes' of git://git.samba.org/ksmbd:
smb: smbdirect: move fs/smb/common/smbdirect/ to fs/smb/smbdirect/
smb: server: stop sending fake security descriptors
ksmbd: scope conn->binding slowpath to bound sessions only
ksmbd: fix CreateOptions sanitization clobbering the whole field
ksmbd: fix durable fd leak on ClientGUID mismatch in durable v2 open
ksmbd: fix O(N^2) DoS in smb2_lock via unbounded LockCount
ksmbd: destroy async_ida in ksmbd_conn_free()
ksmbd: destroy tree_conn_ida in ksmbd_session_destroy()
ksmbd: Use AES-CMAC library for SMB3 signature calculation
ksmbd: reset rcount per connection in ksmbd_conn_wait_idle_sess_id()
ksmbd: fix out-of-bounds write in smb2_get_ea() EA alignment
ksmbd: use check_add_overflow() to prevent u16 DACL size overflow
ksmbd: fix use-after-free in smb2_open during durable reconnect
ksmbd: validate num_aces and harden ACE walk in smb_inherit_dacl()
smb: server: fix max_connections off-by-one in tcp accept path
ksmbd: require minimum ACE size in smb_check_perm_dacl()
ksmbd: validate response sizes in ipc_validate_msg()
smb: server: fix active_num_conn leak on transport allocation failure

+165 -215
+1 -1
MAINTAINERS
··· 24662 24662 L: samba-technical@lists.samba.org (moderated for non-subscribers) 24663 24663 S: Maintained 24664 24664 F: fs/smb/client/smbdirect.* 24665 - F: fs/smb/common/smbdirect/ 24665 + F: fs/smb/smbdirect/ 24666 24666 F: fs/smb/server/transport_rdma.* 24667 24667 24668 24668 SMC91x ETHERNET DRIVER
+1 -1
fs/smb/Kconfig
··· 4 4 5 5 source "fs/smb/client/Kconfig" 6 6 source "fs/smb/server/Kconfig" 7 - source "fs/smb/common/smbdirect/Kconfig" 7 + source "fs/smb/smbdirect/Kconfig" 8 8 9 9 config SMBFS 10 10 tristate
+1
fs/smb/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 3 obj-$(CONFIG_SMBFS) += common/ 4 + obj-$(CONFIG_SMBDIRECT) += smbdirect/ 4 5 obj-$(CONFIG_CIFS) += client/ 5 6 obj-$(CONFIG_SMB_SERVER) += server/
+1 -1
fs/smb/client/Kconfig
··· 182 182 bool "SMB Direct support" 183 183 depends on CIFS && INFINIBAND && INFINIBAND_ADDR_TRANS 184 184 depends on CIFS=m || INFINIBAND=y 185 - select SMB_COMMON_SMBDIRECT 185 + select SMBDIRECT 186 186 help 187 187 Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1. 188 188 SMB Direct allows transferring SMB packets over RDMA. If unsure,
+1 -1
fs/smb/client/smbdirect.c
··· 9 9 #include "cifs_debug.h" 10 10 #include "cifsproto.h" 11 11 #include "smb2proto.h" 12 - #include "../common/smbdirect/smbdirect_public.h" 12 + #include "../smbdirect/public.h" 13 13 14 14 /* Port numbers for SMBD transport */ 15 15 #define SMB_PORT 445
+1 -1
fs/smb/client/smbdirect.h
··· 12 12 13 13 #include "cifsglob.h" 14 14 15 - #include "../common/smbdirect/smbdirect.h" 15 + #include "../smbdirect/smbdirect.h" 16 16 17 17 extern int rdma_readwrite_threshold; 18 18 extern int smbd_max_frmr_depth;
-1
fs/smb/common/Makefile
··· 4 4 # 5 5 6 6 obj-$(CONFIG_SMBFS) += cifs_md4.o 7 - obj-$(CONFIG_SMB_COMMON_SMBDIRECT) += smbdirect/
+1 -1
fs/smb/common/smbdirect/Kconfig fs/smb/smbdirect/Kconfig
··· 2 2 # 3 3 # smbdirect configuration 4 4 5 - config SMB_COMMON_SMBDIRECT 5 + config SMBDIRECT 6 6 def_tristate n 7 7 depends on INFINIBAND && INFINIBAND_ADDR_TRANS 8 8 depends on m || INFINIBAND=y
-18
fs/smb/common/smbdirect/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-or-later 2 - # 3 - # Makefile for smbdirect support 4 - # 5 - 6 - obj-$(CONFIG_SMB_COMMON_SMBDIRECT) += smbdirect.o 7 - 8 - smbdirect-y := \ 9 - smbdirect_socket.o \ 10 - smbdirect_connection.o \ 11 - smbdirect_mr.o \ 12 - smbdirect_rw.o \ 13 - smbdirect_debug.o \ 14 - smbdirect_connect.o \ 15 - smbdirect_listen.o \ 16 - smbdirect_accept.o \ 17 - smbdirect_devices.o \ 18 - smbdirect_main.o
fs/smb/common/smbdirect/smbdirect.h fs/smb/smbdirect/smbdirect.h
+2 -2
fs/smb/common/smbdirect/smbdirect_accept.c fs/smb/smbdirect/accept.c
··· 5 5 * Copyright (c) 2025, Stefan Metzmacher 6 6 */ 7 7 8 - #include "smbdirect_internal.h" 8 + #include "internal.h" 9 9 #include <net/sock.h> 10 - #include "../../common/smb2status.h" 10 + #include "../common/smb2status.h" 11 11 12 12 static int smbdirect_accept_rdma_event_handler(struct rdma_cm_id *id, 13 13 struct rdma_cm_event *event);
+2 -2
fs/smb/common/smbdirect/smbdirect_connect.c fs/smb/smbdirect/connect.c
··· 3 3 * Copyright (c) 2012,2016,2017,2025 Stefan Metzmacher 4 4 */ 5 5 6 - #include "smbdirect_internal.h" 7 - #include "../../common/smb2status.h" 6 + #include "internal.h" 7 + #include "../common/smb2status.h" 8 8 9 9 static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc); 10 10 static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc,
+1 -1
fs/smb/common/smbdirect/smbdirect_connection.c fs/smb/smbdirect/connection.c
··· 4 4 * Copyright (c) 2025, Stefan Metzmacher 5 5 */ 6 6 7 - #include "smbdirect_internal.h" 7 + #include "internal.h" 8 8 #include <linux/folio_queue.h> 9 9 10 10 struct smbdirect_map_sges {
+1 -1
fs/smb/common/smbdirect/smbdirect_debug.c fs/smb/smbdirect/debug.c
··· 4 4 * Copyright (c) 2025, Stefan Metzmacher 5 5 */ 6 6 7 - #include "smbdirect_internal.h" 7 + #include "internal.h" 8 8 #include <linux/seq_file.h> 9 9 10 10 void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
+1 -1
fs/smb/common/smbdirect/smbdirect_devices.c fs/smb/smbdirect/devices.c
··· 5 5 * Copyright (c) 2025 Stefan Metzmacher 6 6 */ 7 7 8 - #include "smbdirect_internal.h" 8 + #include "internal.h" 9 9 10 10 static u8 smbdirect_ib_device_rdma_capable_node_type(struct ib_device *ib_dev) 11 11 {
+3 -3
fs/smb/common/smbdirect/smbdirect_internal.h fs/smb/smbdirect/internal.h
··· 9 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 10 11 11 #include "smbdirect.h" 12 - #include "smbdirect_pdu.h" 13 - #include "smbdirect_public.h" 12 + #include "pdu.h" 13 + #include "public.h" 14 14 15 15 #include <linux/mutex.h> 16 16 ··· 34 34 35 35 extern struct smbdirect_module_state smbdirect_globals; 36 36 37 - #include "smbdirect_socket.h" 37 + #include "socket.h" 38 38 39 39 struct smbdirect_device { 40 40 struct list_head list;
+1 -1
fs/smb/common/smbdirect/smbdirect_listen.c fs/smb/smbdirect/listen.c
··· 5 5 * Copyright (c) 2025, Stefan Metzmacher 6 6 */ 7 7 8 - #include "smbdirect_internal.h" 8 + #include "internal.h" 9 9 10 10 static int smbdirect_listen_rdma_event_handler(struct rdma_cm_id *id, 11 11 struct rdma_cm_event *event);
+1 -1
fs/smb/common/smbdirect/smbdirect_main.c fs/smb/smbdirect/main.c
··· 3 3 * Copyright (c) 2025, Stefan Metzmacher 4 4 */ 5 5 6 - #include "smbdirect_internal.h" 6 + #include "internal.h" 7 7 #include <linux/module.h> 8 8 9 9 struct smbdirect_module_state smbdirect_globals = {
+1 -1
fs/smb/common/smbdirect/smbdirect_mr.c fs/smb/smbdirect/mr.c
··· 4 4 * Copyright (c) 2025, Stefan Metzmacher 5 5 */ 6 6 7 - #include "smbdirect_internal.h" 7 + #include "internal.h" 8 8 9 9 /* 10 10 * Allocate MRs used for RDMA read/write
fs/smb/common/smbdirect/smbdirect_pdu.h fs/smb/smbdirect/pdu.h
fs/smb/common/smbdirect/smbdirect_public.h fs/smb/smbdirect/public.h
+1 -1
fs/smb/common/smbdirect/smbdirect_rw.c fs/smb/smbdirect/rw.c
··· 5 5 * Copyright (c) 2025, Stefan Metzmacher 6 6 */ 7 7 8 - #include "smbdirect_internal.h" 8 + #include "internal.h" 9 9 10 10 static int smbdirect_connection_wait_for_rw_credits(struct smbdirect_socket *sc, 11 11 int credits)
+1 -1
fs/smb/common/smbdirect/smbdirect_socket.c fs/smb/smbdirect/socket.c
··· 4 4 * Copyright (c) 2025, Stefan Metzmacher 5 5 */ 6 6 7 - #include "smbdirect_internal.h" 7 + #include "internal.h" 8 8 9 9 bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs) 10 10 {
fs/smb/common/smbdirect/smbdirect_socket.h fs/smb/smbdirect/socket.h
+2 -2
fs/smb/server/Kconfig
··· 7 7 select NLS_UTF8 8 8 select NLS_UCS2_UTILS 9 9 select CRYPTO 10 + select CRYPTO_LIB_AES_CBC_MACS 10 11 select CRYPTO_LIB_ARC4 11 12 select CRYPTO_LIB_DES 12 13 select CRYPTO_LIB_MD5 13 14 select CRYPTO_LIB_SHA256 14 15 select CRYPTO_LIB_SHA512 15 16 select CRYPTO_LIB_UTILS 16 - select CRYPTO_CMAC 17 17 select CRYPTO_AEAD2 18 18 select CRYPTO_CCM 19 19 select CRYPTO_GCM ··· 49 49 bool "Support for SMB Direct protocol" 50 50 depends on SMB_SERVER && INFINIBAND && INFINIBAND_ADDR_TRANS 51 51 depends on SMB_SERVER=m || INFINIBAND=y 52 - select SMB_COMMON_SMBDIRECT 52 + select SMBDIRECT 53 53 default n 54 54 55 55 help
+13 -38
fs/smb/server/auth.c
··· 11 11 #include <linux/writeback.h> 12 12 #include <linux/uio.h> 13 13 #include <linux/xattr.h> 14 - #include <crypto/hash.h> 15 14 #include <crypto/aead.h> 15 + #include <crypto/aes-cbc-macs.h> 16 16 #include <crypto/md5.h> 17 17 #include <crypto/sha2.h> 18 18 #include <crypto/utils.h> ··· 490 490 * @sig: signature value generated for client request packet 491 491 * 492 492 */ 493 - int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, 494 - int n_vec, char *sig) 493 + void ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, 494 + int n_vec, char *sig) 495 495 { 496 - struct ksmbd_crypto_ctx *ctx; 497 - int rc, i; 496 + struct aes_cmac_key cmac_key; 497 + struct aes_cmac_ctx cmac_ctx; 498 + int i; 498 499 499 - ctx = ksmbd_crypto_ctx_find_cmacaes(); 500 - if (!ctx) { 501 - ksmbd_debug(AUTH, "could not crypto alloc cmac\n"); 502 - return -ENOMEM; 503 - } 500 + /* This cannot fail, since we always pass a valid key length. */ 501 + static_assert(SMB2_CMACAES_SIZE == AES_KEYSIZE_128); 502 + aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE); 504 503 505 - rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx), 506 - key, 507 - SMB2_CMACAES_SIZE); 508 - if (rc) 509 - goto out; 510 - 511 - rc = crypto_shash_init(CRYPTO_CMACAES(ctx)); 512 - if (rc) { 513 - ksmbd_debug(AUTH, "cmaces init error %d\n", rc); 514 - goto out; 515 - } 516 - 517 - for (i = 0; i < n_vec; i++) { 518 - rc = crypto_shash_update(CRYPTO_CMACAES(ctx), 519 - iov[i].iov_base, 520 - iov[i].iov_len); 521 - if (rc) { 522 - ksmbd_debug(AUTH, "cmaces update error %d\n", rc); 523 - goto out; 524 - } 525 - } 526 - 527 - rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig); 528 - if (rc) 529 - ksmbd_debug(AUTH, "cmaces generation error %d\n", rc); 530 - out: 531 - ksmbd_release_crypto_ctx(ctx); 532 - return rc; 504 + aes_cmac_init(&cmac_ctx, &cmac_key); 505 + for (i = 0; i < n_vec; i++) 506 + aes_cmac_update(&cmac_ctx, iov[i].iov_base, iov[i].iov_len); 507 + aes_cmac_final(&cmac_ctx, sig); 533 508 } 534 509 535 510 struct derivation {
+2 -2
fs/smb/server/auth.h
··· 54 54 int in_len, char *out_blob, int *out_len); 55 55 void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, 56 56 int n_vec, char *sig); 57 - int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, 58 - int n_vec, char *sig); 57 + void ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, 58 + int n_vec, char *sig); 59 59 int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess, 60 60 struct ksmbd_conn *conn); 61 61 int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
+11 -3
fs/smb/server/connection.c
··· 98 98 kfree(conn->preauth_info); 99 99 kfree(conn->mechToken); 100 100 if (atomic_dec_and_test(&conn->refcnt)) { 101 + /* 102 + * async_ida is embedded in struct ksmbd_conn, so pair 103 + * ida_destroy() with the final kfree() rather than with 104 + * the unconditional field teardown above. This keeps 105 + * the IDA valid for the entire lifetime of the struct, 106 + * even while other refcount holders (oplock / vfs 107 + * durable handles) still reference the connection. 108 + */ 109 + ida_destroy(&conn->async_ida); 101 110 conn->transport->ops->free_transport(conn->transport); 102 111 kfree(conn); 103 112 } ··· 246 237 { 247 238 struct ksmbd_conn *conn; 248 239 int rc, retry_count = 0, max_timeout = 120; 249 - int rcount = 1, bkt; 240 + int rcount, bkt; 250 241 251 242 retry_idle: 252 243 if (retry_count >= max_timeout) ··· 255 246 down_read(&conn_list_lock); 256 247 hash_for_each(conn_list, bkt, conn, hlist) { 257 248 if (conn->binding || xa_load(&conn->sessions, sess_id)) { 258 - if (conn == curr_conn) 259 - rcount = 2; 249 + rcount = (conn == curr_conn) ? 2 : 1; 260 250 if (atomic_read(&conn->req_running) >= rcount) { 261 251 rc = wait_event_timeout(conn->req_running_q, 262 252 atomic_read(&conn->req_running) < rcount,
-58
fs/smb/server/crypto_ctx.c
··· 28 28 crypto_free_aead(aead); 29 29 } 30 30 31 - static void free_shash(struct shash_desc *shash) 32 - { 33 - if (shash) { 34 - crypto_free_shash(shash->tfm); 35 - kfree(shash); 36 - } 37 - } 38 - 39 31 static struct crypto_aead *alloc_aead(int id) 40 32 { 41 33 struct crypto_aead *tfm = NULL; ··· 52 60 return tfm; 53 61 } 54 62 55 - static struct shash_desc *alloc_shash_desc(int id) 56 - { 57 - struct crypto_shash *tfm = NULL; 58 - struct shash_desc *shash; 59 - 60 - switch (id) { 61 - case CRYPTO_SHASH_CMACAES: 62 - tfm = crypto_alloc_shash("cmac(aes)", 0, 0); 63 - break; 64 - default: 65 - return NULL; 66 - } 67 - 68 - if (IS_ERR(tfm)) 69 - return NULL; 70 - 71 - shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), 72 - KSMBD_DEFAULT_GFP); 73 - if (!shash) 74 - crypto_free_shash(tfm); 75 - else 76 - shash->tfm = tfm; 77 - return shash; 78 - } 79 - 80 63 static void ctx_free(struct ksmbd_crypto_ctx *ctx) 81 64 { 82 65 int i; 83 66 84 - for (i = 0; i < CRYPTO_SHASH_MAX; i++) 85 - free_shash(ctx->desc[i]); 86 67 for (i = 0; i < CRYPTO_AEAD_MAX; i++) 87 68 free_aead(ctx->ccmaes[i]); 88 69 kfree(ctx); ··· 116 151 ctx_list.avail_ctx--; 117 152 spin_unlock(&ctx_list.ctx_lock); 118 153 ctx_free(ctx); 119 - } 120 - 121 - static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id) 122 - { 123 - struct ksmbd_crypto_ctx *ctx; 124 - 125 - if (id >= CRYPTO_SHASH_MAX) 126 - return NULL; 127 - 128 - ctx = ksmbd_find_crypto_ctx(); 129 - if (ctx->desc[id]) 130 - return ctx; 131 - 132 - ctx->desc[id] = alloc_shash_desc(id); 133 - if (ctx->desc[id]) 134 - return ctx; 135 - ksmbd_release_crypto_ctx(ctx); 136 - return NULL; 137 - } 138 - 139 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void) 140 - { 141 - return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES); 142 154 } 143 155 144 156 static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
-12
fs/smb/server/crypto_ctx.h
··· 6 6 #ifndef __CRYPTO_CTX_H__ 7 7 #define __CRYPTO_CTX_H__ 8 8 9 - #include <crypto/hash.h> 10 9 #include <crypto/aead.h> 11 - 12 - enum { 13 - CRYPTO_SHASH_CMACAES = 0, 14 - CRYPTO_SHASH_MAX, 15 - }; 16 10 17 11 enum { 18 12 CRYPTO_AEAD_AES_GCM = 16, ··· 17 23 struct ksmbd_crypto_ctx { 18 24 struct list_head list; 19 25 20 - struct shash_desc *desc[CRYPTO_SHASH_MAX]; 21 26 struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX]; 22 27 }; 23 - 24 - #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) 25 - 26 - #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) 27 28 28 29 #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) 29 30 #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) 30 31 31 32 void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx); 32 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); 33 33 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); 34 34 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); 35 35 void ksmbd_crypto_destroy(void);
-6
fs/smb/server/mgmt/user_config.c
··· 56 56 goto err_free; 57 57 58 58 if (resp_ext) { 59 - if (resp_ext->ngroups > NGROUPS_MAX) { 60 - pr_err("ngroups(%u) from login response exceeds max groups(%d)\n", 61 - resp_ext->ngroups, NGROUPS_MAX); 62 - goto err_free; 63 - } 64 - 65 59 user->sgid = kmemdup(resp_ext->____payload, 66 60 resp_ext->ngroups * sizeof(gid_t), 67 61 KSMBD_DEFAULT_GFP);
+9 -3
fs/smb/server/mgmt/user_session.c
··· 391 391 free_channel_list(sess); 392 392 kfree(sess->Preauth_HashValue); 393 393 ksmbd_release_id(&session_ida, sess->id); 394 + ida_destroy(&sess->tree_conn_ida); 394 395 kfree(sess); 395 396 } 396 397 ··· 548 547 struct ksmbd_session *sess; 549 548 550 549 sess = ksmbd_session_lookup(conn, id); 551 - if (!sess && conn->binding) 550 + if (!sess && conn->binding) { 552 551 sess = ksmbd_session_lookup_slowpath(id); 552 + if (sess && !xa_load(&sess->ksmbd_chann_list, (long)conn)) { 553 + ksmbd_user_session_put(sess); 554 + sess = NULL; 555 + } 556 + } 553 557 if (sess && sess->state != SMB2_SESSION_VALID) { 554 558 ksmbd_user_session_put(sess); 555 559 sess = NULL; ··· 671 665 if (!sess) 672 666 return NULL; 673 667 668 + ida_init(&sess->tree_conn_ida); 669 + 674 670 if (ksmbd_init_file_table(&sess->file_table)) 675 671 goto error; 676 672 ··· 691 683 ret = __init_smb2_session(sess); 692 684 if (ret) 693 685 goto error; 694 - 695 - ida_init(&sess->tree_conn_ida); 696 686 697 687 down_write(&sessions_table_lock); 698 688 hash_add(sessions_table, &sess->hlist, sess->id);
-1
fs/smb/server/server.c
··· 631 631 MODULE_LICENSE("GPL"); 632 632 MODULE_SOFTDEP("pre: nls"); 633 633 MODULE_SOFTDEP("pre: aes"); 634 - MODULE_SOFTDEP("pre: cmac"); 635 634 MODULE_SOFTDEP("pre: aead2"); 636 635 MODULE_SOFTDEP("pre: ccm"); 637 636 MODULE_SOFTDEP("pre: gcm");
+22 -31
fs/smb/server/smb2pdu.c
··· 2844 2844 dh_info->reconnected = true; 2845 2845 goto out; 2846 2846 } 2847 + ksmbd_put_durable_fd(dh_info->fp); 2848 + dh_info->fp = NULL; 2847 2849 } 2848 2850 2849 2851 if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || ··· 3016 3014 if (dh_info.reconnected == true) { 3017 3015 rc = smb2_check_durable_oplock(conn, share, dh_info.fp, 3018 3016 lc, sess->user, name); 3019 - if (rc) { 3020 - ksmbd_put_durable_fd(dh_info.fp); 3017 + if (rc) 3021 3018 goto err_out2; 3022 - } 3023 3019 3024 3020 rc = ksmbd_reopen_durable_fd(work, dh_info.fp); 3025 - if (rc) { 3026 - ksmbd_put_durable_fd(dh_info.fp); 3021 + if (rc) 3027 3022 goto err_out2; 3028 - } 3029 3023 3030 3024 fp = dh_info.fp; 3031 3025 3032 3026 if (ksmbd_override_fsids(work)) { 3033 3027 rc = -ENOMEM; 3034 - ksmbd_put_durable_fd(dh_info.fp); 3035 3028 goto err_out2; 3036 3029 } 3037 3030 3038 3031 file_info = FILE_OPENED; 3039 3032 3040 3033 rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); 3041 - ksmbd_put_durable_fd(fp); 3042 3034 if (rc) 3043 3035 goto err_out2; 3044 3036 ··· 3057 3061 } else { 3058 3062 if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && 3059 3063 req->CreateOptions & FILE_RANDOM_ACCESS_LE) 3060 - req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE); 3064 + req->CreateOptions &= ~FILE_SEQUENTIAL_ONLY_LE; 3061 3065 3062 3066 if (req->CreateOptions & 3063 3067 (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION | ··· 3071 3075 rc = -EINVAL; 3072 3076 goto err_out2; 3073 3077 } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { 3074 - req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); 3078 + req->CreateOptions &= ~FILE_NO_COMPRESSION_LE; 3075 3079 } 3076 3080 } 3077 3081 } ··· 3801 3805 smb2_set_err_rsp(work); 3802 3806 ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status); 3803 3807 } 3808 + 3809 + if (dh_info.reconnected) 3810 + ksmbd_put_durable_fd(dh_info.fp); 3804 3811 3805 3812 kfree(name); 3806 3813 kfree(lc); ··· 4820 4821 /* align next xattr entry at 4 byte bundary */ 4821 4822 alignment_bytes = ((next_offset + 3) & ~3) - next_offset; 4822 4823 if (alignment_bytes) { 4824 + if (buf_free_len < alignment_bytes) 4825 + break; 4823 4826 memset(ptr, '\0', alignment_bytes); 4824 4827 ptr += alignment_bytes; 4825 4828 next_offset += alignment_bytes; ··· 5746 5745 ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n", 5747 5746 addition_info); 5748 5747 5749 - pntsd = kzalloc(ALIGN(sizeof(struct smb_ntsd), 8), 5750 - KSMBD_DEFAULT_GFP); 5751 - if (!pntsd) 5752 - return -ENOMEM; 5753 - 5754 - pntsd->revision = cpu_to_le16(1); 5755 - pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED); 5756 - pntsd->osidoffset = 0; 5757 - pntsd->gsidoffset = 0; 5758 - pntsd->sacloffset = 0; 5759 - pntsd->dacloffset = 0; 5760 - 5761 - secdesclen = sizeof(struct smb_ntsd); 5762 - goto iov_pin; 5748 + rsp->hdr.Status = STATUS_NOT_SUPPORTED; 5749 + return -EINVAL; 5763 5750 } 5764 5751 5765 5752 if (work->next_smb2_rcv_hdr_off) { ··· 5814 5825 if (rc) 5815 5826 goto err_out; 5816 5827 5817 - iov_pin: 5818 5828 rsp->OutputBufferLength = cpu_to_le32(secdesclen); 5819 5829 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), 5820 5830 rsp, work->response_buf); ··· 7480 7492 lock_ele = req->locks; 7481 7493 7482 7494 ksmbd_debug(SMB, "lock count is %d\n", lock_count); 7483 - if (!lock_count) { 7495 + /* 7496 + * Cap lock_count at 64. The MS-SMB2 spec defines Open.LockSequenceArray 7497 + * as exactly 64 entries so 64 is the intended ceiling. No real workload 7498 + * comes close to this in a single request. 7499 + */ 7500 + if (!lock_count || lock_count > 64) { 7484 7501 err = -EINVAL; 7485 7502 goto out2; 7486 7503 } ··· 9060 9067 iov[0].iov_base = (char *)&hdr->ProtocolId; 9061 9068 iov[0].iov_len = len; 9062 9069 9063 - if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature)) 9064 - return 0; 9070 + ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature); 9065 9071 9066 9072 if (crypto_memneq(signature, signature_req, SMB2_SIGNATURE_SIZE)) { 9067 9073 pr_err("bad smb2 signature\n"); ··· 9111 9119 iov = &work->iov[work->iov_idx]; 9112 9120 } 9113 9121 9114 - if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, 9115 - signature)) 9116 - memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); 9122 + ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature); 9123 + memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); 9117 9124 } 9118 9125 9119 9126 /**
+48 -13
fs/smb/server/smbacl.c
··· 596 596 struct smb_sid *sid; 597 597 struct smb_ace *ntace; 598 598 int i, j; 599 + u16 ace_sz; 599 600 600 601 if (!fattr->cf_acls) 601 602 goto posix_default_acl; ··· 641 640 flags = 0x03; 642 641 643 642 ntace = (struct smb_ace *)((char *)pndace + *size); 644 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags, 643 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags, 645 644 pace->e_perm, 0777); 645 + if (check_add_overflow(*size, ace_sz, size)) 646 + break; 646 647 (*num_aces)++; 647 648 if (pace->e_tag == ACL_USER) 648 649 ntace->access_req |= ··· 653 650 if (S_ISDIR(fattr->cf_mode) && 654 651 (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) { 655 652 ntace = (struct smb_ace *)((char *)pndace + *size); 656 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 653 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 657 654 0x03, pace->e_perm, 0777); 655 + if (check_add_overflow(*size, ace_sz, size)) 656 + break; 658 657 (*num_aces)++; 659 658 if (pace->e_tag == ACL_USER) 660 659 ntace->access_req |= ··· 696 691 } 697 692 698 693 ntace = (struct smb_ace *)((char *)pndace + *size); 699 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b, 694 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b, 700 695 pace->e_perm, 0777); 696 + if (check_add_overflow(*size, ace_sz, size)) 697 + break; 701 698 (*num_aces)++; 702 699 if (pace->e_tag == ACL_USER) 703 700 ntace->access_req |= ··· 735 728 break; 736 729 737 730 memcpy((char *)pndace + size, ntace, nt_ace_size); 738 - size += nt_ace_size; 731 + if (check_add_overflow(size, nt_ace_size, &size)) 732 + break; 739 733 aces_size -= nt_ace_size; 740 734 ntace = (struct smb_ace *)((char *)ntace + nt_ace_size); 741 735 num_aces++; ··· 1114 1106 goto free_parent_pntsd; 1115 1107 } 1116 1108 1117 - aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, 1118 - KSMBD_DEFAULT_GFP); 1109 + aces_size = pdacl_size - sizeof(struct smb_acl); 1110 + 1111 + /* 1112 + * Validate num_aces against the DACL payload before allocating. 1113 + * Each ACE must be at least as large as its fixed-size header 1114 + * (up to the SID base), so num_aces cannot exceed the payload 1115 + * divided by the minimum ACE size. This mirrors the existing 1116 + * check in parse_dacl(). 1117 + */ 1118 + if (num_aces > aces_size / (offsetof(struct smb_ace, sid) + 1119 + offsetof(struct smb_sid, sub_auth) + 1120 + sizeof(__le16))) { 1121 + rc = -EINVAL; 1122 + goto free_parent_pntsd; 1123 + } 1124 + 1125 + aces_base = kmalloc_array(num_aces * 2, sizeof(struct smb_ace), 1126 + KSMBD_DEFAULT_GFP); 1119 1127 if (!aces_base) { 1120 1128 rc = -ENOMEM; 1121 1129 goto free_parent_pntsd; ··· 1140 1116 aces = (struct smb_ace *)aces_base; 1141 1117 parent_aces = (struct smb_ace *)((char *)parent_pdacl + 1142 1118 sizeof(struct smb_acl)); 1143 - aces_size = acl_len - sizeof(struct smb_acl); 1144 1119 1145 1120 if (pntsd_type & DACL_AUTO_INHERITED) 1146 1121 inherited_flags = INHERITED_ACE; ··· 1147 1124 for (i = 0; i < num_aces; i++) { 1148 1125 int pace_size; 1149 1126 1150 - if (offsetof(struct smb_ace, access_req) > aces_size) 1127 + if (aces_size < offsetof(struct smb_ace, sid) + 1128 + CIFS_SID_BASE_SIZE) 1151 1129 break; 1152 1130 1153 1131 pace_size = le16_to_cpu(parent_aces->size); 1154 - if (pace_size > aces_size) 1132 + if (pace_size > aces_size || 1133 + pace_size < offsetof(struct smb_ace, sid) + 1134 + CIFS_SID_BASE_SIZE) 1155 1135 break; 1156 1136 1157 1137 aces_size -= pace_size; ··· 1368 1342 ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); 1369 1343 aces_size = acl_size - sizeof(struct smb_acl); 1370 1344 for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { 1371 - if (offsetof(struct smb_ace, access_req) > aces_size) 1345 + if (offsetof(struct smb_ace, sid) + 1346 + aces_size < CIFS_SID_BASE_SIZE) 1372 1347 break; 1373 1348 ace_size = le16_to_cpu(ace->size); 1374 - if (ace_size > aces_size) 1349 + if (ace_size > aces_size || 1350 + ace_size < offsetof(struct smb_ace, sid) + 1351 + CIFS_SID_BASE_SIZE) 1375 1352 break; 1376 1353 aces_size -= ace_size; 1377 1354 granted |= le32_to_cpu(ace->access_req); ··· 1389 1360 ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); 1390 1361 aces_size = acl_size - sizeof(struct smb_acl); 1391 1362 for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { 1392 - if (offsetof(struct smb_ace, access_req) > aces_size) 1363 + if (offsetof(struct smb_ace, sid) + 1364 + aces_size < CIFS_SID_BASE_SIZE) 1393 1365 break; 1394 1366 ace_size = le16_to_cpu(ace->size); 1395 - if (ace_size > aces_size) 1367 + if (ace_size > aces_size || 1368 + ace_size < offsetof(struct smb_ace, sid) + 1369 + CIFS_SID_BASE_SIZE) 1396 1370 break; 1397 1371 aces_size -= ace_size; 1372 + 1373 + if (ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES) 1374 + break; 1398 1375 1399 1376 if (!compare_sids(&sid, &ace->sid) || 1400 1377 !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
+13 -3
fs/smb/server/transport_ipc.c
··· 13 13 #include <net/genetlink.h> 14 14 #include <linux/socket.h> 15 15 #include <linux/workqueue.h> 16 + #include <linux/overflow.h> 16 17 17 18 #include "vfs_cache.h" 18 19 #include "transport_ipc.h" ··· 497 496 { 498 497 struct ksmbd_rpc_command *resp = entry->response; 499 498 500 - msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz; 499 + if (check_add_overflow(sizeof(struct ksmbd_rpc_command), 500 + resp->payload_sz, &msg_sz)) 501 + return -EINVAL; 501 502 break; 502 503 } 503 504 case KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST: ··· 518 515 if (resp->payload_sz < resp->veto_list_sz) 519 516 return -EINVAL; 520 517 521 - msg_sz = sizeof(struct ksmbd_share_config_response) + 522 - resp->payload_sz; 518 + if (check_add_overflow(sizeof(struct ksmbd_share_config_response), 519 + resp->payload_sz, &msg_sz)) 520 + return -EINVAL; 523 521 } 524 522 break; 525 523 } ··· 529 525 struct ksmbd_login_response_ext *resp = entry->response; 530 526 531 527 if (resp->ngroups) { 528 + if (resp->ngroups < 0 || 529 + resp->ngroups > NGROUPS_MAX) { 530 + pr_err("ngroups(%d) from login response exceeds max groups(%d)\n", 531 + resp->ngroups, NGROUPS_MAX); 532 + return -EINVAL; 533 + } 532 534 msg_sz = sizeof(struct ksmbd_login_response_ext) + 533 535 resp->ngroups * sizeof(gid_t); 534 536 }
+1 -1
fs/smb/server/transport_rdma.c
··· 18 18 #include "smb_common.h" 19 19 #include "../common/smb2status.h" 20 20 #include "transport_rdma.h" 21 - #include "../common/smbdirect/smbdirect_public.h" 21 + #include "../smbdirect/public.h" 22 22 23 23 24 24 #define SMB_DIRECT_PORT_IWARP 5445
+1 -1
fs/smb/server/transport_rdma.h
··· 25 25 static inline unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt) { return 0; } 26 26 #endif 27 27 28 - #include "../common/smbdirect/smbdirect.h" 28 + #include "../smbdirect/smbdirect.h" 29 29 30 30 #endif /* __KSMBD_TRANSPORT_RDMA_H__ */
+3 -1
fs/smb/server/transport_tcp.c
··· 183 183 t = alloc_transport(client_sk); 184 184 if (!t) { 185 185 sock_release(client_sk); 186 + if (server_conf.max_connections) 187 + atomic_dec(&active_num_conn); 186 188 return -ENOMEM; 187 189 } 188 190 ··· 281 279 282 280 skip_max_ip_conns_limit: 283 281 if (server_conf.max_connections && 284 - atomic_inc_return(&active_num_conn) >= server_conf.max_connections) { 282 + atomic_inc_return(&active_num_conn) > server_conf.max_connections) { 285 283 pr_info_ratelimited("Limit the maximum number of connections(%u)\n", 286 284 atomic_read(&active_num_conn)); 287 285 atomic_dec(&active_num_conn);
+18
fs/smb/smbdirect/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-or-later 2 + # 3 + # Makefile for smbdirect support 4 + # 5 + 6 + obj-$(CONFIG_SMBDIRECT) += smbdirect.o 7 + 8 + smbdirect-y := \ 9 + socket.o \ 10 + connection.o \ 11 + mr.o \ 12 + rw.o \ 13 + debug.o \ 14 + connect.o \ 15 + listen.o \ 16 + accept.o \ 17 + devices.o \ 18 + main.o