From eebff916f07775b2ecd9186439e69a70af24630b Mon Sep 17 00:00:00 2001 From: Marios Makassikis Date: Thu, 12 Aug 2021 10:12:35 +0900 Subject: ksmbd: Fix multi-protocol negotiation To negotiate either the SMB2 protocol or SMB protocol, a client must send a SMB_COM_NEGOTIATE message containing the list of dialects it supports, to which the server will respond with either a SMB_COM_NEGOTIATE or a SMB2_NEGOTIATE response. The current implementation responds with the highest common dialect, rather than looking explicitly for "SMB 2.???" and "SMB 2.002", as indicated in [MS-SMB2]: [MS-SMB2] 3.3.5.3.1: If the server does not implement the SMB 2.1 or 3.x dialect family, processing MUST continue as specified in 3.3.5.3.2. Otherwise, the server MUST scan the dialects provided for the dialect string "SMB 2.???". If the string is not present, continue to section 3.3.5.3.2. If the string is present, the server MUST respond with an SMB2 NEGOTIATE Response as specified in 2.2.4. [MS-SMB2] 3.3.5.3.2: The server MUST scan the dialects provided for the dialect string "SMB 2.002". If the string is present, the client understands SMB2, and the server MUST respond with an SMB2 NEGOTIATE Response. This is an issue if a client attempts to negotiate SMB3.1.1 using a SMB_COM_NEGOTIATE, as it will trigger the following NULL pointer dereference: 8<--- cut here --- Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = 1917455e [00000000] *pgd=00000000 Internal error: Oops: 17 [#1] ARM CPU: 0 PID: 60 Comm: kworker/0:1 Not tainted 5.4.60-00027-g0518c02b5c5b #35 Hardware name: Marvell Kirkwood (Flattened Device Tree) Workqueue: ksmbd-io handle_ksmbd_work PC is at ksmbd_gen_preauth_integrity_hash+0x24/0x190 LR is at smb3_preauth_hash_rsp+0x50/0xa0 pc : [<802b7044>] lr : [<802d6ac0>] psr: 40000013 sp : bf199ed8 ip : 00000000 fp : 80d1edb0 r10: 80a3471b r9 : 8091af16 r8 : 80d70640 r7 : 00000072 r6 : be95e198 r5 : ca000000 r4 : b97fee00 r3 : 00000000 r2 : 00000002 r1 : b97fea00 r0 : b97fee00 Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: 3e7f4000 DAC: 00000055 Process kworker/0:1 (pid: 60, stack limit = 0x3dd1fdb4) Stack: (0xbf199ed8 to 0xbf19a000) 9ec0: b97fee00 00000000 9ee0: be95e198 00000072 80d70640 802d6ac0 b3da2680 b97fea00 424d53ff be95e140 9f00: b97fee00 802bd7b0 bf10fa58 80128a78 00000000 000001c8 b6220000 bf0b7720 9f20: be95e198 80d0c410 bf7e2a00 00000000 00000000 be95e19c 80d0c370 80123b90 9f40: bf0b7720 be95e198 bf0b7720 bf0b7734 80d0c410 bf198000 80d0c424 80d116e0 9f60: bf10fa58 801240c0 00000000 bf10fa40 bf1463a0 bf198000 bf0b7720 80123ed0 9f80: bf077ee4 bf10fa58 00000000 80127f80 bf1463a0 80127e88 00000000 00000000 9fa0: 00000000 00000000 00000000 801010d0 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 [<802b7044>] (ksmbd_gen_preauth_integrity_hash) from [<802d6ac0>] (smb3_preauth_hash_rsp+0x50/0xa0) [<802d6ac0>] (smb3_preauth_hash_rsp) from [<802bd7b0>] (handle_ksmbd_work+0x348/0x3f8) [<802bd7b0>] (handle_ksmbd_work) from [<80123b90>] (process_one_work+0x160/0x200) [<80123b90>] (process_one_work) from [<801240c0>] (worker_thread+0x1f0/0x2e4) [<801240c0>] (worker_thread) from [<80127f80>] (kthread+0xf8/0x10c) [<80127f80>] (kthread) from [<801010d0>] (ret_from_fork+0x14/0x24) Exception stack(0xbf199fb0 to 0xbf199ff8) 9fa0: 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: e1855803 e5d13003 e1855c03 e5903094 (e1d330b0) ---[ end trace 8d03be3ed09e5699 ]--- Kernel panic - not syncing: Fatal exception smb3_preauth_hash_rsp() panics because conn->preauth_info is only allocated when processing a SMB2 NEGOTIATE request. Fix this by splitting the smb_protos array into two, each containing only SMB1 and SMB2 dialects respectively. While here, make ksmbd_negotiate_smb_dialect() static as it not called from anywhere else. Signed-off-by: Marios Makassikis Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb_common.c | 53 ++++++++++++++++++++++++++++++++++----------------- fs/ksmbd/smb_common.h | 1 - 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c index 24c6bb476f6e..b108b918ec84 100644 --- a/fs/ksmbd/smb_common.c +++ b/fs/ksmbd/smb_common.c @@ -30,7 +30,7 @@ struct smb_protocol { __u16 prot_id; }; -static struct smb_protocol smb_protos[] = { +static struct smb_protocol smb1_protos[] = { { SMB21_PROT, "\2SMB 2.1", @@ -43,6 +43,15 @@ static struct smb_protocol smb_protos[] = { "SMB2_22", SMB2X_PROT_ID }, +}; + +static struct smb_protocol smb2_protos[] = { + { + SMB21_PROT, + "\2SMB 2.1", + "SMB2_10", + SMB21_PROT_ID + }, { SMB30_PROT, "\2SMB 3.0", @@ -90,14 +99,24 @@ inline int ksmbd_max_protocol(void) int ksmbd_lookup_protocol_idx(char *str) { - int offt = ARRAY_SIZE(smb_protos) - 1; + int offt = ARRAY_SIZE(smb1_protos) - 1; int len = strlen(str); while (offt >= 0) { - if (!strncmp(str, smb_protos[offt].prot, len)) { + if (!strncmp(str, smb1_protos[offt].prot, len)) { + ksmbd_debug(SMB, "selected %s dialect idx = %d\n", + smb1_protos[offt].prot, offt); + return smb1_protos[offt].index; + } + offt--; + } + + offt = ARRAY_SIZE(smb2_protos) - 1; + while (offt >= 0) { + if (!strncmp(str, smb2_protos[offt].prot, len)) { ksmbd_debug(SMB, "selected %s dialect idx = %d\n", - smb_protos[offt].prot, offt); - return smb_protos[offt].index; + smb2_protos[offt].prot, offt); + return smb2_protos[offt].index; } offt--; } @@ -169,7 +188,7 @@ static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count) int i, seq_num, bcount, next; char *dialect; - for (i = ARRAY_SIZE(smb_protos) - 1; i >= 0; i--) { + for (i = ARRAY_SIZE(smb1_protos) - 1; i >= 0; i--) { seq_num = 0; next = 0; dialect = cli_dialects; @@ -178,14 +197,14 @@ static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count) dialect = next_dialect(dialect, &next); ksmbd_debug(SMB, "client requested dialect %s\n", dialect); - if (!strcmp(dialect, smb_protos[i].name)) { - if (supported_protocol(smb_protos[i].index)) { + if (!strcmp(dialect, smb1_protos[i].name)) { + if (supported_protocol(smb1_protos[i].index)) { ksmbd_debug(SMB, "selected %s dialect\n", - smb_protos[i].name); - if (smb_protos[i].index == SMB1_PROT) + smb1_protos[i].name); + if (smb1_protos[i].index == SMB1_PROT) return seq_num; - return smb_protos[i].prot_id; + return smb1_protos[i].prot_id; } } seq_num++; @@ -201,19 +220,19 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count) int i; int count; - for (i = ARRAY_SIZE(smb_protos) - 1; i >= 0; i--) { + for (i = ARRAY_SIZE(smb2_protos) - 1; i >= 0; i--) { count = le16_to_cpu(dialects_count); while (--count >= 0) { ksmbd_debug(SMB, "client requested dialect 0x%x\n", le16_to_cpu(cli_dialects[count])); if (le16_to_cpu(cli_dialects[count]) != - smb_protos[i].prot_id) + smb2_protos[i].prot_id) continue; - if (supported_protocol(smb_protos[i].index)) { + if (supported_protocol(smb2_protos[i].index)) { ksmbd_debug(SMB, "selected %s dialect\n", - smb_protos[i].name); - return smb_protos[i].prot_id; + smb2_protos[i].name); + return smb2_protos[i].prot_id; } } } @@ -221,7 +240,7 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count) return BAD_PROT_ID; } -int ksmbd_negotiate_smb_dialect(void *buf) +static int ksmbd_negotiate_smb_dialect(void *buf) { __le32 proto; diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h index b8c350725905..c4219c3432e2 100644 --- a/fs/ksmbd/smb_common.h +++ b/fs/ksmbd/smb_common.h @@ -498,7 +498,6 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn); int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count); -int ksmbd_negotiate_smb_dialect(void *buf); int ksmbd_init_smb_server(struct ksmbd_work *work); bool ksmbd_pdu_size_has_room(unsigned int pdu); -- cgit From f4228b678b410a401148f9ad9911d0013fa0f24e Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 12 Aug 2021 10:16:40 +0900 Subject: ksmbd: change int data type to boolean Change data type of function that return only 0 or 1 to boolean. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 32 ++++++++++++++++---------------- fs/ksmbd/smb2pdu.h | 6 +++--- fs/ksmbd/smb_common.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 636570ecfa31..0de4163978ce 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -58,18 +58,18 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp) * * Return: 1 if valid session id, otherwise 0 */ -static inline int check_session_id(struct ksmbd_conn *conn, u64 id) +static inline bool check_session_id(struct ksmbd_conn *conn, u64 id) { struct ksmbd_session *sess; if (id == 0 || id == -1) - return 0; + return false; sess = ksmbd_session_lookup_all(conn, id); if (sess) - return 1; + return true; pr_err("Invalid user session id: %llu\n", id); - return 0; + return false; } struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn) @@ -145,45 +145,45 @@ void smb2_set_err_rsp(struct ksmbd_work *work) * is_smb2_neg_cmd() - is it smb2 negotiation command * @work: smb work containing smb header * - * Return: 1 if smb2 negotiation command, otherwise 0 + * Return: true if smb2 negotiation command, otherwise false */ -int is_smb2_neg_cmd(struct ksmbd_work *work) +bool is_smb2_neg_cmd(struct ksmbd_work *work) { struct smb2_hdr *hdr = work->request_buf; /* is it SMB2 header ? */ if (hdr->ProtocolId != SMB2_PROTO_NUMBER) - return 0; + return false; /* make sure it is request not response message */ if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) - return 0; + return false; if (hdr->Command != SMB2_NEGOTIATE) - return 0; + return false; - return 1; + return true; } /** * is_smb2_rsp() - is it smb2 response * @work: smb work containing smb response buffer * - * Return: 1 if smb2 response, otherwise 0 + * Return: true if smb2 response, otherwise false */ -int is_smb2_rsp(struct ksmbd_work *work) +bool is_smb2_rsp(struct ksmbd_work *work) { struct smb2_hdr *hdr = work->response_buf; /* is it SMB2 header ? */ if (hdr->ProtocolId != SMB2_PROTO_NUMBER) - return 0; + return false; /* make sure it is response not request message */ if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)) - return 0; + return false; - return 1; + return true; } /** @@ -8291,7 +8291,7 @@ int smb3_encrypt_resp(struct ksmbd_work *work) return rc; } -int smb3_is_transform_hdr(void *buf) +bool smb3_is_transform_hdr(void *buf) { struct smb2_transform_hdr *trhdr = buf; diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h index 89019f67234c..bcec845b03f3 100644 --- a/fs/ksmbd/smb2pdu.h +++ b/fs/ksmbd/smb2pdu.h @@ -1638,8 +1638,8 @@ void init_smb2_max_read_size(unsigned int sz); void init_smb2_max_write_size(unsigned int sz); void init_smb2_max_trans_size(unsigned int sz); -int is_smb2_neg_cmd(struct ksmbd_work *work); -int is_smb2_rsp(struct ksmbd_work *work); +bool is_smb2_neg_cmd(struct ksmbd_work *work); +bool is_smb2_rsp(struct ksmbd_work *work); u16 get_smb2_cmd_val(struct ksmbd_work *work); void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err); @@ -1664,7 +1664,7 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status); struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn); void smb3_preauth_hash_rsp(struct ksmbd_work *work); -int smb3_is_transform_hdr(void *buf); +bool smb3_is_transform_hdr(void *buf); int smb3_decrypt_req(struct ksmbd_work *work); int smb3_encrypt_resp(struct ksmbd_work *work); bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work); diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h index c4219c3432e2..eb667d85558e 100644 --- a/fs/ksmbd/smb_common.h +++ b/fs/ksmbd/smb_common.h @@ -473,7 +473,7 @@ struct smb_version_ops { void (*set_sign_rsp)(struct ksmbd_work *work); int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn); int (*generate_encryptionkey)(struct ksmbd_session *sess); - int (*is_transform_hdr)(void *buf); + bool (*is_transform_hdr)(void *buf); int (*decrypt_req)(struct ksmbd_work *work); int (*encrypt_resp)(struct ksmbd_work *work); }; -- cgit From 5ec3df8e98f51e21fe1f46633b6085897f9b040e Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 12 Aug 2021 10:17:39 +0900 Subject: ksmbd: update the comment for smb2_get_ksmbd_tcon() Update the comment for smb2_get_ksmbd_tcon(). Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 0de4163978ce..4ac4fe22edde 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -85,10 +85,11 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn } /** - * smb2_get_ksmbd_tcon() - get tree connection information for a tree id + * smb2_get_ksmbd_tcon() - get tree connection information using a tree id. * @work: smb work * - * Return: matching tree connection on success, otherwise error + * Return: 0 if there is a tree connection matched or these are + * skipable commands, otherwise error */ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) { -- cgit From c6ce2b5716b04cc6ec36fa7e3c3b851368e6ee7c Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 12 Aug 2021 10:18:18 +0900 Subject: ksmbd: use proper errno instead of -1 in smb2_get_ksmbd_tcon() Use proper errno instead of -1 in smb2_get_ksmbd_tcon(). Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 4ac4fe22edde..8f6ffa427ebf 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -106,14 +106,14 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) if (xa_empty(&work->sess->tree_conns)) { ksmbd_debug(SMB, "NO tree connected\n"); - return -1; + return -ENOENT; } tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId); work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id); if (!work->tcon) { pr_err("Invalid tid %d\n", tree_id); - return -1; + return -EINVAL; } return 1; -- cgit From 777cad1604d68ed4379ec899d1f7d2f6a29f01f0 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 13 Aug 2021 08:15:33 +0900 Subject: ksmbd: remove select FS_POSIX_ACL in Kconfig ksmbd is forcing to turn on FS_POSIX_ACL in Kconfig to use vfs acl functions(posix_acl_alloc, get_acl, set_posix_acl). OpenWRT and other platform doesn't use acl and this config is disable by default in kernel. This patch use IS_ENABLED() to know acl config is enable and use acl function if it is enable. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/Kconfig | 1 - fs/ksmbd/smb2pdu.c | 9 ++++-- fs/ksmbd/smbacl.c | 80 +++++++++++++++++++++++++++++++----------------------- fs/ksmbd/vfs.c | 9 ++++++ 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig index e9a5ac01b6e0..b83cbd756ae5 100644 --- a/fs/ksmbd/Kconfig +++ b/fs/ksmbd/Kconfig @@ -19,7 +19,6 @@ config SMB_SERVER select CRYPTO_GCM select ASN1 select OID_REGISTRY - select FS_POSIX_ACL default n help Choose Y here if you want to allow SMB3 compliant clients diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 8f6ffa427ebf..0131997c2177 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -2386,11 +2386,14 @@ static void ksmbd_acls_fattr(struct smb_fattr *fattr, struct inode *inode) fattr->cf_uid = inode->i_uid; fattr->cf_gid = inode->i_gid; fattr->cf_mode = inode->i_mode; + fattr->cf_acls = NULL; fattr->cf_dacls = NULL; - fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS); - if (S_ISDIR(inode->i_mode)) - fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT); + if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) { + fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS); + if (S_ISDIR(inode->i_mode)) + fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT); + } } /** diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c index fa99d950a6f2..2ca3714c518e 100644 --- a/fs/ksmbd/smbacl.c +++ b/fs/ksmbd/smbacl.c @@ -533,22 +533,29 @@ static void parse_dacl(struct user_namespace *user_ns, if (acl_state.users->n || acl_state.groups->n) { acl_state.mask.allow = 0x07; - fattr->cf_acls = posix_acl_alloc(acl_state.users->n + - acl_state.groups->n + 4, GFP_KERNEL); - if (fattr->cf_acls) { - cf_pace = fattr->cf_acls->a_entries; - posix_state_to_acl(&acl_state, cf_pace); + + if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) { + fattr->cf_acls = + posix_acl_alloc(acl_state.users->n + + acl_state.groups->n + 4, GFP_KERNEL); + if (fattr->cf_acls) { + cf_pace = fattr->cf_acls->a_entries; + posix_state_to_acl(&acl_state, cf_pace); + } } } if (default_acl_state.users->n || default_acl_state.groups->n) { default_acl_state.mask.allow = 0x07; - fattr->cf_dacls = - posix_acl_alloc(default_acl_state.users->n + - default_acl_state.groups->n + 4, GFP_KERNEL); - if (fattr->cf_dacls) { - cf_pdace = fattr->cf_dacls->a_entries; - posix_state_to_acl(&default_acl_state, cf_pdace); + + if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) { + fattr->cf_dacls = + posix_acl_alloc(default_acl_state.users->n + + default_acl_state.groups->n + 4, GFP_KERNEL); + if (fattr->cf_dacls) { + cf_pdace = fattr->cf_dacls->a_entries; + posix_state_to_acl(&default_acl_state, cf_pdace); + } } } free_acl_state(&acl_state); @@ -1221,31 +1228,36 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, granted = GENERIC_ALL_FLAGS; } - posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS); - if (posix_acls && !found) { - unsigned int id = -1; - - pa_entry = posix_acls->a_entries; - for (i = 0; i < posix_acls->a_count; i++, pa_entry++) { - if (pa_entry->e_tag == ACL_USER) - id = from_kuid(user_ns, - pa_entry->e_uid); - else if (pa_entry->e_tag == ACL_GROUP) - id = from_kgid(user_ns, - pa_entry->e_gid); - else - continue; - - if (id == uid) { - mode_to_access_flags(pa_entry->e_perm, 0777, &access_bits); - if (!access_bits) - access_bits = SET_MINIMUM_RIGHTS; - goto check_access_bits; + if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) { + posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS); + if (posix_acls && !found) { + unsigned int id = -1; + + pa_entry = posix_acls->a_entries; + for (i = 0; i < posix_acls->a_count; i++, pa_entry++) { + if (pa_entry->e_tag == ACL_USER) + id = from_kuid(user_ns, + pa_entry->e_uid); + else if (pa_entry->e_tag == ACL_GROUP) + id = from_kgid(user_ns, + pa_entry->e_gid); + else + continue; + + if (id == uid) { + mode_to_access_flags(pa_entry->e_perm, + 0777, + &access_bits); + if (!access_bits) + access_bits = + SET_MINIMUM_RIGHTS; + goto check_access_bits; + } } } + if (posix_acls) + posix_acl_release(posix_acls); } - if (posix_acls) - posix_acl_release(posix_acls); if (!found) { if (others_ace) { @@ -1308,7 +1320,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry); /* Update posix acls */ - if (fattr.cf_dacls) { + if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) { rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, fattr.cf_acls); if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c index 612c52d7a01b..aee28ee6b19c 100644 --- a/fs/ksmbd/vfs.c +++ b/fs/ksmbd/vfs.c @@ -1365,6 +1365,9 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac struct xattr_acl_entry *xa_entry; int i; + if (!IS_ENABLED(CONFIG_FS_POSIX_ACL)) + return NULL; + posix_acls = get_acl(inode, acl_type); if (!posix_acls) return NULL; @@ -1811,6 +1814,9 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns, struct posix_acl *acls; int rc; + if (!IS_ENABLED(CONFIG_FS_POSIX_ACL)) + return -EOPNOTSUPP; + ksmbd_debug(SMB, "Set posix acls\n"); rc = init_acl_state(&acl_state, 1); if (rc) @@ -1858,6 +1864,9 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns, struct posix_acl_entry *pace; int rc, i; + if (!IS_ENABLED(CONFIG_FS_POSIX_ACL)) + return -EOPNOTSUPP; + acls = get_acl(parent_inode, ACL_TYPE_DEFAULT); if (!acls) return -ENOENT; -- cgit From 323b1ea10263e5f11c9fb12e25f6d8beb327228c Mon Sep 17 00:00:00 2001 From: Hyunchul Lee Date: Thu, 12 Aug 2021 10:23:08 +0900 Subject: ksmbd: smbd: fix kernel oops during server shutdown if server shutdown happens in the situation that there are connections, workqueue could be destroyed before queueing disconnect work. Signed-off-by: Hyunchul Lee Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/transport_rdma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c index f2ae6bae83f1..58f530056ac0 100644 --- a/fs/ksmbd/transport_rdma.c +++ b/fs/ksmbd/transport_rdma.c @@ -329,7 +329,8 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work) static void smb_direct_disconnect_rdma_connection(struct smb_direct_transport *t) { - queue_work(smb_direct_wq, &t->disconnect_work); + if (t->status == SMB_DIRECT_CS_CONNECTED) + queue_work(smb_direct_wq, &t->disconnect_work); } static void smb_direct_send_immediate_work(struct work_struct *work) @@ -1415,7 +1416,7 @@ static void smb_direct_disconnect(struct ksmbd_transport *t) ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", st->cm_id); - smb_direct_disconnect_rdma_connection(st); + smb_direct_disconnect_rdma_work(&st->disconnect_work); wait_event_interruptible(st->wait_status, st->status == SMB_DIRECT_CS_DISCONNECTED); free_transport(st); -- cgit From 668fff017233ed7d1bc684a23cdf2875be1b5aea Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 12 Aug 2021 11:32:28 +0900 Subject: ksmbd: update SMB3 multi-channel support in ksmbd.rst ksmbd start supporting SMB3 Multi-channel feature. Mark it as Partially supported till replay/retry mechanisms are implemented. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- Documentation/filesystems/cifs/ksmbd.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/filesystems/cifs/ksmbd.rst b/Documentation/filesystems/cifs/ksmbd.rst index 1e111efecd45..a1326157d53f 100644 --- a/Documentation/filesystems/cifs/ksmbd.rst +++ b/Documentation/filesystems/cifs/ksmbd.rst @@ -84,7 +84,8 @@ SMB3 encryption(CCM, GCM) Supported. (CCM and GCM128 supported, GCM256 in progress) SMB direct(RDMA) Partially Supported. SMB3 Multi-channel is required to connect to Windows client. -SMB3 Multi-channel In Progress. +SMB3 Multi-channel Partially Supported. Planned to implement + replay/retry mechanisms for future. SMB3.1.1 POSIX extension Supported. ACLs Partially Supported. only DACLs available, SACLs (auditing) is planned for the future. For -- cgit From 29668d7e9d842be722a4c0416bb577828026ce4f Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 17 Aug 2021 13:06:38 +0900 Subject: MAINTAINERS: add git adddress of ksmbd Add missing git address of ksmbd. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6691ac75fce5..85af3ce6a28e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9945,6 +9945,7 @@ M: Steve French M: Hyunchul Lee L: linux-cifs@vger.kernel.org S: Maintained +T: git git://git.samba.org/ksmbd.git F: fs/ksmbd/ KERNEL UNIT TESTING FRAMEWORK (KUnit) -- cgit From a9a27d4ab3de2a6a81bad4b158c74a554d78e89b Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 20 Aug 2021 15:38:06 +0900 Subject: ksmbd: don't set FILE DELETE and FILE_DELETE_CHILD in access mask by default When there is no dacl in request, ksmbd send dacl that coverted by using file permission. This patch don't set FILE DELETE and FILE_DELETE_CHILD in access mask by default. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smbacl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c index 2ca3714c518e..20455d810523 100644 --- a/fs/ksmbd/smbacl.c +++ b/fs/ksmbd/smbacl.c @@ -731,7 +731,6 @@ static void set_mode_dacl(struct user_namespace *user_ns, ace_size = fill_ace_for_sid(pace, sid, ACCESS_ALLOWED, 0, fattr->cf_mode, 0700); pace->sid.sub_auth[pace->sid.num_subauth++] = cpu_to_le32(uid); - pace->access_req |= FILE_DELETE_LE | FILE_DELETE_CHILD_LE; pace->size = cpu_to_le16(ace_size + 4); size += le16_to_cpu(pace->size); pace = (struct smb_ace *)((char *)pndace + size); @@ -752,7 +751,6 @@ static void set_mode_dacl(struct user_namespace *user_ns, /* creator owner */ size += fill_ace_for_sid(pace, &creator_owner, ACCESS_ALLOWED, 0x0b, fattr->cf_mode, 0700); - pace->access_req |= FILE_DELETE_LE | FILE_DELETE_CHILD_LE; pace = (struct smb_ace *)((char *)pndace + size); /* creator group */ -- cgit