diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-12 21:49:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-12 21:49:53 -0400 |
commit | ccda3c4b77777f66aeb3c531352bb40d59501c59 (patch) | |
tree | 1f06e12e644bd24d35df6924b85cfceed3947bfb | |
parent | 427fbe89261d8f11cd20b5a4ba94e977061f69d6 (diff) | |
parent | 6e70c267e68d77679534dcf4aaf84e66f2cf1425 (diff) |
Merge tag '4.17-rc4-SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French:
"Some small SMB3 fixes for 4.17-rc5, some for stable"
* tag '4.17-rc4-SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb3: directory sync should not return an error
cifs: smb2ops: Fix listxattr() when there are no EAs
cifs: smbd: Enable signing with smbdirect
cifs: Allocate validate negotiation request through kmalloc
-rw-r--r-- | fs/cifs/cifsfs.c | 13 | ||||
-rw-r--r-- | fs/cifs/connect.c | 8 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 6 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 73 |
4 files changed, 57 insertions, 43 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f715609b13f3..5a5a0158cc8f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -1047,6 +1047,18 @@ out: | |||
1047 | return rc; | 1047 | return rc; |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | /* | ||
1051 | * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync() | ||
1052 | * is a dummy operation. | ||
1053 | */ | ||
1054 | static int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
1055 | { | ||
1056 | cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n", | ||
1057 | file, datasync); | ||
1058 | |||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1050 | static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, | 1062 | static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, |
1051 | struct file *dst_file, loff_t destoff, | 1063 | struct file *dst_file, loff_t destoff, |
1052 | size_t len, unsigned int flags) | 1064 | size_t len, unsigned int flags) |
@@ -1181,6 +1193,7 @@ const struct file_operations cifs_dir_ops = { | |||
1181 | .copy_file_range = cifs_copy_file_range, | 1193 | .copy_file_range = cifs_copy_file_range, |
1182 | .clone_file_range = cifs_clone_file_range, | 1194 | .clone_file_range = cifs_clone_file_range, |
1183 | .llseek = generic_file_llseek, | 1195 | .llseek = generic_file_llseek, |
1196 | .fsync = cifs_dir_fsync, | ||
1184 | }; | 1197 | }; |
1185 | 1198 | ||
1186 | static void | 1199 | static void |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a5aa158d535a..7a10a5d0731f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1977,14 +1977,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1977 | goto cifs_parse_mount_err; | 1977 | goto cifs_parse_mount_err; |
1978 | } | 1978 | } |
1979 | 1979 | ||
1980 | #ifdef CONFIG_CIFS_SMB_DIRECT | ||
1981 | if (vol->rdma && vol->sign) { | ||
1982 | cifs_dbg(VFS, "Currently SMB direct doesn't support signing." | ||
1983 | " This is being fixed\n"); | ||
1984 | goto cifs_parse_mount_err; | ||
1985 | } | ||
1986 | #endif | ||
1987 | |||
1988 | #ifndef CONFIG_KEYS | 1980 | #ifndef CONFIG_KEYS |
1989 | /* Muliuser mounts require CONFIG_KEYS support */ | 1981 | /* Muliuser mounts require CONFIG_KEYS support */ |
1990 | if (vol->multiuser) { | 1982 | if (vol->multiuser) { |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index b76b85881dcc..9c6d95ffca97 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -589,9 +589,15 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | |||
589 | 589 | ||
590 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 590 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
591 | 591 | ||
592 | /* | ||
593 | * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's | ||
594 | * not an error. Otherwise, the specified ea_name was not found. | ||
595 | */ | ||
592 | if (!rc) | 596 | if (!rc) |
593 | rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data, | 597 | rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data, |
594 | SMB2_MAX_EA_BUF, ea_name); | 598 | SMB2_MAX_EA_BUF, ea_name); |
599 | else if (!ea_name && rc == -ENODATA) | ||
600 | rc = 0; | ||
595 | 601 | ||
596 | kfree(smb2_data); | 602 | kfree(smb2_data); |
597 | return rc; | 603 | return rc; |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 60db51bae0e3..0f48741a0130 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -730,19 +730,14 @@ neg_exit: | |||
730 | 730 | ||
731 | int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | 731 | int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) |
732 | { | 732 | { |
733 | int rc = 0; | 733 | int rc; |
734 | struct validate_negotiate_info_req vneg_inbuf; | 734 | struct validate_negotiate_info_req *pneg_inbuf; |
735 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; | 735 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; |
736 | u32 rsplen; | 736 | u32 rsplen; |
737 | u32 inbuflen; /* max of 4 dialects */ | 737 | u32 inbuflen; /* max of 4 dialects */ |
738 | 738 | ||
739 | cifs_dbg(FYI, "validate negotiate\n"); | 739 | cifs_dbg(FYI, "validate negotiate\n"); |
740 | 740 | ||
741 | #ifdef CONFIG_CIFS_SMB_DIRECT | ||
742 | if (tcon->ses->server->rdma) | ||
743 | return 0; | ||
744 | #endif | ||
745 | |||
746 | /* In SMB3.11 preauth integrity supersedes validate negotiate */ | 741 | /* In SMB3.11 preauth integrity supersedes validate negotiate */ |
747 | if (tcon->ses->server->dialect == SMB311_PROT_ID) | 742 | if (tcon->ses->server->dialect == SMB311_PROT_ID) |
748 | return 0; | 743 | return 0; |
@@ -765,63 +760,69 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
765 | if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) | 760 | if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) |
766 | cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); | 761 | cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); |
767 | 762 | ||
768 | vneg_inbuf.Capabilities = | 763 | pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); |
764 | if (!pneg_inbuf) | ||
765 | return -ENOMEM; | ||
766 | |||
767 | pneg_inbuf->Capabilities = | ||
769 | cpu_to_le32(tcon->ses->server->vals->req_capabilities); | 768 | cpu_to_le32(tcon->ses->server->vals->req_capabilities); |
770 | memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid, | 769 | memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, |
771 | SMB2_CLIENT_GUID_SIZE); | 770 | SMB2_CLIENT_GUID_SIZE); |
772 | 771 | ||
773 | if (tcon->ses->sign) | 772 | if (tcon->ses->sign) |
774 | vneg_inbuf.SecurityMode = | 773 | pneg_inbuf->SecurityMode = |
775 | cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); | 774 | cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); |
776 | else if (global_secflags & CIFSSEC_MAY_SIGN) | 775 | else if (global_secflags & CIFSSEC_MAY_SIGN) |
777 | vneg_inbuf.SecurityMode = | 776 | pneg_inbuf->SecurityMode = |
778 | cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); | 777 | cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); |
779 | else | 778 | else |
780 | vneg_inbuf.SecurityMode = 0; | 779 | pneg_inbuf->SecurityMode = 0; |
781 | 780 | ||
782 | 781 | ||
783 | if (strcmp(tcon->ses->server->vals->version_string, | 782 | if (strcmp(tcon->ses->server->vals->version_string, |
784 | SMB3ANY_VERSION_STRING) == 0) { | 783 | SMB3ANY_VERSION_STRING) == 0) { |
785 | vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID); | 784 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); |
786 | vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID); | 785 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); |
787 | vneg_inbuf.DialectCount = cpu_to_le16(2); | 786 | pneg_inbuf->DialectCount = cpu_to_le16(2); |
788 | /* structure is big enough for 3 dialects, sending only 2 */ | 787 | /* structure is big enough for 3 dialects, sending only 2 */ |
789 | inbuflen = sizeof(struct validate_negotiate_info_req) - 2; | 788 | inbuflen = sizeof(*pneg_inbuf) - |
789 | sizeof(pneg_inbuf->Dialects[0]); | ||
790 | } else if (strcmp(tcon->ses->server->vals->version_string, | 790 | } else if (strcmp(tcon->ses->server->vals->version_string, |
791 | SMBDEFAULT_VERSION_STRING) == 0) { | 791 | SMBDEFAULT_VERSION_STRING) == 0) { |
792 | vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID); | 792 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
793 | vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID); | 793 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
794 | vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID); | 794 | pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); |
795 | vneg_inbuf.DialectCount = cpu_to_le16(3); | 795 | pneg_inbuf->DialectCount = cpu_to_le16(3); |
796 | /* structure is big enough for 3 dialects */ | 796 | /* structure is big enough for 3 dialects */ |
797 | inbuflen = sizeof(struct validate_negotiate_info_req); | 797 | inbuflen = sizeof(*pneg_inbuf); |
798 | } else { | 798 | } else { |
799 | /* otherwise specific dialect was requested */ | 799 | /* otherwise specific dialect was requested */ |
800 | vneg_inbuf.Dialects[0] = | 800 | pneg_inbuf->Dialects[0] = |
801 | cpu_to_le16(tcon->ses->server->vals->protocol_id); | 801 | cpu_to_le16(tcon->ses->server->vals->protocol_id); |
802 | vneg_inbuf.DialectCount = cpu_to_le16(1); | 802 | pneg_inbuf->DialectCount = cpu_to_le16(1); |
803 | /* structure is big enough for 3 dialects, sending only 1 */ | 803 | /* structure is big enough for 3 dialects, sending only 1 */ |
804 | inbuflen = sizeof(struct validate_negotiate_info_req) - 4; | 804 | inbuflen = sizeof(*pneg_inbuf) - |
805 | sizeof(pneg_inbuf->Dialects[0]) * 2; | ||
805 | } | 806 | } |
806 | 807 | ||
807 | rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, | 808 | rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, |
808 | FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, | 809 | FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, |
809 | (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req), | 810 | (char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen); |
810 | (char **)&pneg_rsp, &rsplen); | ||
811 | 811 | ||
812 | if (rc != 0) { | 812 | if (rc != 0) { |
813 | cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); | 813 | cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); |
814 | return -EIO; | 814 | rc = -EIO; |
815 | goto out_free_inbuf; | ||
815 | } | 816 | } |
816 | 817 | ||
817 | if (rsplen != sizeof(struct validate_negotiate_info_rsp)) { | 818 | rc = -EIO; |
819 | if (rsplen != sizeof(*pneg_rsp)) { | ||
818 | cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", | 820 | cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", |
819 | rsplen); | 821 | rsplen); |
820 | 822 | ||
821 | /* relax check since Mac returns max bufsize allowed on ioctl */ | 823 | /* relax check since Mac returns max bufsize allowed on ioctl */ |
822 | if ((rsplen > CIFSMaxBufSize) | 824 | if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp)) |
823 | || (rsplen < sizeof(struct validate_negotiate_info_rsp))) | 825 | goto out_free_rsp; |
824 | goto err_rsp_free; | ||
825 | } | 826 | } |
826 | 827 | ||
827 | /* check validate negotiate info response matches what we got earlier */ | 828 | /* check validate negotiate info response matches what we got earlier */ |
@@ -838,15 +839,17 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
838 | goto vneg_out; | 839 | goto vneg_out; |
839 | 840 | ||
840 | /* validate negotiate successful */ | 841 | /* validate negotiate successful */ |
842 | rc = 0; | ||
841 | cifs_dbg(FYI, "validate negotiate info successful\n"); | 843 | cifs_dbg(FYI, "validate negotiate info successful\n"); |
842 | kfree(pneg_rsp); | 844 | goto out_free_rsp; |
843 | return 0; | ||
844 | 845 | ||
845 | vneg_out: | 846 | vneg_out: |
846 | cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); | 847 | cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); |
847 | err_rsp_free: | 848 | out_free_rsp: |
848 | kfree(pneg_rsp); | 849 | kfree(pneg_rsp); |
849 | return -EIO; | 850 | out_free_inbuf: |
851 | kfree(pneg_inbuf); | ||
852 | return rc; | ||
850 | } | 853 | } |
851 | 854 | ||
852 | enum securityEnum | 855 | enum securityEnum |