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 '5.14-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"13 cifs/smb3 fixes. Most are to address minor issues pointed out by
Coverity.

Also includes a packet signing enhancement and mount improvement"

* tag '5.14-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
cifs: update internal version number
cifs: prevent NULL deref in cifs_compose_mount_options()
SMB3.1.1: Add support for negotiating signing algorithm
cifs: use helpers when parsing uid/gid mount options and validate them
CIFS: Clarify SMB1 code for POSIX Lock
CIFS: Clarify SMB1 code for rename open file
CIFS: Clarify SMB1 code for delete
CIFS: Clarify SMB1 code for SetFileSize
smb3: fix typo in header file
CIFS: Clarify SMB1 code for UnixSetPathInfo
CIFS: Clarify SMB1 code for UnixCreateSymLink
cifs: clarify SMB1 code for UnixCreateHardLink
cifs: make locking consistent around the server session status

+135 -29
+3
fs/cifs/cifs_dfs_ref.c
··· 151 151 return ERR_PTR(-EINVAL); 152 152 153 153 if (ref) { 154 + if (WARN_ON_ONCE(!ref->node_name || ref->path_consumed < 0)) 155 + return ERR_PTR(-EINVAL); 156 + 154 157 if (strlen(fullpath) - ref->path_consumed) { 155 158 prepath = fullpath + ref->path_consumed; 156 159 /* skip initial delimiter */
+4
fs/cifs/cifsfs.c
··· 65 65 bool disable_legacy_dialects; /* false by default */ 66 66 bool enable_gcm_256 = true; 67 67 bool require_gcm_256; /* false by default */ 68 + bool enable_negotiate_signing; /* false by default */ 68 69 unsigned int global_secflags = CIFSSEC_DEF; 69 70 /* unsigned int ntlmv2_support = 0; */ 70 71 unsigned int sign_CIFS_PDUs = 1; ··· 104 103 105 104 module_param(require_gcm_256, bool, 0644); 106 105 MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0"); 106 + 107 + module_param(enable_negotiate_signing, bool, 0644); 108 + MODULE_PARM_DESC(enable_negotiate_signing, "Enable negotiating packet signing algorithm with server. Default: n/N/0"); 107 109 108 110 module_param(disable_legacy_dialects, bool, 0644); 109 111 MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
+1 -1
fs/cifs/cifsfs.h
··· 153 153 extern const struct export_operations cifs_export_ops; 154 154 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 155 155 156 - #define CIFS_VERSION "2.32" 156 + #define CIFS_VERSION "2.33" 157 157 #endif /* _CIFSFS_H */
+5 -1
fs/cifs/cifsglob.h
··· 577 577 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 578 578 struct smb_version_operations *ops; 579 579 struct smb_version_values *vals; 580 + /* updates to tcpStatus protected by GlobalMid_Lock */ 580 581 enum statusEnum tcpStatus; /* what we think the status is */ 581 582 char *hostname; /* hostname portion of UNC string */ 582 583 struct socket *ssocket; ··· 667 666 unsigned int max_write; 668 667 unsigned int min_offload; 669 668 __le16 compress_algorithm; 669 + __u16 signing_algorithm; 670 670 __le16 cipher_type; 671 671 /* save initital negprot hash */ 672 672 __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; 673 + bool signing_negotiated; /* true if valid signing context rcvd from server */ 673 674 bool posix_ext_supported; 674 675 struct delayed_work reconnect; /* reconnect workqueue job */ 675 676 struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ ··· 1788 1785 * list operations on pending_mid_q and oplockQ 1789 1786 * updates to XID counters, multiplex id and SMB sequence numbers 1790 1787 * list operations on global DnotifyReqList 1791 - * updates to ses->status 1788 + * updates to ses->status and TCP_Server_Info->tcpStatus 1792 1789 * updates to server->CurrentMid 1793 1790 * tcp_ses_lock protects: 1794 1791 * list operations on tcp and SMB session lists ··· 1871 1868 extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ 1872 1869 extern bool enable_gcm_256; /* allow optional negotiate of strongest signing (aes-gcm-256) */ 1873 1870 extern bool require_gcm_256; /* require use of strongest signing (aes-gcm-256) */ 1871 + extern bool enable_negotiate_signing; /* request use of faster (GMAC) signing if available */ 1874 1872 extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ 1875 1873 extern unsigned int CIFSMaxBufSize; /* max size not including hdr */ 1876 1874 extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
+1
fs/cifs/cifspdu.h
··· 1785 1785 __u16 Fid; 1786 1786 __le16 InformationLevel; 1787 1787 __u16 Reserved4; 1788 + __u8 payload[]; 1788 1789 } __attribute__((packed)); 1789 1790 1790 1791 struct smb_com_transaction2_sfi_rsp {
+14 -10
fs/cifs/cifssmb.c
··· 2537 2537 pSMB->TotalDataCount = pSMB->DataCount; 2538 2538 pSMB->TotalParameterCount = pSMB->ParameterCount; 2539 2539 pSMB->ParameterOffset = cpu_to_le16(param_offset); 2540 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 2540 2541 parm_data = (struct cifs_posix_lock *) 2541 - (((char *) &pSMB->hdr.Protocol) + offset); 2542 + (((char *)pSMB) + offset + 4); 2542 2543 2543 2544 parm_data->lock_type = cpu_to_le16(lock_type); 2544 2545 if (waitFlag) { ··· 2768 2767 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 2769 2768 offset = param_offset + params; 2770 2769 2771 - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 2770 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 2771 + data_offset = (char *)(pSMB) + offset + 4; 2772 2772 rename_info = (struct set_file_rename *) data_offset; 2773 2773 pSMB->MaxParameterCount = cpu_to_le16(2); 2774 2774 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */ ··· 2927 2925 InformationLevel) - 4; 2928 2926 offset = param_offset + params; 2929 2927 2930 - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 2928 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 2929 + data_offset = (char *)pSMB + offset + 4; 2931 2930 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2932 2931 name_len_target = 2933 2932 cifsConvertToUTF16((__le16 *) data_offset, toName, ··· 3012 3009 InformationLevel) - 4; 3013 3010 offset = param_offset + params; 3014 3011 3015 - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 3012 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 3013 + data_offset = (char *)pSMB + offset + 4; 3016 3014 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3017 3015 name_len_target = 3018 3016 cifsConvertToUTF16((__le16 *) data_offset, fromName, ··· 5630 5626 pSMB->TotalDataCount = pSMB->DataCount; 5631 5627 pSMB->TotalParameterCount = pSMB->ParameterCount; 5632 5628 pSMB->ParameterOffset = cpu_to_le16(param_offset); 5629 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 5633 5630 parm_data = 5634 - (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) 5635 - + offset); 5631 + (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4); 5636 5632 pSMB->DataOffset = cpu_to_le16(offset); 5637 5633 parm_data->FileSize = cpu_to_le64(size); 5638 5634 pSMB->Fid = cfile->fid.netfid; ··· 5765 5761 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 5766 5762 offset = param_offset + params; 5767 5763 5768 - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 5764 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 5765 + data_offset = (char *)(pSMB) + offset + 4; 5769 5766 5770 5767 count = 1; 5771 5768 pSMB->MaxParameterCount = cpu_to_le16(2); ··· 6067 6062 param_offset = offsetof(struct smb_com_transaction2_spi_req, 6068 6063 InformationLevel) - 4; 6069 6064 offset = param_offset + params; 6070 - data_offset = 6071 - (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol + 6072 - offset); 6065 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 6066 + data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4); 6073 6067 memset(data_offset, 0, count); 6074 6068 pSMB->DataOffset = cpu_to_le16(offset); 6075 6069 pSMB->ParameterOffset = cpu_to_le16(param_offset);
+5
fs/cifs/connect.c
··· 1403 1403 goto out_err_crypto_release; 1404 1404 } 1405 1405 tcp_ses->min_offload = ctx->min_offload; 1406 + /* 1407 + * at this point we are the only ones with the pointer 1408 + * to the struct since the kernel thread not created yet 1409 + * no need to spinlock this update of tcpStatus 1410 + */ 1406 1411 tcp_ses->tcpStatus = CifsNeedNegotiate; 1407 1412 1408 1413 if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
+19 -5
fs/cifs/fs_context.c
··· 322 322 new_ctx->UNC = NULL; 323 323 new_ctx->source = NULL; 324 324 new_ctx->iocharset = NULL; 325 - 326 325 /* 327 326 * Make sure to stay in sync with smb3_cleanup_fs_context_contents() 328 327 */ ··· 791 792 int i, opt; 792 793 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); 793 794 bool skip_parsing = false; 795 + kuid_t uid; 796 + kgid_t gid; 794 797 795 798 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); 796 799 ··· 905 904 } 906 905 break; 907 906 case Opt_uid: 908 - ctx->linux_uid.val = result.uint_32; 907 + uid = make_kuid(current_user_ns(), result.uint_32); 908 + if (!uid_valid(uid)) 909 + goto cifs_parse_mount_err; 910 + ctx->linux_uid = uid; 909 911 ctx->uid_specified = true; 910 912 break; 911 913 case Opt_cruid: 912 - ctx->cred_uid.val = result.uint_32; 914 + uid = make_kuid(current_user_ns(), result.uint_32); 915 + if (!uid_valid(uid)) 916 + goto cifs_parse_mount_err; 917 + ctx->cred_uid = uid; 918 + ctx->cruid_specified = true; 913 919 break; 914 920 case Opt_backupgid: 915 - ctx->backupgid.val = result.uint_32; 921 + gid = make_kgid(current_user_ns(), result.uint_32); 922 + if (!gid_valid(gid)) 923 + goto cifs_parse_mount_err; 924 + ctx->backupgid = gid; 916 925 ctx->backupgid_specified = true; 917 926 break; 918 927 case Opt_gid: 919 - ctx->linux_gid.val = result.uint_32; 928 + gid = make_kgid(current_user_ns(), result.uint_32); 929 + if (!gid_valid(gid)) 930 + goto cifs_parse_mount_err; 931 + ctx->linux_gid = gid; 920 932 ctx->gid_specified = true; 921 933 break; 922 934 case Opt_port:
+1
fs/cifs/fs_context.h
··· 155 155 156 156 struct smb3_fs_context { 157 157 bool uid_specified; 158 + bool cruid_specified; 158 159 bool gid_specified; 159 160 bool sloppy; 160 161 bool got_ip;
+75 -10
fs/cifs/smb2pdu.c
··· 433 433 pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1; 434 434 } 435 435 436 + static unsigned int 437 + build_signing_ctxt(struct smb2_signing_capabilities *pneg_ctxt) 438 + { 439 + unsigned int ctxt_len = sizeof(struct smb2_signing_capabilities); 440 + unsigned short num_algs = 1; /* number of signing algorithms sent */ 441 + 442 + pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES; 443 + /* 444 + * Context Data length must be rounded to multiple of 8 for some servers 445 + */ 446 + pneg_ctxt->DataLength = cpu_to_le16(DIV_ROUND_UP( 447 + sizeof(struct smb2_signing_capabilities) - 448 + sizeof(struct smb2_neg_context) + 449 + (num_algs * 2 /* sizeof u16 */), 8) * 8); 450 + pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(num_algs); 451 + pneg_ctxt->SigningAlgorithms[0] = cpu_to_le16(SIGNING_ALG_AES_CMAC); 452 + 453 + ctxt_len += 2 /* sizeof le16 */ * num_algs; 454 + ctxt_len = DIV_ROUND_UP(ctxt_len, 8) * 8; 455 + return ctxt_len; 456 + /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ 457 + } 458 + 436 459 static void 437 460 build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) 438 461 { ··· 521 498 struct TCP_Server_Info *server, unsigned int *total_len) 522 499 { 523 500 char *pneg_ctxt; 524 - unsigned int ctxt_len; 501 + unsigned int ctxt_len, neg_context_count; 525 502 526 503 if (*total_len > 200) { 527 504 /* In case length corrupted don't want to overrun smb buffer */ ··· 548 525 *total_len += ctxt_len; 549 526 pneg_ctxt += ctxt_len; 550 527 528 + ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, 529 + server->hostname); 530 + *total_len += ctxt_len; 531 + pneg_ctxt += ctxt_len; 532 + 533 + build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); 534 + *total_len += sizeof(struct smb2_posix_neg_context); 535 + pneg_ctxt += sizeof(struct smb2_posix_neg_context); 536 + 537 + neg_context_count = 4; 538 + 551 539 if (server->compress_algorithm) { 552 540 build_compression_ctxt((struct smb2_compression_capabilities_context *) 553 541 pneg_ctxt); ··· 567 533 8) * 8; 568 534 *total_len += ctxt_len; 569 535 pneg_ctxt += ctxt_len; 570 - req->NegotiateContextCount = cpu_to_le16(5); 571 - } else 572 - req->NegotiateContextCount = cpu_to_le16(4); 536 + neg_context_count++; 537 + } 573 538 574 - ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, 575 - server->hostname); 576 - *total_len += ctxt_len; 577 - pneg_ctxt += ctxt_len; 539 + if (enable_negotiate_signing) { 540 + ctxt_len = build_signing_ctxt((struct smb2_signing_capabilities *) 541 + pneg_ctxt); 542 + *total_len += ctxt_len; 543 + pneg_ctxt += ctxt_len; 544 + neg_context_count++; 545 + } 578 546 579 - build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); 580 - *total_len += sizeof(struct smb2_posix_neg_context); 547 + /* check for and add transport_capabilities and signing capabilities */ 548 + req->NegotiateContextCount = cpu_to_le16(neg_context_count); 549 + 581 550 } 582 551 583 552 static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) ··· 669 632 return 0; 670 633 } 671 634 635 + static void decode_signing_ctx(struct TCP_Server_Info *server, 636 + struct smb2_signing_capabilities *pctxt) 637 + { 638 + unsigned int len = le16_to_cpu(pctxt->DataLength); 639 + 640 + if ((len < 4) || (len > 16)) { 641 + pr_warn_once("server sent bad signing negcontext\n"); 642 + return; 643 + } 644 + if (le16_to_cpu(pctxt->SigningAlgorithmCount) != 1) { 645 + pr_warn_once("Invalid signing algorithm count\n"); 646 + return; 647 + } 648 + if (le16_to_cpu(pctxt->SigningAlgorithms[0]) > 2) { 649 + pr_warn_once("unknown signing algorithm\n"); 650 + return; 651 + } 652 + 653 + server->signing_negotiated = true; 654 + server->signing_algorithm = le16_to_cpu(pctxt->SigningAlgorithms[0]); 655 + cifs_dbg(FYI, "signing algorithm %d chosen\n", 656 + server->signing_algorithm); 657 + } 658 + 659 + 672 660 static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, 673 661 struct TCP_Server_Info *server, 674 662 unsigned int len_of_smb) ··· 737 675 (struct smb2_compression_capabilities_context *)pctx); 738 676 else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) 739 677 server->posix_ext_supported = true; 678 + else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) 679 + decode_signing_ctx(server, 680 + (struct smb2_signing_capabilities *)pctx); 740 681 else 741 682 cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", 742 683 le16_to_cpu(pctx->ContextType));
+5 -2
fs/cifs/smb2pdu.h
··· 13 13 #define _SMB2PDU_H 14 14 15 15 #include <net/sock.h> 16 - #include <cifsacl.h> 16 + #include "cifsacl.h" 17 17 18 18 /* 19 19 * Note that, due to trying to use names similar to the protocol specifications, ··· 329 329 __le16 ContextType; 330 330 __le16 DataLength; 331 331 __le32 Reserved; 332 - /* Followed by array of data */ 332 + /* Followed by array of data. NOTE: some servers require padding to 8 byte boundary */ 333 333 } __packed; 334 334 335 335 #define SMB311_LINUX_CLIENT_SALT_SIZE 32 ··· 394 394 __u16 Padding; 395 395 __u32 Flags; 396 396 __le16 CompressionAlgorithms[3]; 397 + /* Check if pad needed */ 397 398 } __packed; 398 399 399 400 /* ··· 421 420 __le16 DataLength; 422 421 __u32 Reserved; 423 422 __le32 Flags; 423 + __u32 Pad; 424 424 } __packed; 425 425 426 426 /* ··· 460 458 __u32 Reserved; 461 459 __le16 SigningAlgorithmCount; 462 460 __le16 SigningAlgorithms[]; 461 + /* Followed by padding to 8 byte boundary (required by some servers) */ 463 462 } __packed; 464 463 465 464 #define POSIX_CTXT_DATA_LEN 16
+2
fs/cifs/transport.c
··· 431 431 * be taken as the remainder of this one. We need to kill the 432 432 * socket so the server throws away the partial SMB 433 433 */ 434 + spin_lock(&GlobalMid_Lock); 434 435 server->tcpStatus = CifsNeedReconnect; 436 + spin_unlock(&GlobalMid_Lock); 435 437 trace_smb3_partial_send_reconnect(server->CurrentMid, 436 438 server->conn_id, server->hostname); 437 439 }