From 01cf30825c8729884090151ab97f1c9c5d14a8bc Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 1 Jul 2021 12:22:47 -0500 Subject: cifs: make locking consistent around the server session status There were three places where we were not taking the spinlock around updates to server->tcpStatus when it was being modified. To be consistent (also removes Coverity warning) and to remove possibility of race best to lock all places where it is updated. Two of the three were in initialization of the field and can't race - but added lock around the other. Addresses-Coverity: 1399512 ("Data race condition") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 3 ++- fs/cifs/connect.c | 5 +++++ fs/cifs/transport.c | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 3100f8b66e60..921680fb7931 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -577,6 +577,7 @@ struct TCP_Server_Info { char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; struct smb_version_operations *ops; struct smb_version_values *vals; + /* updates to tcpStatus protected by GlobalMid_Lock */ enum statusEnum tcpStatus; /* what we think the status is */ char *hostname; /* hostname portion of UNC string */ struct socket *ssocket; @@ -1785,7 +1786,7 @@ require use of the stronger protocol */ * list operations on pending_mid_q and oplockQ * updates to XID counters, multiplex id and SMB sequence numbers * list operations on global DnotifyReqList - * updates to ses->status + * updates to ses->status and TCP_Server_Info->tcpStatus * updates to server->CurrentMid * tcp_ses_lock protects: * list operations on tcp and SMB session lists diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5d269f583dac..01dc45178f66 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1403,6 +1403,11 @@ smbd_connected: goto out_err_crypto_release; } tcp_ses->min_offload = ctx->min_offload; + /* + * at this point we are the only ones with the pointer + * to the struct since the kernel thread not created yet + * no need to spinlock this update of tcpStatus + */ tcp_ses->tcpStatus = CifsNeedNegotiate; if ((ctx->max_credits < 20) || (ctx->max_credits > 60000)) diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index f65f9a692ca2..75a95de320cf 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -431,7 +431,9 @@ unmask: * be taken as the remainder of this one. We need to kill the * socket so the server throws away the partial SMB */ + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsNeedReconnect; + spin_unlock(&GlobalMid_Lock); trace_smb3_partial_send_reconnect(server->CurrentMid, server->conn_id, server->hostname); } -- cgit v1.2.3-59-g8ed1b From 819f916c835d0d022117ad97cb3a658546352ab8 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 1 Jul 2021 17:46:23 -0500 Subject: cifs: clarify SMB1 code for UnixCreateHardLink Coverity complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes). This doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711529 ("Out of bounds read") Reviewed-by: Ronnie Sahlberg Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 1 + fs/cifs/cifssmb.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 0923f72d27e9..f6e235001358 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1785,6 +1785,7 @@ struct smb_com_transaction2_sfi_req { __u16 Fid; __le16 InformationLevel; __u16 Reserved4; + __u8 payload[]; } __attribute__((packed)); struct smb_com_transaction2_sfi_rsp { diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 58ebec4d4413..ea12fa6eacb6 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3009,7 +3009,8 @@ createHardLinkRetry: InformationLevel) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ + data_offset = (char *)pSMB + offset + 4; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = cifsConvertToUTF16((__le16 *) data_offset, fromName, -- cgit v1.2.3-59-g8ed1b From ded2d99cef169a12a1d3961a540728675f525846 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 1 Jul 2021 20:44:27 -0500 Subject: CIFS: Clarify SMB1 code for UnixCreateSymLink Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for creating SMB1 symlinks when using the Unix extensions. This doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711530 ("Out of bounds read") Reviewed-by: Ronnie Sahlberg Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index ea12fa6eacb6..a14d3f533301 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2925,7 +2925,8 @@ createSymLinkRetry: InformationLevel) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ + data_offset = (char *)pSMB + offset + 4; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = cifsConvertToUTF16((__le16 *) data_offset, toName, -- cgit v1.2.3-59-g8ed1b From b019e1187ce4bb1f120cbea1a412d8aadb499260 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 1 Jul 2021 21:01:19 -0500 Subject: CIFS: Clarify SMB1 code for UnixSetPathInfo Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for doing SetPathInfo (setattr) when using the Unix extensions. This doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711528 ("Out of bounds read") Reviewed-by: Ronnie Sahlberg Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a14d3f533301..22b8c12962fa 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -6064,9 +6064,8 @@ setPermsRetry: param_offset = offsetof(struct smb_com_transaction2_spi_req, InformationLevel) - 4; offset = param_offset + params; - data_offset = - (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol + - offset); + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ + data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4); memset(data_offset, 0, count); pSMB->DataOffset = cpu_to_le16(offset); pSMB->ParameterOffset = cpu_to_le16(param_offset); -- cgit v1.2.3-59-g8ed1b From 90810c25cf028bbd7e8abd9903c37610ef7072c7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 3 Jul 2021 15:49:35 -0500 Subject: smb3: fix typo in header file Although it compiles, the test robot correctly noted: 'cifsacl.h' file not found with include; use "quotes" instead Reported-by: kernel test robot Signed-off-by: Steve French --- fs/cifs/smb2pdu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index a5c48b85549a..ba75e65924ac 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -13,7 +13,7 @@ #define _SMB2PDU_H #include -#include +#include "cifsacl.h" /* * Note that, due to trying to use names similar to the protocol specifications, -- cgit v1.2.3-59-g8ed1b From e3973ea3a7c218c1e92bdbfe1da934ef69d7a4ed Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 6 Jul 2021 21:27:26 -0500 Subject: CIFS: Clarify SMB1 code for SetFileSize Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for setting the file size using SMB1. This changeset doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711525 ("Out of bounds write") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 22b8c12962fa..a513a89aad1a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5628,9 +5628,9 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, pSMB->TotalDataCount = pSMB->DataCount; pSMB->TotalParameterCount = pSMB->ParameterCount; pSMB->ParameterOffset = cpu_to_le16(param_offset); + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ parm_data = - (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) - + offset); + (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4); pSMB->DataOffset = cpu_to_le16(offset); parm_data->FileSize = cpu_to_le64(size); pSMB->Fid = cfile->fid.netfid; -- cgit v1.2.3-59-g8ed1b From 2a780e8b64874ae5b4201a491799aef838da7bdd Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 6 Jul 2021 21:42:08 -0500 Subject: CIFS: Clarify SMB1 code for delete Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for SMB1 SetFileDisposition (which is used to unlink a file by setting the delete on close flag). This changeset doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711524 ("Out of bounds write") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a513a89aad1a..0863238ddd20 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5763,7 +5763,8 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ + data_offset = (char *)(pSMB) + offset + 4; count = 1; pSMB->MaxParameterCount = cpu_to_le16(2); -- cgit v1.2.3-59-g8ed1b From f371793d6e13a1387b83a72d7bb2c0e3a9ea654f Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 7 Jul 2021 13:34:47 -0500 Subject: CIFS: Clarify SMB1 code for rename open file Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for SMB1 RenameOpenFile. This changeset doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711521 ("Out of bounds write") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0863238ddd20..16bd4cf3bceb 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2767,7 +2767,8 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ + data_offset = (char *)(pSMB) + offset + 4; rename_info = (struct set_file_rename *) data_offset; pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */ -- cgit v1.2.3-59-g8ed1b From d4dc277c480c1faf87d452467d16f513b7ae2fb8 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 7 Jul 2021 14:03:54 -0500 Subject: CIFS: Clarify SMB1 code for POSIX Lock Coverity also complains about the way we calculate the offset (starting from the address of a 4 byte array within the header structure rather than from the beginning of the struct plus 4 bytes) for SMB1 PosixLock. This changeset doesn't change the address but makes it slightly clearer. Addresses-Coverity: 711520 ("Out of bounds write") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 16bd4cf3bceb..f72e3b3dca69 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2537,8 +2537,9 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, pSMB->TotalDataCount = pSMB->DataCount; pSMB->TotalParameterCount = pSMB->ParameterCount; pSMB->ParameterOffset = cpu_to_le16(param_offset); + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ parm_data = (struct cifs_posix_lock *) - (((char *) &pSMB->hdr.Protocol) + offset); + (((char *)pSMB) + offset + 4); parm_data->lock_type = cpu_to_le16(lock_type); if (waitFlag) { -- cgit v1.2.3-59-g8ed1b From e0a3cbcd5cef00cace01546cc6eaaa3b31940da9 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 8 Jul 2021 09:24:16 +1000 Subject: cifs: use helpers when parsing uid/gid mount options and validate them Use the nice helpers to initialize and the uid/gid/cred_uid when passed as mount arguments. Signed-off-by: Ronnie Sahlberg Acked-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/fs_context.c | 24 +++++++++++++++++++----- fs/cifs/fs_context.h | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c index 92d4ab029c91..553adfbcc22a 100644 --- a/fs/cifs/fs_context.c +++ b/fs/cifs/fs_context.c @@ -322,7 +322,6 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx new_ctx->UNC = NULL; new_ctx->source = NULL; new_ctx->iocharset = NULL; - /* * Make sure to stay in sync with smb3_cleanup_fs_context_contents() */ @@ -792,6 +791,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, int i, opt; bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); bool skip_parsing = false; + kuid_t uid; + kgid_t gid; cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); @@ -904,18 +905,31 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, } break; case Opt_uid: - ctx->linux_uid.val = result.uint_32; + uid = make_kuid(current_user_ns(), result.uint_32); + if (!uid_valid(uid)) + goto cifs_parse_mount_err; + ctx->linux_uid = uid; ctx->uid_specified = true; break; case Opt_cruid: - ctx->cred_uid.val = result.uint_32; + uid = make_kuid(current_user_ns(), result.uint_32); + if (!uid_valid(uid)) + goto cifs_parse_mount_err; + ctx->cred_uid = uid; + ctx->cruid_specified = true; break; case Opt_backupgid: - ctx->backupgid.val = result.uint_32; + gid = make_kgid(current_user_ns(), result.uint_32); + if (!gid_valid(gid)) + goto cifs_parse_mount_err; + ctx->backupgid = gid; ctx->backupgid_specified = true; break; case Opt_gid: - ctx->linux_gid.val = result.uint_32; + gid = make_kgid(current_user_ns(), result.uint_32); + if (!gid_valid(gid)) + goto cifs_parse_mount_err; + ctx->linux_gid = gid; ctx->gid_specified = true; break; case Opt_port: diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h index 2a71c8e411ac..b6243972edf3 100644 --- a/fs/cifs/fs_context.h +++ b/fs/cifs/fs_context.h @@ -155,6 +155,7 @@ enum cifs_param { struct smb3_fs_context { bool uid_specified; + bool cruid_specified; bool gid_specified; bool sloppy; bool got_ip; -- cgit v1.2.3-59-g8ed1b From 53d31a3ffd60176af24f2f77fb3a7e567134eb90 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 5 Jul 2021 15:05:39 -0500 Subject: SMB3.1.1: Add support for negotiating signing algorithm Support for faster packet signing (using GMAC instead of CMAC) can now be negotiated to some newer servers, including Windows. See MS-SMB2 section 2.2.3.17. This patch adds support for sending the new negotiate context with the first of three supported signing algorithms (AES-CMAC) and decoding the response. A followon patch will add support for sending the other two (including AES-GMAC, which is fastest) and changing the signing algorithm used based on what was negotiated. To allow the client to request GMAC signing set module parameter "enable_negotiate_signing" to 1. Reviewed-by: Ronnie Sahlberg Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 4 +++ fs/cifs/cifsglob.h | 3 ++ fs/cifs/smb2pdu.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++------- fs/cifs/smb2pdu.h | 5 +++- 4 files changed, 86 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9fb874dd8d24..64b71c4e2a9d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -65,6 +65,7 @@ bool lookupCacheEnabled = true; bool disable_legacy_dialects; /* false by default */ bool enable_gcm_256 = true; bool require_gcm_256; /* false by default */ +bool enable_negotiate_signing; /* false by default */ unsigned int global_secflags = CIFSSEC_DEF; /* unsigned int ntlmv2_support = 0; */ unsigned int sign_CIFS_PDUs = 1; @@ -104,6 +105,9 @@ MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encr module_param(require_gcm_256, bool, 0644); MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0"); +module_param(enable_negotiate_signing, bool, 0644); +MODULE_PARM_DESC(enable_negotiate_signing, "Enable negotiating packet signing algorithm with server. Default: n/N/0"); + module_param(disable_legacy_dialects, bool, 0644); MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " "helpful to restrict the ability to " diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 921680fb7931..3c2e117bb926 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -667,9 +667,11 @@ struct TCP_Server_Info { unsigned int max_write; unsigned int min_offload; __le16 compress_algorithm; + __u16 signing_algorithm; __le16 cipher_type; /* save initital negprot hash */ __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; + bool signing_negotiated; /* true if valid signing context rcvd from server */ bool posix_ext_supported; struct delayed_work reconnect; /* reconnect workqueue job */ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ @@ -1869,6 +1871,7 @@ extern unsigned int global_secflags; /* if on, session setup sent extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ extern bool enable_gcm_256; /* allow optional negotiate of strongest signing (aes-gcm-256) */ extern bool require_gcm_256; /* require use of strongest signing (aes-gcm-256) */ +extern bool enable_negotiate_signing; /* request use of faster (GMAC) signing if available */ extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ extern unsigned int CIFSMaxBufSize; /* max size not including hdr */ extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 962826dc3316..781d14e5f2af 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -433,6 +433,29 @@ build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt) pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1; } +static unsigned int +build_signing_ctxt(struct smb2_signing_capabilities *pneg_ctxt) +{ + unsigned int ctxt_len = sizeof(struct smb2_signing_capabilities); + unsigned short num_algs = 1; /* number of signing algorithms sent */ + + pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES; + /* + * Context Data length must be rounded to multiple of 8 for some servers + */ + pneg_ctxt->DataLength = cpu_to_le16(DIV_ROUND_UP( + sizeof(struct smb2_signing_capabilities) - + sizeof(struct smb2_neg_context) + + (num_algs * 2 /* sizeof u16 */), 8) * 8); + pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(num_algs); + pneg_ctxt->SigningAlgorithms[0] = cpu_to_le16(SIGNING_ALG_AES_CMAC); + + ctxt_len += 2 /* sizeof le16 */ * num_algs; + ctxt_len = DIV_ROUND_UP(ctxt_len, 8) * 8; + return ctxt_len; + /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ +} + static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) { @@ -498,7 +521,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, struct TCP_Server_Info *server, unsigned int *total_len) { char *pneg_ctxt; - unsigned int ctxt_len; + unsigned int ctxt_len, neg_context_count; if (*total_len > 200) { /* In case length corrupted don't want to overrun smb buffer */ @@ -525,6 +548,17 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, *total_len += ctxt_len; pneg_ctxt += ctxt_len; + ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, + server->hostname); + *total_len += ctxt_len; + pneg_ctxt += ctxt_len; + + build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); + *total_len += sizeof(struct smb2_posix_neg_context); + pneg_ctxt += sizeof(struct smb2_posix_neg_context); + + neg_context_count = 4; + if (server->compress_algorithm) { build_compression_ctxt((struct smb2_compression_capabilities_context *) pneg_ctxt); @@ -533,17 +567,20 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, 8) * 8; *total_len += ctxt_len; pneg_ctxt += ctxt_len; - req->NegotiateContextCount = cpu_to_le16(5); - } else - req->NegotiateContextCount = cpu_to_le16(4); + neg_context_count++; + } - ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, - server->hostname); - *total_len += ctxt_len; - pneg_ctxt += ctxt_len; + if (enable_negotiate_signing) { + ctxt_len = build_signing_ctxt((struct smb2_signing_capabilities *) + pneg_ctxt); + *total_len += ctxt_len; + pneg_ctxt += ctxt_len; + neg_context_count++; + } + + /* check for and add transport_capabilities and signing capabilities */ + req->NegotiateContextCount = cpu_to_le16(neg_context_count); - build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); - *total_len += sizeof(struct smb2_posix_neg_context); } static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) @@ -632,6 +669,31 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server, return 0; } +static void decode_signing_ctx(struct TCP_Server_Info *server, + struct smb2_signing_capabilities *pctxt) +{ + unsigned int len = le16_to_cpu(pctxt->DataLength); + + if ((len < 4) || (len > 16)) { + pr_warn_once("server sent bad signing negcontext\n"); + return; + } + if (le16_to_cpu(pctxt->SigningAlgorithmCount) != 1) { + pr_warn_once("Invalid signing algorithm count\n"); + return; + } + if (le16_to_cpu(pctxt->SigningAlgorithms[0]) > 2) { + pr_warn_once("unknown signing algorithm\n"); + return; + } + + server->signing_negotiated = true; + server->signing_algorithm = le16_to_cpu(pctxt->SigningAlgorithms[0]); + cifs_dbg(FYI, "signing algorithm %d chosen\n", + server->signing_algorithm); +} + + static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, struct TCP_Server_Info *server, unsigned int len_of_smb) @@ -675,6 +737,9 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, (struct smb2_compression_capabilities_context *)pctx); else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) server->posix_ext_supported = true; + else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) + decode_signing_ctx(server, + (struct smb2_signing_capabilities *)pctx); else cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", le16_to_cpu(pctx->ContextType)); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index ba75e65924ac..4b27cb9105fd 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -329,7 +329,7 @@ struct smb2_neg_context { __le16 ContextType; __le16 DataLength; __le32 Reserved; - /* Followed by array of data */ + /* Followed by array of data. NOTE: some servers require padding to 8 byte boundary */ } __packed; #define SMB311_LINUX_CLIENT_SALT_SIZE 32 @@ -394,6 +394,7 @@ struct smb2_compression_capabilities_context { __u16 Padding; __u32 Flags; __le16 CompressionAlgorithms[3]; + /* Check if pad needed */ } __packed; /* @@ -420,6 +421,7 @@ struct smb2_transport_capabilities_context { __le16 DataLength; __u32 Reserved; __le32 Flags; + __u32 Pad; } __packed; /* @@ -458,6 +460,7 @@ struct smb2_signing_capabilities { __u32 Reserved; __le16 SigningAlgorithmCount; __le16 SigningAlgorithms[]; + /* Followed by padding to 8 byte boundary (required by some servers) */ } __packed; #define POSIX_CTXT_DATA_LEN 16 -- cgit v1.2.3-59-g8ed1b From 03313d1c3a2f086bb60920607ab79ac8f8578306 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Fri, 2 Jul 2021 11:50:54 -0300 Subject: cifs: prevent NULL deref in cifs_compose_mount_options() The optional @ref parameter might contain an NULL node_name, so prevent dereferencing it in cifs_compose_mount_options(). Addresses-Coverity: 1476408 ("Explicit null dereferenced") Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index ec57cdb1590f..57f91311fdaa 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -151,6 +151,9 @@ char *cifs_compose_mount_options(const char *sb_mountdata, return ERR_PTR(-EINVAL); if (ref) { + if (WARN_ON_ONCE(!ref->node_name || ref->path_consumed < 0)) + return ERR_PTR(-EINVAL); + if (strlen(fullpath) - ref->path_consumed) { prepath = fullpath + ref->path_consumed; /* skip initial delimiter */ -- cgit v1.2.3-59-g8ed1b From 4d069f6022e938bc51667da637f2483a37a77e19 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 9 Jul 2021 13:02:26 -0500 Subject: cifs: update internal version number To 2.33 Signed-off-by: Steve French --- fs/cifs/cifsfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 177f3e7ab86d..d25a4099b32e 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -153,5 +153,5 @@ extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, extern const struct export_operations cifs_export_ops; #endif /* CONFIG_CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "2.32" +#define CIFS_VERSION "2.33" #endif /* _CIFSFS_H */ -- cgit v1.2.3-59-g8ed1b