diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-04 17:42:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-04 17:42:46 -0400 |
| commit | 325520142b47690018d09060a874327d5e7f0709 (patch) | |
| tree | c4fc16898e0ac00f4c1d761df6fd61ab8f6f7d21 | |
| parent | 1e43938bfbad4fd51bea4c092c1ded06790bf79c (diff) | |
| parent | 8e7360f67e75e06f3ea144354243728fb8f54c57 (diff) | |
Merge tag '4.18-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French:
- smb3 fixes for stable
- addition of ftrace hooks for cifs.ko
- improvements in compounding and smbdirect (rdma)
* tag '4.18-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (38 commits)
CIFS: Add support for direct pages in wdata
CIFS: Use offset when reading pages
CIFS: Add support for direct pages in rdata
cifs: update multiplex loop to handle compounded responses
cifs: remove header_preamble_size where it is always 0
cifs: remove struct smb2_hdr
CIFS: 511c54a2f69195b28afb9dd119f03787b1625bb4 adds a check for session expiry, status STATUS_NETWORK_SESSION_EXPIRED, however the server can also respond with STATUS_USER_SESSION_DELETED in cases where the session has been idle for some time and the server reaps the session to recover resources.
cifs: change smb2_get_data_area_len to take a smb2_sync_hdr as argument
cifs: update smb2_calc_size to use smb2_sync_hdr instead of smb2_hdr
cifs: remove struct smb2_oplock_break_rsp
cifs: remove rfc1002 header from all SMB2 response structures
smb3: on reconnect set PreviousSessionId field
smb3: Add posix create context for smb3.11 posix mounts
smb3: add tracepoints for smb2/smb3 open
cifs: add debug output to show nocase mount option
smb3: add define for id for posix create context and corresponding struct
cifs: update smb2_check_message to handle PDUs without a 4 byte length header
smb3: allow "posix" mount option to enable new SMB311 protocol extensions
smb3: add support for posix negotiate context
cifs: allow disabling less secure legacy dialects
...
| -rw-r--r-- | fs/cifs/Makefile | 7 | ||||
| -rw-r--r-- | fs/cifs/cifs_debug.c | 43 | ||||
| -rw-r--r-- | fs/cifs/cifs_debug.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 48 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 47 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 16 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 23 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 93 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 2 | ||||
| -rw-r--r-- | fs/cifs/file.c | 75 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 13 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 7 | ||||
| -rw-r--r-- | fs/cifs/netmisc.c | 2 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 6 | ||||
| -rw-r--r-- | fs/cifs/smb2glob.h | 5 | ||||
| -rw-r--r-- | fs/cifs/smb2inode.c | 43 | ||||
| -rw-r--r-- | fs/cifs/smb2maperror.c | 11 | ||||
| -rw-r--r-- | fs/cifs/smb2misc.c | 126 | ||||
| -rw-r--r-- | fs/cifs/smb2ops.c | 314 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 340 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.h | 84 | ||||
| -rw-r--r-- | fs/cifs/smb2proto.h | 9 | ||||
| -rw-r--r-- | fs/cifs/smb2transport.c | 10 | ||||
| -rw-r--r-- | fs/cifs/trace.c | 18 | ||||
| -rw-r--r-- | fs/cifs/trace.h | 429 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 4 |
28 files changed, 1346 insertions, 434 deletions
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 7e4a1e2f0696..85817991ee68 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | # | 2 | # |
| 3 | # Makefile for Linux CIFS VFS client | 3 | # Makefile for Linux CIFS/SMB2/SMB3 VFS client |
| 4 | # | 4 | # |
| 5 | ccflags-y += -I$(src) # needed for trace events | ||
| 5 | obj-$(CONFIG_CIFS) += cifs.o | 6 | obj-$(CONFIG_CIFS) += cifs.o |
| 6 | 7 | ||
| 7 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 8 | cifs-y := trace.o cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o \ |
| 8 | link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ | 9 | inode.o link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ |
| 9 | cifs_unicode.o nterr.o cifsencrypt.o \ | 10 | cifs_unicode.o nterr.o cifsencrypt.o \ |
| 10 | readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o \ | 11 | readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o \ |
| 11 | smb2ops.o smb2maperror.o smb2transport.o \ | 12 | smb2ops.o smb2maperror.o smb2transport.o \ |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 4bc4a7ac61d9..116146022aa1 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -42,7 +42,7 @@ cifs_dump_mem(char *label, void *data, int length) | |||
| 42 | data, length, true); | 42 | data, length, true); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | void cifs_dump_detail(void *buf) | 45 | void cifs_dump_detail(void *buf, struct TCP_Server_Info *server) |
| 46 | { | 46 | { |
| 47 | #ifdef CONFIG_CIFS_DEBUG2 | 47 | #ifdef CONFIG_CIFS_DEBUG2 |
| 48 | struct smb_hdr *smb = (struct smb_hdr *)buf; | 48 | struct smb_hdr *smb = (struct smb_hdr *)buf; |
| @@ -50,7 +50,8 @@ void cifs_dump_detail(void *buf) | |||
| 50 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n", | 50 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n", |
| 51 | smb->Command, smb->Status.CifsError, | 51 | smb->Command, smb->Status.CifsError, |
| 52 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); | 52 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); |
| 53 | cifs_dbg(VFS, "smb buf %p len %u\n", smb, smbCalcSize(smb)); | 53 | cifs_dbg(VFS, "smb buf %p len %u\n", smb, |
| 54 | server->ops->calc_smb_size(smb, server)); | ||
| 54 | #endif /* CONFIG_CIFS_DEBUG2 */ | 55 | #endif /* CONFIG_CIFS_DEBUG2 */ |
| 55 | } | 56 | } |
| 56 | 57 | ||
| @@ -83,7 +84,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
| 83 | cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n", | 84 | cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n", |
| 84 | mid_entry->multiRsp, mid_entry->multiEnd); | 85 | mid_entry->multiRsp, mid_entry->multiEnd); |
| 85 | if (mid_entry->resp_buf) { | 86 | if (mid_entry->resp_buf) { |
| 86 | cifs_dump_detail(mid_entry->resp_buf); | 87 | cifs_dump_detail(mid_entry->resp_buf, server); |
| 87 | cifs_dump_mem("existing buf: ", | 88 | cifs_dump_mem("existing buf: ", |
| 88 | mid_entry->resp_buf, 62); | 89 | mid_entry->resp_buf, 62); |
| 89 | } | 90 | } |
| @@ -113,6 +114,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) | |||
| 113 | seq_printf(m, " type: %d ", dev_type); | 114 | seq_printf(m, " type: %d ", dev_type); |
| 114 | if (tcon->seal) | 115 | if (tcon->seal) |
| 115 | seq_printf(m, " Encrypted"); | 116 | seq_printf(m, " Encrypted"); |
| 117 | if (tcon->nocase) | ||
| 118 | seq_printf(m, " nocase"); | ||
| 116 | if (tcon->unix_ext) | 119 | if (tcon->unix_ext) |
| 117 | seq_printf(m, " POSIX Extensions"); | 120 | seq_printf(m, " POSIX Extensions"); |
| 118 | if (tcon->ses->server->ops->dump_share_caps) | 121 | if (tcon->ses->server->ops->dump_share_caps) |
| @@ -237,6 +240,10 @@ skip_rdma: | |||
| 237 | server->credits, server->dialect); | 240 | server->credits, server->dialect); |
| 238 | if (server->sign) | 241 | if (server->sign) |
| 239 | seq_printf(m, " signed"); | 242 | seq_printf(m, " signed"); |
| 243 | #ifdef CONFIG_CIFS_SMB311 | ||
| 244 | if (server->posix_ext_supported) | ||
| 245 | seq_printf(m, " posix"); | ||
| 246 | #endif /* 3.1.1 */ | ||
| 240 | i++; | 247 | i++; |
| 241 | list_for_each(tmp2, &server->smb_ses_list) { | 248 | list_for_each(tmp2, &server->smb_ses_list) { |
| 242 | ses = list_entry(tmp2, struct cifs_ses, | 249 | ses = list_entry(tmp2, struct cifs_ses, |
| @@ -489,32 +496,32 @@ cifs_proc_init(void) | |||
| 489 | cifs_debug_data_proc_show); | 496 | cifs_debug_data_proc_show); |
| 490 | 497 | ||
| 491 | #ifdef CONFIG_CIFS_STATS | 498 | #ifdef CONFIG_CIFS_STATS |
| 492 | proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops); | 499 | proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops); |
| 493 | #endif /* STATS */ | 500 | #endif /* STATS */ |
| 494 | proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); | 501 | proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops); |
| 495 | proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); | 502 | proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops); |
| 496 | proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, | 503 | proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs, |
| 497 | &cifs_linux_ext_proc_fops); | 504 | &cifs_linux_ext_proc_fops); |
| 498 | proc_create("SecurityFlags", 0, proc_fs_cifs, | 505 | proc_create("SecurityFlags", 0644, proc_fs_cifs, |
| 499 | &cifs_security_flags_proc_fops); | 506 | &cifs_security_flags_proc_fops); |
| 500 | proc_create("LookupCacheEnabled", 0, proc_fs_cifs, | 507 | proc_create("LookupCacheEnabled", 0644, proc_fs_cifs, |
| 501 | &cifs_lookup_cache_proc_fops); | 508 | &cifs_lookup_cache_proc_fops); |
| 502 | #ifdef CONFIG_CIFS_SMB_DIRECT | 509 | #ifdef CONFIG_CIFS_SMB_DIRECT |
| 503 | proc_create("rdma_readwrite_threshold", 0, proc_fs_cifs, | 510 | proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs, |
| 504 | &cifs_rdma_readwrite_threshold_proc_fops); | 511 | &cifs_rdma_readwrite_threshold_proc_fops); |
| 505 | proc_create("smbd_max_frmr_depth", 0, proc_fs_cifs, | 512 | proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs, |
| 506 | &cifs_smbd_max_frmr_depth_proc_fops); | 513 | &cifs_smbd_max_frmr_depth_proc_fops); |
| 507 | proc_create("smbd_keep_alive_interval", 0, proc_fs_cifs, | 514 | proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs, |
| 508 | &cifs_smbd_keep_alive_interval_proc_fops); | 515 | &cifs_smbd_keep_alive_interval_proc_fops); |
| 509 | proc_create("smbd_max_receive_size", 0, proc_fs_cifs, | 516 | proc_create("smbd_max_receive_size", 0644, proc_fs_cifs, |
| 510 | &cifs_smbd_max_receive_size_proc_fops); | 517 | &cifs_smbd_max_receive_size_proc_fops); |
| 511 | proc_create("smbd_max_fragmented_recv_size", 0, proc_fs_cifs, | 518 | proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs, |
| 512 | &cifs_smbd_max_fragmented_recv_size_proc_fops); | 519 | &cifs_smbd_max_fragmented_recv_size_proc_fops); |
| 513 | proc_create("smbd_max_send_size", 0, proc_fs_cifs, | 520 | proc_create("smbd_max_send_size", 0644, proc_fs_cifs, |
| 514 | &cifs_smbd_max_send_size_proc_fops); | 521 | &cifs_smbd_max_send_size_proc_fops); |
| 515 | proc_create("smbd_send_credit_target", 0, proc_fs_cifs, | 522 | proc_create("smbd_send_credit_target", 0644, proc_fs_cifs, |
| 516 | &cifs_smbd_send_credit_target_proc_fops); | 523 | &cifs_smbd_send_credit_target_proc_fops); |
| 517 | proc_create("smbd_receive_credit_max", 0, proc_fs_cifs, | 524 | proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs, |
| 518 | &cifs_smbd_receive_credit_max_proc_fops); | 525 | &cifs_smbd_receive_credit_max_proc_fops); |
| 519 | #endif | 526 | #endif |
| 520 | } | 527 | } |
| @@ -572,6 +579,8 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer, | |||
| 572 | cifsFYI = bv; | 579 | cifsFYI = bv; |
| 573 | else if ((c[0] > '1') && (c[0] <= '9')) | 580 | else if ((c[0] > '1') && (c[0] <= '9')) |
| 574 | cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */ | 581 | cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */ |
| 582 | else | ||
| 583 | return -EINVAL; | ||
| 575 | 584 | ||
| 576 | return count; | 585 | return count; |
| 577 | } | 586 | } |
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 0e74690d11bc..f4f3f0853c6e 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #define _H_CIFS_DEBUG | 23 | #define _H_CIFS_DEBUG |
| 24 | 24 | ||
| 25 | void cifs_dump_mem(char *label, void *data, int length); | 25 | void cifs_dump_mem(char *label, void *data, int length); |
| 26 | void cifs_dump_detail(void *); | 26 | void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info); |
| 27 | void cifs_dump_mids(struct TCP_Server_Info *); | 27 | void cifs_dump_mids(struct TCP_Server_Info *); |
| 28 | extern bool traceSMB; /* flag which enables the function below */ | 28 | extern bool traceSMB; /* flag which enables the function below */ |
| 29 | void dump_smb(void *, int); | 29 | void dump_smb(void *, int); |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 350fa55a1bf7..9731d0d891e7 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | * root mountable | 50 | * root mountable |
| 51 | */ | 51 | */ |
| 52 | #define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */ | 52 | #define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */ |
| 53 | #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */ | ||
| 53 | 54 | ||
| 54 | struct cifs_sb_info { | 55 | struct cifs_sb_info { |
| 55 | struct rb_root tlink_tree; | 56 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5a5a0158cc8f..eb7b6573f322 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -58,13 +58,15 @@ bool traceSMB; | |||
| 58 | bool enable_oplocks = true; | 58 | bool enable_oplocks = true; |
| 59 | bool linuxExtEnabled = true; | 59 | bool linuxExtEnabled = true; |
| 60 | bool lookupCacheEnabled = true; | 60 | bool lookupCacheEnabled = true; |
| 61 | bool disable_legacy_dialects; /* false by default */ | ||
| 61 | unsigned int global_secflags = CIFSSEC_DEF; | 62 | unsigned int global_secflags = CIFSSEC_DEF; |
| 62 | /* unsigned int ntlmv2_support = 0; */ | 63 | /* unsigned int ntlmv2_support = 0; */ |
| 63 | unsigned int sign_CIFS_PDUs = 1; | 64 | unsigned int sign_CIFS_PDUs = 1; |
| 64 | static const struct super_operations cifs_super_ops; | 65 | static const struct super_operations cifs_super_ops; |
| 65 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 66 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
| 66 | module_param(CIFSMaxBufSize, uint, 0444); | 67 | module_param(CIFSMaxBufSize, uint, 0444); |
| 67 | MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). " | 68 | MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header) " |
| 69 | "for CIFS requests. " | ||
| 68 | "Default: 16384 Range: 8192 to 130048"); | 70 | "Default: 16384 Range: 8192 to 130048"); |
| 69 | unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; | 71 | unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; |
| 70 | module_param(cifs_min_rcv, uint, 0444); | 72 | module_param(cifs_min_rcv, uint, 0444); |
| @@ -76,11 +78,21 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " | |||
| 76 | "Range: 2 to 256"); | 78 | "Range: 2 to 256"); |
| 77 | unsigned int cifs_max_pending = CIFS_MAX_REQ; | 79 | unsigned int cifs_max_pending = CIFS_MAX_REQ; |
| 78 | module_param(cifs_max_pending, uint, 0444); | 80 | module_param(cifs_max_pending, uint, 0444); |
| 79 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " | 81 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for " |
| 82 | "CIFS/SMB1 dialect (N/A for SMB3) " | ||
| 80 | "Default: 32767 Range: 2 to 32767."); | 83 | "Default: 32767 Range: 2 to 32767."); |
| 81 | module_param(enable_oplocks, bool, 0644); | 84 | module_param(enable_oplocks, bool, 0644); |
| 82 | MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1"); | 85 | MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1"); |
| 83 | 86 | ||
| 87 | module_param(disable_legacy_dialects, bool, 0644); | ||
| 88 | MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " | ||
| 89 | "helpful to restrict the ability to " | ||
| 90 | "override the default dialects (SMB2.1, " | ||
| 91 | "SMB3 and SMB3.02) on mount with old " | ||
| 92 | "dialects (CIFS/SMB1 and SMB2) since " | ||
| 93 | "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker" | ||
| 94 | " and less secure. Default: n/N/0"); | ||
| 95 | |||
| 84 | extern mempool_t *cifs_sm_req_poolp; | 96 | extern mempool_t *cifs_sm_req_poolp; |
| 85 | extern mempool_t *cifs_req_poolp; | 97 | extern mempool_t *cifs_req_poolp; |
| 86 | extern mempool_t *cifs_mid_poolp; | 98 | extern mempool_t *cifs_mid_poolp; |
| @@ -469,10 +481,20 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
| 469 | seq_puts(s, ",persistenthandles"); | 481 | seq_puts(s, ",persistenthandles"); |
| 470 | else if (tcon->use_resilient) | 482 | else if (tcon->use_resilient) |
| 471 | seq_puts(s, ",resilienthandles"); | 483 | seq_puts(s, ",resilienthandles"); |
| 484 | |||
| 485 | #ifdef CONFIG_CIFS_SMB311 | ||
| 486 | if (tcon->posix_extensions) | ||
| 487 | seq_puts(s, ",posix"); | ||
| 488 | else if (tcon->unix_ext) | ||
| 489 | seq_puts(s, ",unix"); | ||
| 490 | else | ||
| 491 | seq_puts(s, ",nounix"); | ||
| 492 | #else | ||
| 472 | if (tcon->unix_ext) | 493 | if (tcon->unix_ext) |
| 473 | seq_puts(s, ",unix"); | 494 | seq_puts(s, ",unix"); |
| 474 | else | 495 | else |
| 475 | seq_puts(s, ",nounix"); | 496 | seq_puts(s, ",nounix"); |
| 497 | #endif /* SMB311 */ | ||
| 476 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 498 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
| 477 | seq_puts(s, ",posixpaths"); | 499 | seq_puts(s, ",posixpaths"); |
| 478 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) | 500 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) |
| @@ -495,6 +517,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
| 495 | seq_puts(s, ",sfu"); | 517 | seq_puts(s, ",sfu"); |
| 496 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 518 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
| 497 | seq_puts(s, ",nobrl"); | 519 | seq_puts(s, ",nobrl"); |
| 520 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE) | ||
| 521 | seq_puts(s, ",nohandlecache"); | ||
| 498 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 522 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
| 499 | seq_puts(s, ",cifsacl"); | 523 | seq_puts(s, ",cifsacl"); |
| 500 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | 524 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) |
| @@ -897,6 +921,17 @@ struct file_system_type cifs_fs_type = { | |||
| 897 | /* .fs_flags */ | 921 | /* .fs_flags */ |
| 898 | }; | 922 | }; |
| 899 | MODULE_ALIAS_FS("cifs"); | 923 | MODULE_ALIAS_FS("cifs"); |
| 924 | |||
| 925 | static struct file_system_type smb3_fs_type = { | ||
| 926 | .owner = THIS_MODULE, | ||
| 927 | .name = "smb3", | ||
| 928 | .mount = cifs_do_mount, | ||
| 929 | .kill_sb = cifs_kill_sb, | ||
| 930 | /* .fs_flags */ | ||
| 931 | }; | ||
| 932 | MODULE_ALIAS_FS("smb3"); | ||
| 933 | MODULE_ALIAS("smb3"); | ||
| 934 | |||
| 900 | const struct inode_operations cifs_dir_inode_ops = { | 935 | const struct inode_operations cifs_dir_inode_ops = { |
| 901 | .create = cifs_create, | 936 | .create = cifs_create, |
| 902 | .atomic_open = cifs_atomic_open, | 937 | .atomic_open = cifs_atomic_open, |
| @@ -1435,6 +1470,12 @@ init_cifs(void) | |||
| 1435 | if (rc) | 1470 | if (rc) |
| 1436 | goto out_init_cifs_idmap; | 1471 | goto out_init_cifs_idmap; |
| 1437 | 1472 | ||
| 1473 | rc = register_filesystem(&smb3_fs_type); | ||
| 1474 | if (rc) { | ||
| 1475 | unregister_filesystem(&cifs_fs_type); | ||
| 1476 | goto out_init_cifs_idmap; | ||
| 1477 | } | ||
| 1478 | |||
| 1438 | return 0; | 1479 | return 0; |
| 1439 | 1480 | ||
| 1440 | out_init_cifs_idmap: | 1481 | out_init_cifs_idmap: |
| @@ -1465,8 +1506,9 @@ out_clean_proc: | |||
| 1465 | static void __exit | 1506 | static void __exit |
| 1466 | exit_cifs(void) | 1507 | exit_cifs(void) |
| 1467 | { | 1508 | { |
| 1468 | cifs_dbg(NOISY, "exit_cifs\n"); | 1509 | cifs_dbg(NOISY, "exit_smb3\n"); |
| 1469 | unregister_filesystem(&cifs_fs_type); | 1510 | unregister_filesystem(&cifs_fs_type); |
| 1511 | unregister_filesystem(&smb3_fs_type); | ||
| 1470 | cifs_dfs_release_automount_timer(); | 1512 | cifs_dfs_release_automount_timer(); |
| 1471 | #ifdef CONFIG_CIFS_ACL | 1513 | #ifdef CONFIG_CIFS_ACL |
| 1472 | exit_cifs_idmap(); | 1514 | exit_cifs_idmap(); |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 013ba2aed8d9..5f0231803431 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 149 | extern const struct export_operations cifs_export_ops; | 149 | extern const struct export_operations cifs_export_ops; |
| 150 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 150 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
| 151 | 151 | ||
| 152 | #define CIFS_VERSION "2.11" | 152 | #define CIFS_VERSION "2.12" |
| 153 | #endif /* _CIFSFS_H */ | 153 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index cb950a5fa078..08d1cdd96701 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -176,6 +176,7 @@ struct smb_rqst { | |||
| 176 | struct kvec *rq_iov; /* array of kvecs */ | 176 | struct kvec *rq_iov; /* array of kvecs */ |
| 177 | unsigned int rq_nvec; /* number of kvecs in array */ | 177 | unsigned int rq_nvec; /* number of kvecs in array */ |
| 178 | struct page **rq_pages; /* pointer to array of page ptrs */ | 178 | struct page **rq_pages; /* pointer to array of page ptrs */ |
| 179 | unsigned int rq_offset; /* the offset to the 1st page */ | ||
| 179 | unsigned int rq_npages; /* number pages in array */ | 180 | unsigned int rq_npages; /* number pages in array */ |
| 180 | unsigned int rq_pagesz; /* page size to use */ | 181 | unsigned int rq_pagesz; /* page size to use */ |
| 181 | unsigned int rq_tailsz; /* length of last page */ | 182 | unsigned int rq_tailsz; /* length of last page */ |
| @@ -244,7 +245,7 @@ struct smb_version_operations { | |||
| 244 | int (*map_error)(char *, bool); | 245 | int (*map_error)(char *, bool); |
| 245 | /* find mid corresponding to the response message */ | 246 | /* find mid corresponding to the response message */ |
| 246 | struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *); | 247 | struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *); |
| 247 | void (*dump_detail)(void *); | 248 | void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info); |
| 248 | void (*clear_stats)(struct cifs_tcon *); | 249 | void (*clear_stats)(struct cifs_tcon *); |
| 249 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); | 250 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); |
| 250 | void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); | 251 | void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); |
| @@ -372,7 +373,7 @@ struct smb_version_operations { | |||
| 372 | int (*close_dir)(const unsigned int, struct cifs_tcon *, | 373 | int (*close_dir)(const unsigned int, struct cifs_tcon *, |
| 373 | struct cifs_fid *); | 374 | struct cifs_fid *); |
| 374 | /* calculate a size of SMB message */ | 375 | /* calculate a size of SMB message */ |
| 375 | unsigned int (*calc_smb_size)(void *); | 376 | unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi); |
| 376 | /* check for STATUS_PENDING and process it in a positive case */ | 377 | /* check for STATUS_PENDING and process it in a positive case */ |
| 377 | bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); | 378 | bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); |
| 378 | /* check for STATUS_NETWORK_SESSION_EXPIRED */ | 379 | /* check for STATUS_NETWORK_SESSION_EXPIRED */ |
| @@ -417,7 +418,7 @@ struct smb_version_operations { | |||
| 417 | /* create lease context buffer for CREATE request */ | 418 | /* create lease context buffer for CREATE request */ |
| 418 | char * (*create_lease_buf)(u8 *, u8); | 419 | char * (*create_lease_buf)(u8 *, u8); |
| 419 | /* parse lease context buffer and return oplock/epoch info */ | 420 | /* parse lease context buffer and return oplock/epoch info */ |
| 420 | __u8 (*parse_lease_buf)(void *, unsigned int *); | 421 | __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey); |
| 421 | ssize_t (*copychunk_range)(const unsigned int, | 422 | ssize_t (*copychunk_range)(const unsigned int, |
| 422 | struct cifsFileInfo *src_file, | 423 | struct cifsFileInfo *src_file, |
| 423 | struct cifsFileInfo *target_file, | 424 | struct cifsFileInfo *target_file, |
| @@ -457,7 +458,7 @@ struct smb_version_operations { | |||
| 457 | struct mid_q_entry **); | 458 | struct mid_q_entry **); |
| 458 | enum securityEnum (*select_sectype)(struct TCP_Server_Info *, | 459 | enum securityEnum (*select_sectype)(struct TCP_Server_Info *, |
| 459 | enum securityEnum); | 460 | enum securityEnum); |
| 460 | 461 | int (*next_header)(char *); | |
| 461 | }; | 462 | }; |
| 462 | 463 | ||
| 463 | struct smb_version_values { | 464 | struct smb_version_values { |
| @@ -521,10 +522,12 @@ struct smb_vol { | |||
| 521 | bool sfu_remap:1; /* remap seven reserved chars ala SFU */ | 522 | bool sfu_remap:1; /* remap seven reserved chars ala SFU */ |
| 522 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 523 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
| 523 | bool no_linux_ext:1; | 524 | bool no_linux_ext:1; |
| 525 | bool linux_ext:1; | ||
| 524 | bool sfu_emul:1; | 526 | bool sfu_emul:1; |
| 525 | bool nullauth:1; /* attempt to authenticate with null user */ | 527 | bool nullauth:1; /* attempt to authenticate with null user */ |
| 526 | bool nocase:1; /* request case insensitive filenames */ | 528 | bool nocase:1; /* request case insensitive filenames */ |
| 527 | bool nobrl:1; /* disable sending byte range locks to srv */ | 529 | bool nobrl:1; /* disable sending byte range locks to srv */ |
| 530 | bool nohandlecache:1; /* disable caching dir handles if srvr probs */ | ||
| 528 | bool mand_lock:1; /* send mandatory not posix byte range lock reqs */ | 531 | bool mand_lock:1; /* send mandatory not posix byte range lock reqs */ |
| 529 | bool seal:1; /* request transport encryption on share */ | 532 | bool seal:1; /* request transport encryption on share */ |
| 530 | bool nodfs:1; /* Do not request DFS, even if available */ | 533 | bool nodfs:1; /* Do not request DFS, even if available */ |
| @@ -630,7 +633,7 @@ struct TCP_Server_Info { | |||
| 630 | bool oplocks:1; /* enable oplocks */ | 633 | bool oplocks:1; /* enable oplocks */ |
| 631 | unsigned int maxReq; /* Clients should submit no more */ | 634 | unsigned int maxReq; /* Clients should submit no more */ |
| 632 | /* than maxReq distinct unanswered SMBs to the server when using */ | 635 | /* than maxReq distinct unanswered SMBs to the server when using */ |
| 633 | /* multiplexed reads or writes */ | 636 | /* multiplexed reads or writes (for SMB1/CIFS only, not SMB2/SMB3) */ |
| 634 | unsigned int maxBuf; /* maxBuf specifies the maximum */ | 637 | unsigned int maxBuf; /* maxBuf specifies the maximum */ |
| 635 | /* message size the server can send or receive for non-raw SMBs */ | 638 | /* message size the server can send or receive for non-raw SMBs */ |
| 636 | /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ | 639 | /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ |
| @@ -681,6 +684,7 @@ struct TCP_Server_Info { | |||
| 681 | __le16 cipher_type; | 684 | __le16 cipher_type; |
| 682 | /* save initital negprot hash */ | 685 | /* save initital negprot hash */ |
| 683 | __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; | 686 | __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; |
| 687 | bool posix_ext_supported; | ||
| 684 | #endif /* 3.1.1 */ | 688 | #endif /* 3.1.1 */ |
| 685 | struct delayed_work reconnect; /* reconnect workqueue job */ | 689 | struct delayed_work reconnect; /* reconnect workqueue job */ |
| 686 | struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ | 690 | struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ |
| @@ -953,9 +957,13 @@ struct cifs_tcon { | |||
| 953 | bool print:1; /* set if connection to printer share */ | 957 | bool print:1; /* set if connection to printer share */ |
| 954 | bool retry:1; | 958 | bool retry:1; |
| 955 | bool nocase:1; | 959 | bool nocase:1; |
| 960 | bool nohandlecache:1; /* if strange server resource prob can turn off */ | ||
| 956 | bool seal:1; /* transport encryption for this mounted share */ | 961 | bool seal:1; /* transport encryption for this mounted share */ |
| 957 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol | 962 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol |
| 958 | for this mount even if server would support */ | 963 | for this mount even if server would support */ |
| 964 | #ifdef CONFIG_CIFS_SMB311 | ||
| 965 | bool posix_extensions; /* if true SMB3.11 posix extensions enabled */ | ||
| 966 | #endif /* CIFS_311 */ | ||
| 959 | bool local_lease:1; /* check leases (only) on local system not remote */ | 967 | bool local_lease:1; /* check leases (only) on local system not remote */ |
| 960 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ | 968 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ |
| 961 | bool broken_sparse_sup; /* if server or share does not support sparse */ | 969 | bool broken_sparse_sup; /* if server or share does not support sparse */ |
| @@ -979,6 +987,9 @@ struct cifs_tcon { | |||
| 979 | struct fscache_cookie *fscache; /* cookie for share */ | 987 | struct fscache_cookie *fscache; /* cookie for share */ |
| 980 | #endif | 988 | #endif |
| 981 | struct list_head pending_opens; /* list of incomplete opens */ | 989 | struct list_head pending_opens; /* list of incomplete opens */ |
| 990 | bool valid_root_fid:1; /* Do we have a useable root fid */ | ||
| 991 | struct mutex prfid_mutex; /* prevents reopen race after dead ses*/ | ||
| 992 | struct cifs_fid *prfid; /* handle to the directory at top of share */ | ||
| 982 | /* BB add field for back pointer to sb struct(s)? */ | 993 | /* BB add field for back pointer to sb struct(s)? */ |
| 983 | }; | 994 | }; |
| 984 | 995 | ||
| @@ -1071,6 +1082,7 @@ struct cifs_open_parms { | |||
| 1071 | int create_options; | 1082 | int create_options; |
| 1072 | const char *path; | 1083 | const char *path; |
| 1073 | struct cifs_fid *fid; | 1084 | struct cifs_fid *fid; |
| 1085 | umode_t mode; | ||
| 1074 | bool reconnect:1; | 1086 | bool reconnect:1; |
| 1075 | }; | 1087 | }; |
| 1076 | 1088 | ||
| @@ -1169,10 +1181,11 @@ struct cifs_readdata { | |||
| 1169 | struct smbd_mr *mr; | 1181 | struct smbd_mr *mr; |
| 1170 | #endif | 1182 | #endif |
| 1171 | unsigned int pagesz; | 1183 | unsigned int pagesz; |
| 1184 | unsigned int page_offset; | ||
| 1172 | unsigned int tailsz; | 1185 | unsigned int tailsz; |
| 1173 | unsigned int credits; | 1186 | unsigned int credits; |
| 1174 | unsigned int nr_pages; | 1187 | unsigned int nr_pages; |
| 1175 | struct page *pages[]; | 1188 | struct page **pages; |
| 1176 | }; | 1189 | }; |
| 1177 | 1190 | ||
| 1178 | struct cifs_writedata; | 1191 | struct cifs_writedata; |
| @@ -1194,10 +1207,11 @@ struct cifs_writedata { | |||
| 1194 | struct smbd_mr *mr; | 1207 | struct smbd_mr *mr; |
| 1195 | #endif | 1208 | #endif |
| 1196 | unsigned int pagesz; | 1209 | unsigned int pagesz; |
| 1210 | unsigned int page_offset; | ||
| 1197 | unsigned int tailsz; | 1211 | unsigned int tailsz; |
| 1198 | unsigned int credits; | 1212 | unsigned int credits; |
| 1199 | unsigned int nr_pages; | 1213 | unsigned int nr_pages; |
| 1200 | struct page *pages[]; | 1214 | struct page **pages; |
| 1201 | }; | 1215 | }; |
| 1202 | 1216 | ||
| 1203 | /* | 1217 | /* |
| @@ -1692,16 +1706,17 @@ GLOBAL_EXTERN atomic_t smBufAllocCount; | |||
| 1692 | GLOBAL_EXTERN atomic_t midCount; | 1706 | GLOBAL_EXTERN atomic_t midCount; |
| 1693 | 1707 | ||
| 1694 | /* Misc globals */ | 1708 | /* Misc globals */ |
| 1695 | GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */ | 1709 | extern bool enable_oplocks; /* enable or disable oplocks */ |
| 1696 | GLOBAL_EXTERN bool lookupCacheEnabled; | 1710 | extern bool lookupCacheEnabled; |
| 1697 | GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent | 1711 | extern unsigned int global_secflags; /* if on, session setup sent |
| 1698 | with more secure ntlmssp2 challenge/resp */ | 1712 | with more secure ntlmssp2 challenge/resp */ |
| 1699 | GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ | 1713 | extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ |
| 1700 | GLOBAL_EXTERN bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ | 1714 | extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ |
| 1701 | GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ | 1715 | extern unsigned int CIFSMaxBufSize; /* max size not including hdr */ |
| 1702 | GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ | 1716 | extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ |
| 1703 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ | 1717 | extern unsigned int cifs_min_small; /* min size of small buf pool */ |
| 1704 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | 1718 | extern unsigned int cifs_max_pending; /* MAX requests at once to server*/ |
| 1719 | extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */ | ||
| 1705 | 1720 | ||
| 1706 | #ifdef CONFIG_CIFS_ACL | 1721 | #ifdef CONFIG_CIFS_ACL |
| 1707 | GLOBAL_EXTERN struct rb_root uidtree; | 1722 | GLOBAL_EXTERN struct rb_root uidtree; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 365a414a75e9..7933c5f9c076 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #ifndef _CIFSPROTO_H | 21 | #ifndef _CIFSPROTO_H |
| 22 | #define _CIFSPROTO_H | 22 | #define _CIFSPROTO_H |
| 23 | #include <linux/nls.h> | 23 | #include <linux/nls.h> |
| 24 | #include "trace.h" | ||
| 24 | 25 | ||
| 25 | struct statfs; | 26 | struct statfs; |
| 26 | struct smb_vol; | 27 | struct smb_vol; |
| @@ -47,6 +48,7 @@ extern void _free_xid(unsigned int); | |||
| 47 | cifs_dbg(FYI, "CIFS VFS: in %s as Xid: %u with uid: %d\n", \ | 48 | cifs_dbg(FYI, "CIFS VFS: in %s as Xid: %u with uid: %d\n", \ |
| 48 | __func__, __xid, \ | 49 | __func__, __xid, \ |
| 49 | from_kuid(&init_user_ns, current_fsuid())); \ | 50 | from_kuid(&init_user_ns, current_fsuid())); \ |
| 51 | trace_smb3_enter(__xid, __func__); \ | ||
| 50 | __xid; \ | 52 | __xid; \ |
| 51 | }) | 53 | }) |
| 52 | 54 | ||
| @@ -54,7 +56,11 @@ extern void _free_xid(unsigned int); | |||
| 54 | do { \ | 56 | do { \ |
| 55 | _free_xid(curr_xid); \ | 57 | _free_xid(curr_xid); \ |
| 56 | cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \ | 58 | cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \ |
| 57 | __func__, curr_xid, (int)rc); \ | 59 | __func__, curr_xid, (int)rc); \ |
| 60 | if (rc) \ | ||
| 61 | trace_smb3_exit_err(curr_xid, __func__, (int)rc); \ | ||
| 62 | else \ | ||
| 63 | trace_smb3_exit_done(curr_xid, __func__); \ | ||
| 58 | } while (0) | 64 | } while (0) |
| 59 | extern int init_cifs_idmap(void); | 65 | extern int init_cifs_idmap(void); |
| 60 | extern void exit_cifs_idmap(void); | 66 | extern void exit_cifs_idmap(void); |
| @@ -124,7 +130,7 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
| 124 | unsigned int bytes_written); | 130 | unsigned int bytes_written); |
| 125 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | 131 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
| 126 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 132 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
| 127 | extern unsigned int smbCalcSize(void *buf); | 133 | extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); |
| 128 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 134 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
| 129 | struct TCP_Server_Info *server); | 135 | struct TCP_Server_Info *server); |
| 130 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 136 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
| @@ -197,7 +203,9 @@ extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); | |||
| 197 | extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, | 203 | extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, |
| 198 | unsigned int to_read); | 204 | unsigned int to_read); |
| 199 | extern int cifs_read_page_from_socket(struct TCP_Server_Info *server, | 205 | extern int cifs_read_page_from_socket(struct TCP_Server_Info *server, |
| 200 | struct page *page, unsigned int to_read); | 206 | struct page *page, |
| 207 | unsigned int page_offset, | ||
| 208 | unsigned int to_read); | ||
| 201 | extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | 209 | extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, |
| 202 | struct cifs_sb_info *cifs_sb); | 210 | struct cifs_sb_info *cifs_sb); |
| 203 | extern int cifs_match_super(struct super_block *, void *); | 211 | extern int cifs_match_super(struct super_block *, void *); |
| @@ -525,6 +533,8 @@ int cifs_async_writev(struct cifs_writedata *wdata, | |||
| 525 | void cifs_writev_complete(struct work_struct *work); | 533 | void cifs_writev_complete(struct work_struct *work); |
| 526 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 534 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
| 527 | work_func_t complete); | 535 | work_func_t complete); |
| 536 | struct cifs_writedata *cifs_writedata_direct_alloc(struct page **pages, | ||
| 537 | work_func_t complete); | ||
| 528 | void cifs_writedata_release(struct kref *refcount); | 538 | void cifs_writedata_release(struct kref *refcount); |
| 529 | int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | 539 | int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
| 530 | struct cifs_sb_info *cifs_sb, | 540 | struct cifs_sb_info *cifs_sb, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1529a088383d..5aca336642c0 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -106,6 +106,12 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) | |||
| 106 | open_file->oplock_break_cancelled = true; | 106 | open_file->oplock_break_cancelled = true; |
| 107 | } | 107 | } |
| 108 | spin_unlock(&tcon->open_file_lock); | 108 | spin_unlock(&tcon->open_file_lock); |
| 109 | |||
| 110 | mutex_lock(&tcon->prfid_mutex); | ||
| 111 | tcon->valid_root_fid = false; | ||
| 112 | memset(tcon->prfid, 0, sizeof(struct cifs_fid)); | ||
| 113 | mutex_unlock(&tcon->prfid_mutex); | ||
| 114 | |||
| 109 | /* | 115 | /* |
| 110 | * BB Add call to invalidate_inodes(sb) for all superblocks mounted | 116 | * BB Add call to invalidate_inodes(sb) for all superblocks mounted |
| 111 | * to this tcon. | 117 | * to this tcon. |
| @@ -1946,6 +1952,7 @@ cifs_writedata_release(struct kref *refcount) | |||
| 1946 | if (wdata->cfile) | 1952 | if (wdata->cfile) |
| 1947 | cifsFileInfo_put(wdata->cfile); | 1953 | cifsFileInfo_put(wdata->cfile); |
| 1948 | 1954 | ||
| 1955 | kvfree(wdata->pages); | ||
| 1949 | kfree(wdata); | 1956 | kfree(wdata); |
| 1950 | } | 1957 | } |
| 1951 | 1958 | ||
| @@ -2069,12 +2076,22 @@ cifs_writev_complete(struct work_struct *work) | |||
| 2069 | struct cifs_writedata * | 2076 | struct cifs_writedata * |
| 2070 | cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) | 2077 | cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) |
| 2071 | { | 2078 | { |
| 2079 | struct page **pages = | ||
| 2080 | kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); | ||
| 2081 | if (pages) | ||
| 2082 | return cifs_writedata_direct_alloc(pages, complete); | ||
| 2083 | |||
| 2084 | return NULL; | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | struct cifs_writedata * | ||
| 2088 | cifs_writedata_direct_alloc(struct page **pages, work_func_t complete) | ||
| 2089 | { | ||
| 2072 | struct cifs_writedata *wdata; | 2090 | struct cifs_writedata *wdata; |
| 2073 | 2091 | ||
| 2074 | /* writedata + number of page pointers */ | 2092 | wdata = kzalloc(sizeof(*wdata), GFP_NOFS); |
| 2075 | wdata = kzalloc(sizeof(*wdata) + | ||
| 2076 | sizeof(struct page *) * nr_pages, GFP_NOFS); | ||
| 2077 | if (wdata != NULL) { | 2093 | if (wdata != NULL) { |
| 2094 | wdata->pages = pages; | ||
| 2078 | kref_init(&wdata->refcount); | 2095 | kref_init(&wdata->refcount); |
| 2079 | INIT_LIST_HEAD(&wdata->list); | 2096 | INIT_LIST_HEAD(&wdata->list); |
| 2080 | init_completion(&wdata->done); | 2097 | init_completion(&wdata->done); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7a10a5d0731f..e5a2fe7f0dd4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | #define RFC1001_PORT 139 | 61 | #define RFC1001_PORT 139 |
| 62 | 62 | ||
| 63 | extern mempool_t *cifs_req_poolp; | 63 | extern mempool_t *cifs_req_poolp; |
| 64 | extern bool disable_legacy_dialects; | ||
| 64 | 65 | ||
| 65 | /* FIXME: should these be tunable? */ | 66 | /* FIXME: should these be tunable? */ |
| 66 | #define TLINK_ERROR_EXPIRE (1 * HZ) | 67 | #define TLINK_ERROR_EXPIRE (1 * HZ) |
| @@ -76,9 +77,10 @@ enum { | |||
| 76 | Opt_mapposix, Opt_nomapposix, | 77 | Opt_mapposix, Opt_nomapposix, |
| 77 | Opt_mapchars, Opt_nomapchars, Opt_sfu, | 78 | Opt_mapchars, Opt_nomapchars, Opt_sfu, |
| 78 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, | 79 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, |
| 79 | Opt_noposixpaths, Opt_nounix, | 80 | Opt_noposixpaths, Opt_nounix, Opt_unix, |
| 80 | Opt_nocase, | 81 | Opt_nocase, |
| 81 | Opt_brl, Opt_nobrl, | 82 | Opt_brl, Opt_nobrl, |
| 83 | Opt_handlecache, Opt_nohandlecache, | ||
| 82 | Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids, | 84 | Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids, |
| 83 | Opt_nosetuids, Opt_dynperm, Opt_nodynperm, | 85 | Opt_nosetuids, Opt_dynperm, Opt_nodynperm, |
| 84 | Opt_nohard, Opt_nosoft, | 86 | Opt_nohard, Opt_nosoft, |
| @@ -144,10 +146,16 @@ static const match_table_t cifs_mount_option_tokens = { | |||
| 144 | { Opt_noposixpaths, "noposixpaths" }, | 146 | { Opt_noposixpaths, "noposixpaths" }, |
| 145 | { Opt_nounix, "nounix" }, | 147 | { Opt_nounix, "nounix" }, |
| 146 | { Opt_nounix, "nolinux" }, | 148 | { Opt_nounix, "nolinux" }, |
| 149 | { Opt_nounix, "noposix" }, | ||
| 150 | { Opt_unix, "unix" }, | ||
| 151 | { Opt_unix, "linux" }, | ||
| 152 | { Opt_unix, "posix" }, | ||
| 147 | { Opt_nocase, "nocase" }, | 153 | { Opt_nocase, "nocase" }, |
| 148 | { Opt_nocase, "ignorecase" }, | 154 | { Opt_nocase, "ignorecase" }, |
| 149 | { Opt_brl, "brl" }, | 155 | { Opt_brl, "brl" }, |
| 150 | { Opt_nobrl, "nobrl" }, | 156 | { Opt_nobrl, "nobrl" }, |
| 157 | { Opt_handlecache, "handlecache" }, | ||
| 158 | { Opt_nohandlecache, "nohandlecache" }, | ||
| 151 | { Opt_nobrl, "nolock" }, | 159 | { Opt_nobrl, "nolock" }, |
| 152 | { Opt_forcemandatorylock, "forcemandatorylock" }, | 160 | { Opt_forcemandatorylock, "forcemandatorylock" }, |
| 153 | { Opt_forcemandatorylock, "forcemand" }, | 161 | { Opt_forcemandatorylock, "forcemand" }, |
| @@ -591,10 +599,11 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, | |||
| 591 | 599 | ||
| 592 | int | 600 | int |
| 593 | cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, | 601 | cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, |
| 594 | unsigned int to_read) | 602 | unsigned int page_offset, unsigned int to_read) |
| 595 | { | 603 | { |
| 596 | struct msghdr smb_msg; | 604 | struct msghdr smb_msg; |
| 597 | struct bio_vec bv = {.bv_page = page, .bv_len = to_read}; | 605 | struct bio_vec bv = { |
| 606 | .bv_page = page, .bv_len = to_read, .bv_offset = page_offset}; | ||
| 598 | iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); | 607 | iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); |
| 599 | return cifs_readv_from_socket(server, &smb_msg); | 608 | return cifs_readv_from_socket(server, &smb_msg); |
| 600 | } | 609 | } |
| @@ -848,6 +857,7 @@ cifs_demultiplex_thread(void *p) | |||
| 848 | int length; | 857 | int length; |
| 849 | struct TCP_Server_Info *server = p; | 858 | struct TCP_Server_Info *server = p; |
| 850 | unsigned int pdu_length; | 859 | unsigned int pdu_length; |
| 860 | unsigned int next_offset; | ||
| 851 | char *buf = NULL; | 861 | char *buf = NULL; |
| 852 | struct task_struct *task_to_wake = NULL; | 862 | struct task_struct *task_to_wake = NULL; |
| 853 | struct mid_q_entry *mid_entry; | 863 | struct mid_q_entry *mid_entry; |
| @@ -874,24 +884,29 @@ cifs_demultiplex_thread(void *p) | |||
| 874 | length = cifs_read_from_socket(server, buf, pdu_length); | 884 | length = cifs_read_from_socket(server, buf, pdu_length); |
| 875 | if (length < 0) | 885 | if (length < 0) |
| 876 | continue; | 886 | continue; |
| 877 | server->total_read = length; | 887 | |
| 888 | if (server->vals->header_preamble_size == 0) | ||
| 889 | server->total_read = 0; | ||
| 890 | else | ||
| 891 | server->total_read = length; | ||
| 878 | 892 | ||
| 879 | /* | 893 | /* |
| 880 | * The right amount was read from socket - 4 bytes, | 894 | * The right amount was read from socket - 4 bytes, |
| 881 | * so we can now interpret the length field. | 895 | * so we can now interpret the length field. |
| 882 | */ | 896 | */ |
| 883 | pdu_length = get_rfc1002_length(buf); | 897 | pdu_length = get_rfc1002_length(buf); |
| 884 | server->pdu_size = pdu_length; | ||
| 885 | 898 | ||
| 886 | cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); | 899 | cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); |
| 887 | if (!is_smb_response(server, buf[0])) | 900 | if (!is_smb_response(server, buf[0])) |
| 888 | continue; | 901 | continue; |
| 902 | next_pdu: | ||
| 903 | server->pdu_size = pdu_length; | ||
| 889 | 904 | ||
| 890 | /* make sure we have enough to get to the MID */ | 905 | /* make sure we have enough to get to the MID */ |
| 891 | if (pdu_length < HEADER_SIZE(server) - 1 - | 906 | if (server->pdu_size < HEADER_SIZE(server) - 1 - |
| 892 | server->vals->header_preamble_size) { | 907 | server->vals->header_preamble_size) { |
| 893 | cifs_dbg(VFS, "SMB response too short (%u bytes)\n", | 908 | cifs_dbg(VFS, "SMB response too short (%u bytes)\n", |
| 894 | pdu_length); | 909 | server->pdu_size); |
| 895 | cifs_reconnect(server); | 910 | cifs_reconnect(server); |
| 896 | wake_up(&server->response_q); | 911 | wake_up(&server->response_q); |
| 897 | continue; | 912 | continue; |
| @@ -906,6 +921,12 @@ cifs_demultiplex_thread(void *p) | |||
| 906 | continue; | 921 | continue; |
| 907 | server->total_read += length; | 922 | server->total_read += length; |
| 908 | 923 | ||
| 924 | if (server->ops->next_header) { | ||
| 925 | next_offset = server->ops->next_header(buf); | ||
| 926 | if (next_offset) | ||
| 927 | server->pdu_size = next_offset; | ||
| 928 | } | ||
| 929 | |||
| 909 | if (server->ops->is_transform_hdr && | 930 | if (server->ops->is_transform_hdr && |
| 910 | server->ops->receive_transform && | 931 | server->ops->receive_transform && |
| 911 | server->ops->is_transform_hdr(buf)) { | 932 | server->ops->is_transform_hdr(buf)) { |
| @@ -948,10 +969,18 @@ cifs_demultiplex_thread(void *p) | |||
| 948 | HEADER_SIZE(server)); | 969 | HEADER_SIZE(server)); |
| 949 | #ifdef CONFIG_CIFS_DEBUG2 | 970 | #ifdef CONFIG_CIFS_DEBUG2 |
| 950 | if (server->ops->dump_detail) | 971 | if (server->ops->dump_detail) |
| 951 | server->ops->dump_detail(buf); | 972 | server->ops->dump_detail(buf, server); |
| 952 | cifs_dump_mids(server); | 973 | cifs_dump_mids(server); |
| 953 | #endif /* CIFS_DEBUG2 */ | 974 | #endif /* CIFS_DEBUG2 */ |
| 954 | 975 | } | |
| 976 | if (pdu_length > server->pdu_size) { | ||
| 977 | if (!allocate_buffers(server)) | ||
| 978 | continue; | ||
| 979 | pdu_length -= server->pdu_size; | ||
| 980 | server->total_read = 0; | ||
| 981 | server->large_buf = false; | ||
| 982 | buf = server->smallbuf; | ||
| 983 | goto next_pdu; | ||
| 955 | } | 984 | } |
| 956 | } /* end while !EXITING */ | 985 | } /* end while !EXITING */ |
| 957 | 986 | ||
| @@ -1143,10 +1172,18 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) | |||
| 1143 | 1172 | ||
| 1144 | switch (match_token(value, cifs_smb_version_tokens, args)) { | 1173 | switch (match_token(value, cifs_smb_version_tokens, args)) { |
| 1145 | case Smb_1: | 1174 | case Smb_1: |
| 1175 | if (disable_legacy_dialects) { | ||
| 1176 | cifs_dbg(VFS, "mount with legacy dialect disabled\n"); | ||
| 1177 | return 1; | ||
| 1178 | } | ||
| 1146 | vol->ops = &smb1_operations; | 1179 | vol->ops = &smb1_operations; |
| 1147 | vol->vals = &smb1_values; | 1180 | vol->vals = &smb1_values; |
| 1148 | break; | 1181 | break; |
| 1149 | case Smb_20: | 1182 | case Smb_20: |
| 1183 | if (disable_legacy_dialects) { | ||
| 1184 | cifs_dbg(VFS, "mount with legacy dialect disabled\n"); | ||
| 1185 | return 1; | ||
| 1186 | } | ||
| 1150 | vol->ops = &smb20_operations; | 1187 | vol->ops = &smb20_operations; |
| 1151 | vol->vals = &smb20_values; | 1188 | vol->vals = &smb20_values; |
| 1152 | break; | 1189 | break; |
| @@ -1426,8 +1463,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1426 | vol->posix_paths = 0; | 1463 | vol->posix_paths = 0; |
| 1427 | break; | 1464 | break; |
| 1428 | case Opt_nounix: | 1465 | case Opt_nounix: |
| 1466 | if (vol->linux_ext) | ||
| 1467 | cifs_dbg(VFS, | ||
| 1468 | "conflicting unix mount options\n"); | ||
| 1429 | vol->no_linux_ext = 1; | 1469 | vol->no_linux_ext = 1; |
| 1430 | break; | 1470 | break; |
| 1471 | case Opt_unix: | ||
| 1472 | if (vol->no_linux_ext) | ||
| 1473 | cifs_dbg(VFS, | ||
| 1474 | "conflicting unix mount options\n"); | ||
| 1475 | vol->linux_ext = 1; | ||
| 1476 | break; | ||
| 1431 | case Opt_nocase: | 1477 | case Opt_nocase: |
| 1432 | vol->nocase = 1; | 1478 | vol->nocase = 1; |
| 1433 | break; | 1479 | break; |
| @@ -1445,6 +1491,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1445 | (S_IALLUGO & ~(S_ISUID | S_IXGRP))) | 1491 | (S_IALLUGO & ~(S_ISUID | S_IXGRP))) |
| 1446 | vol->file_mode = S_IALLUGO; | 1492 | vol->file_mode = S_IALLUGO; |
| 1447 | break; | 1493 | break; |
| 1494 | case Opt_nohandlecache: | ||
| 1495 | vol->nohandlecache = 1; | ||
| 1496 | break; | ||
| 1497 | case Opt_handlecache: | ||
| 1498 | vol->nohandlecache = 0; | ||
| 1499 | break; | ||
| 1448 | case Opt_forcemandatorylock: | 1500 | case Opt_forcemandatorylock: |
| 1449 | vol->mand_lock = 1; | 1501 | vol->mand_lock = 1; |
| 1450 | break; | 1502 | break; |
| @@ -2967,6 +3019,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2967 | } | 3019 | } |
| 2968 | } | 3020 | } |
| 2969 | 3021 | ||
| 3022 | #ifdef CONFIG_CIFS_SMB311 | ||
| 3023 | if ((volume_info->linux_ext) && (ses->server->posix_ext_supported)) { | ||
| 3024 | if (ses->server->vals->protocol_id == SMB311_PROT_ID) | ||
| 3025 | tcon->posix_extensions = true; | ||
| 3026 | } | ||
| 3027 | #endif /* 311 */ | ||
| 3028 | |||
| 2970 | /* | 3029 | /* |
| 2971 | * BB Do we need to wrap session_mutex around this TCon call and Unix | 3030 | * BB Do we need to wrap session_mutex around this TCon call and Unix |
| 2972 | * SetFS as we do on SessSetup and reconnect? | 3031 | * SetFS as we do on SessSetup and reconnect? |
| @@ -3022,6 +3081,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 3022 | */ | 3081 | */ |
| 3023 | tcon->retry = volume_info->retry; | 3082 | tcon->retry = volume_info->retry; |
| 3024 | tcon->nocase = volume_info->nocase; | 3083 | tcon->nocase = volume_info->nocase; |
| 3084 | tcon->nohandlecache = volume_info->nohandlecache; | ||
| 3025 | tcon->local_lease = volume_info->local_lease; | 3085 | tcon->local_lease = volume_info->local_lease; |
| 3026 | INIT_LIST_HEAD(&tcon->pending_opens); | 3086 | INIT_LIST_HEAD(&tcon->pending_opens); |
| 3027 | 3087 | ||
| @@ -3580,6 +3640,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 3580 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | 3640 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; |
| 3581 | if (pvolume_info->nobrl) | 3641 | if (pvolume_info->nobrl) |
| 3582 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | 3642 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; |
| 3643 | if (pvolume_info->nohandlecache) | ||
| 3644 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE; | ||
| 3583 | if (pvolume_info->nostrictsync) | 3645 | if (pvolume_info->nostrictsync) |
| 3584 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; | 3646 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; |
| 3585 | if (pvolume_info->mand_lock) | 3647 | if (pvolume_info->mand_lock) |
| @@ -3922,6 +3984,12 @@ try_mount_again: | |||
| 3922 | goto remote_path_check; | 3984 | goto remote_path_check; |
| 3923 | } | 3985 | } |
| 3924 | 3986 | ||
| 3987 | #ifdef CONFIG_CIFS_SMB311 | ||
| 3988 | /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ | ||
| 3989 | if (tcon->posix_extensions) | ||
| 3990 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | ||
| 3991 | #endif /* SMB3.11 */ | ||
| 3992 | |||
| 3925 | /* tell server which Unix caps we support */ | 3993 | /* tell server which Unix caps we support */ |
| 3926 | if (cap_unix(tcon->ses)) { | 3994 | if (cap_unix(tcon->ses)) { |
| 3927 | /* reset of caps checks mount to see if unix extensions | 3995 | /* reset of caps checks mount to see if unix extensions |
| @@ -4353,6 +4421,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) | |||
| 4353 | vol_info->UNC = master_tcon->treeName; | 4421 | vol_info->UNC = master_tcon->treeName; |
| 4354 | vol_info->retry = master_tcon->retry; | 4422 | vol_info->retry = master_tcon->retry; |
| 4355 | vol_info->nocase = master_tcon->nocase; | 4423 | vol_info->nocase = master_tcon->nocase; |
| 4424 | vol_info->nohandlecache = master_tcon->nohandlecache; | ||
| 4356 | vol_info->local_lease = master_tcon->local_lease; | 4425 | vol_info->local_lease = master_tcon->local_lease; |
| 4357 | vol_info->no_linux_ext = !master_tcon->unix_ext; | 4426 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
| 4358 | vol_info->sectype = master_tcon->ses->sectype; | 4427 | vol_info->sectype = master_tcon->ses->sectype; |
| @@ -4382,8 +4451,14 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) | |||
| 4382 | goto out; | 4451 | goto out; |
| 4383 | } | 4452 | } |
| 4384 | 4453 | ||
| 4454 | #ifdef CONFIG_CIFS_SMB311 | ||
| 4455 | /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ | ||
| 4456 | if (tcon->posix_extensions) | ||
| 4457 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | ||
| 4458 | #endif /* SMB3.11 */ | ||
| 4385 | if (cap_unix(ses)) | 4459 | if (cap_unix(ses)) |
| 4386 | reset_cifs_unix_caps(0, tcon, NULL, vol_info); | 4460 | reset_cifs_unix_caps(0, tcon, NULL, vol_info); |
| 4461 | |||
| 4387 | out: | 4462 | out: |
| 4388 | kfree(vol_info->username); | 4463 | kfree(vol_info->username); |
| 4389 | kzfree(vol_info->password); | 4464 | kzfree(vol_info->password); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 9eb03e8b1ada..ddae52bd1993 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -369,7 +369,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, | |||
| 369 | oparms.path = full_path; | 369 | oparms.path = full_path; |
| 370 | oparms.fid = fid; | 370 | oparms.fid = fid; |
| 371 | oparms.reconnect = false; | 371 | oparms.reconnect = false; |
| 372 | 372 | oparms.mode = mode; | |
| 373 | rc = server->ops->open(xid, &oparms, oplock, buf); | 373 | rc = server->ops->open(xid, &oparms, oplock, buf); |
| 374 | if (rc) { | 374 | if (rc) { |
| 375 | cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); | 375 | cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 23fd430fe74a..87eece6fbd48 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2880,13 +2880,13 @@ out: | |||
| 2880 | } | 2880 | } |
| 2881 | 2881 | ||
| 2882 | static struct cifs_readdata * | 2882 | static struct cifs_readdata * |
| 2883 | cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) | 2883 | cifs_readdata_direct_alloc(struct page **pages, work_func_t complete) |
| 2884 | { | 2884 | { |
| 2885 | struct cifs_readdata *rdata; | 2885 | struct cifs_readdata *rdata; |
| 2886 | 2886 | ||
| 2887 | rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages), | 2887 | rdata = kzalloc(sizeof(*rdata), GFP_KERNEL); |
| 2888 | GFP_KERNEL); | ||
| 2889 | if (rdata != NULL) { | 2888 | if (rdata != NULL) { |
| 2889 | rdata->pages = pages; | ||
| 2890 | kref_init(&rdata->refcount); | 2890 | kref_init(&rdata->refcount); |
| 2891 | INIT_LIST_HEAD(&rdata->list); | 2891 | INIT_LIST_HEAD(&rdata->list); |
| 2892 | init_completion(&rdata->done); | 2892 | init_completion(&rdata->done); |
| @@ -2896,6 +2896,22 @@ cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) | |||
| 2896 | return rdata; | 2896 | return rdata; |
| 2897 | } | 2897 | } |
| 2898 | 2898 | ||
| 2899 | static struct cifs_readdata * | ||
| 2900 | cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) | ||
| 2901 | { | ||
| 2902 | struct page **pages = | ||
| 2903 | kzalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL); | ||
| 2904 | struct cifs_readdata *ret = NULL; | ||
| 2905 | |||
| 2906 | if (pages) { | ||
| 2907 | ret = cifs_readdata_direct_alloc(pages, complete); | ||
| 2908 | if (!ret) | ||
| 2909 | kfree(pages); | ||
| 2910 | } | ||
| 2911 | |||
| 2912 | return ret; | ||
| 2913 | } | ||
| 2914 | |||
| 2899 | void | 2915 | void |
| 2900 | cifs_readdata_release(struct kref *refcount) | 2916 | cifs_readdata_release(struct kref *refcount) |
| 2901 | { | 2917 | { |
| @@ -2910,6 +2926,7 @@ cifs_readdata_release(struct kref *refcount) | |||
| 2910 | if (rdata->cfile) | 2926 | if (rdata->cfile) |
| 2911 | cifsFileInfo_put(rdata->cfile); | 2927 | cifsFileInfo_put(rdata->cfile); |
| 2912 | 2928 | ||
| 2929 | kvfree(rdata->pages); | ||
| 2913 | kfree(rdata); | 2930 | kfree(rdata); |
| 2914 | } | 2931 | } |
| 2915 | 2932 | ||
| @@ -3009,12 +3026,20 @@ uncached_fill_pages(struct TCP_Server_Info *server, | |||
| 3009 | int result = 0; | 3026 | int result = 0; |
| 3010 | unsigned int i; | 3027 | unsigned int i; |
| 3011 | unsigned int nr_pages = rdata->nr_pages; | 3028 | unsigned int nr_pages = rdata->nr_pages; |
| 3029 | unsigned int page_offset = rdata->page_offset; | ||
| 3012 | 3030 | ||
| 3013 | rdata->got_bytes = 0; | 3031 | rdata->got_bytes = 0; |
| 3014 | rdata->tailsz = PAGE_SIZE; | 3032 | rdata->tailsz = PAGE_SIZE; |
| 3015 | for (i = 0; i < nr_pages; i++) { | 3033 | for (i = 0; i < nr_pages; i++) { |
| 3016 | struct page *page = rdata->pages[i]; | 3034 | struct page *page = rdata->pages[i]; |
| 3017 | size_t n; | 3035 | size_t n; |
| 3036 | unsigned int segment_size = rdata->pagesz; | ||
| 3037 | |||
| 3038 | if (i == 0) | ||
| 3039 | segment_size -= page_offset; | ||
| 3040 | else | ||
| 3041 | page_offset = 0; | ||
| 3042 | |||
| 3018 | 3043 | ||
| 3019 | if (len <= 0) { | 3044 | if (len <= 0) { |
| 3020 | /* no need to hold page hostage */ | 3045 | /* no need to hold page hostage */ |
| @@ -3023,24 +3048,25 @@ uncached_fill_pages(struct TCP_Server_Info *server, | |||
| 3023 | put_page(page); | 3048 | put_page(page); |
| 3024 | continue; | 3049 | continue; |
| 3025 | } | 3050 | } |
| 3051 | |||
| 3026 | n = len; | 3052 | n = len; |
| 3027 | if (len >= PAGE_SIZE) { | 3053 | if (len >= segment_size) |
| 3028 | /* enough data to fill the page */ | 3054 | /* enough data to fill the page */ |
| 3029 | n = PAGE_SIZE; | 3055 | n = segment_size; |
| 3030 | len -= n; | 3056 | else |
| 3031 | } else { | ||
| 3032 | zero_user(page, len, PAGE_SIZE - len); | ||
| 3033 | rdata->tailsz = len; | 3057 | rdata->tailsz = len; |
| 3034 | len = 0; | 3058 | len -= n; |
| 3035 | } | 3059 | |
| 3036 | if (iter) | 3060 | if (iter) |
| 3037 | result = copy_page_from_iter(page, 0, n, iter); | 3061 | result = copy_page_from_iter( |
| 3062 | page, page_offset, n, iter); | ||
| 3038 | #ifdef CONFIG_CIFS_SMB_DIRECT | 3063 | #ifdef CONFIG_CIFS_SMB_DIRECT |
| 3039 | else if (rdata->mr) | 3064 | else if (rdata->mr) |
| 3040 | result = n; | 3065 | result = n; |
| 3041 | #endif | 3066 | #endif |
| 3042 | else | 3067 | else |
| 3043 | result = cifs_read_page_from_socket(server, page, n); | 3068 | result = cifs_read_page_from_socket( |
| 3069 | server, page, page_offset, n); | ||
| 3044 | if (result < 0) | 3070 | if (result < 0) |
| 3045 | break; | 3071 | break; |
| 3046 | 3072 | ||
| @@ -3113,6 +3139,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3113 | rdata->bytes = cur_len; | 3139 | rdata->bytes = cur_len; |
| 3114 | rdata->pid = pid; | 3140 | rdata->pid = pid; |
| 3115 | rdata->pagesz = PAGE_SIZE; | 3141 | rdata->pagesz = PAGE_SIZE; |
| 3142 | rdata->tailsz = PAGE_SIZE; | ||
| 3116 | rdata->read_into_pages = cifs_uncached_read_into_pages; | 3143 | rdata->read_into_pages = cifs_uncached_read_into_pages; |
| 3117 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; | 3144 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; |
| 3118 | rdata->credits = credits; | 3145 | rdata->credits = credits; |
| @@ -3557,6 +3584,7 @@ readpages_fill_pages(struct TCP_Server_Info *server, | |||
| 3557 | u64 eof; | 3584 | u64 eof; |
| 3558 | pgoff_t eof_index; | 3585 | pgoff_t eof_index; |
| 3559 | unsigned int nr_pages = rdata->nr_pages; | 3586 | unsigned int nr_pages = rdata->nr_pages; |
| 3587 | unsigned int page_offset = rdata->page_offset; | ||
| 3560 | 3588 | ||
| 3561 | /* determine the eof that the server (probably) has */ | 3589 | /* determine the eof that the server (probably) has */ |
| 3562 | eof = CIFS_I(rdata->mapping->host)->server_eof; | 3590 | eof = CIFS_I(rdata->mapping->host)->server_eof; |
| @@ -3567,13 +3595,21 @@ readpages_fill_pages(struct TCP_Server_Info *server, | |||
| 3567 | rdata->tailsz = PAGE_SIZE; | 3595 | rdata->tailsz = PAGE_SIZE; |
| 3568 | for (i = 0; i < nr_pages; i++) { | 3596 | for (i = 0; i < nr_pages; i++) { |
| 3569 | struct page *page = rdata->pages[i]; | 3597 | struct page *page = rdata->pages[i]; |
| 3570 | size_t n = PAGE_SIZE; | 3598 | unsigned int to_read = rdata->pagesz; |
| 3599 | size_t n; | ||
| 3600 | |||
| 3601 | if (i == 0) | ||
| 3602 | to_read -= page_offset; | ||
| 3603 | else | ||
| 3604 | page_offset = 0; | ||
| 3605 | |||
| 3606 | n = to_read; | ||
| 3571 | 3607 | ||
| 3572 | if (len >= PAGE_SIZE) { | 3608 | if (len >= to_read) { |
| 3573 | len -= PAGE_SIZE; | 3609 | len -= to_read; |
| 3574 | } else if (len > 0) { | 3610 | } else if (len > 0) { |
| 3575 | /* enough for partial page, fill and zero the rest */ | 3611 | /* enough for partial page, fill and zero the rest */ |
| 3576 | zero_user(page, len, PAGE_SIZE - len); | 3612 | zero_user(page, len + page_offset, to_read - len); |
| 3577 | n = rdata->tailsz = len; | 3613 | n = rdata->tailsz = len; |
| 3578 | len = 0; | 3614 | len = 0; |
| 3579 | } else if (page->index > eof_index) { | 3615 | } else if (page->index > eof_index) { |
| @@ -3605,13 +3641,15 @@ readpages_fill_pages(struct TCP_Server_Info *server, | |||
| 3605 | } | 3641 | } |
| 3606 | 3642 | ||
| 3607 | if (iter) | 3643 | if (iter) |
| 3608 | result = copy_page_from_iter(page, 0, n, iter); | 3644 | result = copy_page_from_iter( |
| 3645 | page, page_offset, n, iter); | ||
| 3609 | #ifdef CONFIG_CIFS_SMB_DIRECT | 3646 | #ifdef CONFIG_CIFS_SMB_DIRECT |
| 3610 | else if (rdata->mr) | 3647 | else if (rdata->mr) |
| 3611 | result = n; | 3648 | result = n; |
| 3612 | #endif | 3649 | #endif |
| 3613 | else | 3650 | else |
| 3614 | result = cifs_read_page_from_socket(server, page, n); | 3651 | result = cifs_read_page_from_socket( |
| 3652 | server, page, page_offset, n); | ||
| 3615 | if (result < 0) | 3653 | if (result < 0) |
| 3616 | break; | 3654 | break; |
| 3617 | 3655 | ||
| @@ -3790,6 +3828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 3790 | rdata->bytes = bytes; | 3828 | rdata->bytes = bytes; |
| 3791 | rdata->pid = pid; | 3829 | rdata->pid = pid; |
| 3792 | rdata->pagesz = PAGE_SIZE; | 3830 | rdata->pagesz = PAGE_SIZE; |
| 3831 | rdata->tailsz = PAGE_SIZE; | ||
| 3793 | rdata->read_into_pages = cifs_readpages_read_into_pages; | 3832 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
| 3794 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; | 3833 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; |
| 3795 | rdata->credits = credits; | 3834 | rdata->credits = credits; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3c371f7f5963..745fd7fe8d0e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -746,7 +746,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
| 746 | cifs_dbg(FYI, "Getting info on %s\n", full_path); | 746 | cifs_dbg(FYI, "Getting info on %s\n", full_path); |
| 747 | 747 | ||
| 748 | if ((data == NULL) && (*inode != NULL)) { | 748 | if ((data == NULL) && (*inode != NULL)) { |
| 749 | if (CIFS_CACHE_READ(CIFS_I(*inode))) { | 749 | if (CIFS_CACHE_READ(CIFS_I(*inode)) && |
| 750 | CIFS_I(*inode)->time != 0) { | ||
| 750 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); | 751 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); |
| 751 | goto cgii_exit; | 752 | goto cgii_exit; |
| 752 | } | 753 | } |
| @@ -1857,15 +1858,15 @@ cifs_inode_needs_reval(struct inode *inode) | |||
| 1857 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1858 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
| 1858 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1859 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1859 | 1860 | ||
| 1861 | if (cifs_i->time == 0) | ||
| 1862 | return true; | ||
| 1863 | |||
| 1860 | if (CIFS_CACHE_READ(cifs_i)) | 1864 | if (CIFS_CACHE_READ(cifs_i)) |
| 1861 | return false; | 1865 | return false; |
| 1862 | 1866 | ||
| 1863 | if (!lookupCacheEnabled) | 1867 | if (!lookupCacheEnabled) |
| 1864 | return true; | 1868 | return true; |
| 1865 | 1869 | ||
| 1866 | if (cifs_i->time == 0) | ||
| 1867 | return true; | ||
| 1868 | |||
| 1869 | if (!cifs_sb->actimeo) | 1870 | if (!cifs_sb->actimeo) |
| 1870 | return true; | 1871 | return true; |
| 1871 | 1872 | ||
| @@ -2104,10 +2105,14 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) | |||
| 2104 | 2105 | ||
| 2105 | static void cifs_setsize(struct inode *inode, loff_t offset) | 2106 | static void cifs_setsize(struct inode *inode, loff_t offset) |
| 2106 | { | 2107 | { |
| 2108 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||
| 2109 | |||
| 2107 | spin_lock(&inode->i_lock); | 2110 | spin_lock(&inode->i_lock); |
| 2108 | i_size_write(inode, offset); | 2111 | i_size_write(inode, offset); |
| 2109 | spin_unlock(&inode->i_lock); | 2112 | spin_unlock(&inode->i_lock); |
| 2110 | 2113 | ||
| 2114 | /* Cached inode must be refreshed on truncate */ | ||
| 2115 | cifs_i->time = 0; | ||
| 2111 | truncate_pagecache(inode, offset); | 2116 | truncate_pagecache(inode, offset); |
| 2112 | } | 2117 | } |
| 2113 | 2118 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 460084a8eac5..aba3fc3058da 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -117,6 +117,8 @@ tconInfoAlloc(void) | |||
| 117 | INIT_LIST_HEAD(&ret_buf->openFileList); | 117 | INIT_LIST_HEAD(&ret_buf->openFileList); |
| 118 | INIT_LIST_HEAD(&ret_buf->tcon_list); | 118 | INIT_LIST_HEAD(&ret_buf->tcon_list); |
| 119 | spin_lock_init(&ret_buf->open_file_lock); | 119 | spin_lock_init(&ret_buf->open_file_lock); |
| 120 | mutex_init(&ret_buf->prfid_mutex); | ||
| 121 | ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL); | ||
| 120 | #ifdef CONFIG_CIFS_STATS | 122 | #ifdef CONFIG_CIFS_STATS |
| 121 | spin_lock_init(&ret_buf->stat_lock); | 123 | spin_lock_init(&ret_buf->stat_lock); |
| 122 | #endif | 124 | #endif |
| @@ -134,6 +136,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) | |||
| 134 | atomic_dec(&tconInfoAllocCount); | 136 | atomic_dec(&tconInfoAllocCount); |
| 135 | kfree(buf_to_free->nativeFileSystem); | 137 | kfree(buf_to_free->nativeFileSystem); |
| 136 | kzfree(buf_to_free->password); | 138 | kzfree(buf_to_free->password); |
| 139 | kfree(buf_to_free->prfid); | ||
| 137 | kfree(buf_to_free); | 140 | kfree(buf_to_free); |
| 138 | } | 141 | } |
| 139 | 142 | ||
| @@ -145,7 +148,7 @@ cifs_buf_get(void) | |||
| 145 | * SMB2 header is bigger than CIFS one - no problems to clean some | 148 | * SMB2 header is bigger than CIFS one - no problems to clean some |
| 146 | * more bytes for CIFS. | 149 | * more bytes for CIFS. |
| 147 | */ | 150 | */ |
| 148 | size_t buf_size = sizeof(struct smb2_hdr); | 151 | size_t buf_size = sizeof(struct smb2_sync_hdr); |
| 149 | 152 | ||
| 150 | /* | 153 | /* |
| 151 | * We could use negotiated size instead of max_msgsize - | 154 | * We could use negotiated size instead of max_msgsize - |
| @@ -339,7 +342,7 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) | |||
| 339 | /* otherwise, there is enough to get to the BCC */ | 342 | /* otherwise, there is enough to get to the BCC */ |
| 340 | if (check_smb_hdr(smb)) | 343 | if (check_smb_hdr(smb)) |
| 341 | return -EIO; | 344 | return -EIO; |
| 342 | clc_len = smbCalcSize(smb); | 345 | clc_len = smbCalcSize(smb, server); |
| 343 | 346 | ||
| 344 | if (4 + rfclen != total_read) { | 347 | if (4 + rfclen != total_read) { |
| 345 | cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n", | 348 | cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n", |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index cc88f4f0325e..d7ad0dfe4e68 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -903,7 +903,7 @@ map_smb_to_linux_error(char *buf, bool logErr) | |||
| 903 | * portion, the number of word parameters and the data portion of the message | 903 | * portion, the number of word parameters and the data portion of the message |
| 904 | */ | 904 | */ |
| 905 | unsigned int | 905 | unsigned int |
| 906 | smbCalcSize(void *buf) | 906 | smbCalcSize(void *buf, struct TCP_Server_Info *server) |
| 907 | { | 907 | { |
| 908 | struct smb_hdr *ptr = (struct smb_hdr *)buf; | 908 | struct smb_hdr *ptr = (struct smb_hdr *)buf; |
| 909 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 909 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index a27fc8791551..eeab81c9452f 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -650,7 +650,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, | |||
| 650 | char *cur_ent; | 650 | char *cur_ent; |
| 651 | char *end_of_smb = cfile->srch_inf.ntwrk_buf_start + | 651 | char *end_of_smb = cfile->srch_inf.ntwrk_buf_start + |
| 652 | server->ops->calc_smb_size( | 652 | server->ops->calc_smb_size( |
| 653 | cfile->srch_inf.ntwrk_buf_start); | 653 | cfile->srch_inf.ntwrk_buf_start, |
| 654 | server); | ||
| 654 | 655 | ||
| 655 | cur_ent = cfile->srch_inf.srch_entries_start; | 656 | cur_ent = cfile->srch_inf.srch_entries_start; |
| 656 | first_entry_in_buffer = cfile->srch_inf.index_of_last_entry | 657 | first_entry_in_buffer = cfile->srch_inf.index_of_last_entry |
| @@ -831,7 +832,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) | |||
| 831 | cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", | 832 | cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", |
| 832 | num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); | 833 | num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); |
| 833 | max_len = tcon->ses->server->ops->calc_smb_size( | 834 | max_len = tcon->ses->server->ops->calc_smb_size( |
| 834 | cifsFile->srch_inf.ntwrk_buf_start); | 835 | cifsFile->srch_inf.ntwrk_buf_start, |
| 836 | tcon->ses->server); | ||
| 835 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | 837 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; |
| 836 | 838 | ||
| 837 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); | 839 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); |
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index 401a5d856636..0ffa18094335 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h | |||
| @@ -61,9 +61,4 @@ | |||
| 61 | /* Maximum buffer size value we can send with 1 credit */ | 61 | /* Maximum buffer size value we can send with 1 credit */ |
| 62 | #define SMB2_MAX_BUFFER_SIZE 65536 | 62 | #define SMB2_MAX_BUFFER_SIZE 65536 |
| 63 | 63 | ||
| 64 | static inline struct smb2_sync_hdr *get_sync_hdr(void *buf) | ||
| 65 | { | ||
| 66 | return &(((struct smb2_hdr *)buf)->sync_hdr); | ||
| 67 | } | ||
| 68 | |||
| 69 | #endif /* _SMB2_GLOB_H */ | 64 | #endif /* _SMB2_GLOB_H */ |
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 1238cd3552f9..a6e786e39248 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c | |||
| @@ -44,26 +44,38 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 44 | __u32 create_options, void *data, int command) | 44 | __u32 create_options, void *data, int command) |
| 45 | { | 45 | { |
| 46 | int rc, tmprc = 0; | 46 | int rc, tmprc = 0; |
| 47 | __le16 *utf16_path; | 47 | __le16 *utf16_path = NULL; |
| 48 | __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | 48 | __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; |
| 49 | struct cifs_open_parms oparms; | 49 | struct cifs_open_parms oparms; |
| 50 | struct cifs_fid fid; | 50 | struct cifs_fid fid; |
| 51 | bool use_cached_root_handle = false; | ||
| 51 | 52 | ||
| 52 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); | 53 | if ((strcmp(full_path, "") == 0) && (create_options == 0) && |
| 53 | if (!utf16_path) | 54 | (desired_access == FILE_READ_ATTRIBUTES) && |
| 54 | return -ENOMEM; | 55 | (create_disposition == FILE_OPEN) && |
| 56 | (tcon->nohandlecache == false)) { | ||
| 57 | rc = open_shroot(xid, tcon, &fid); | ||
| 58 | if (rc == 0) | ||
| 59 | use_cached_root_handle = true; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (use_cached_root_handle == false) { | ||
| 63 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); | ||
| 64 | if (!utf16_path) | ||
| 65 | return -ENOMEM; | ||
| 55 | 66 | ||
| 56 | oparms.tcon = tcon; | 67 | oparms.tcon = tcon; |
| 57 | oparms.desired_access = desired_access; | 68 | oparms.desired_access = desired_access; |
| 58 | oparms.disposition = create_disposition; | 69 | oparms.disposition = create_disposition; |
| 59 | oparms.create_options = create_options; | 70 | oparms.create_options = create_options; |
| 60 | oparms.fid = &fid; | 71 | oparms.fid = &fid; |
| 61 | oparms.reconnect = false; | 72 | oparms.reconnect = false; |
| 62 | 73 | ||
| 63 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); | 74 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); |
| 64 | if (rc) { | 75 | if (rc) { |
| 65 | kfree(utf16_path); | 76 | kfree(utf16_path); |
| 66 | return rc; | 77 | return rc; |
| 78 | } | ||
| 67 | } | 79 | } |
| 68 | 80 | ||
| 69 | switch (command) { | 81 | switch (command) { |
| @@ -107,7 +119,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 107 | break; | 119 | break; |
| 108 | } | 120 | } |
| 109 | 121 | ||
| 110 | rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 122 | if (use_cached_root_handle == false) |
| 123 | rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
| 111 | if (tmprc) | 124 | if (tmprc) |
| 112 | rc = tmprc; | 125 | rc = tmprc; |
| 113 | kfree(utf16_path); | 126 | kfree(utf16_path); |
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index 3bfc9c990724..20a2d304c603 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "smb2proto.h" | 27 | #include "smb2proto.h" |
| 28 | #include "smb2status.h" | 28 | #include "smb2status.h" |
| 29 | #include "smb2glob.h" | 29 | #include "smb2glob.h" |
| 30 | #include "trace.h" | ||
| 30 | 31 | ||
| 31 | struct status_to_posix_error { | 32 | struct status_to_posix_error { |
| 32 | __le32 smb2_status; | 33 | __le32 smb2_status; |
| @@ -2450,13 +2451,16 @@ smb2_print_status(__le32 status) | |||
| 2450 | int | 2451 | int |
| 2451 | map_smb2_to_linux_error(char *buf, bool log_err) | 2452 | map_smb2_to_linux_error(char *buf, bool log_err) |
| 2452 | { | 2453 | { |
| 2453 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 2454 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 2454 | unsigned int i; | 2455 | unsigned int i; |
| 2455 | int rc = -EIO; | 2456 | int rc = -EIO; |
| 2456 | __le32 smb2err = shdr->Status; | 2457 | __le32 smb2err = shdr->Status; |
| 2457 | 2458 | ||
| 2458 | if (smb2err == 0) | 2459 | if (smb2err == 0) { |
| 2460 | trace_smb3_cmd_done(shdr->TreeId, shdr->SessionId, | ||
| 2461 | le16_to_cpu(shdr->Command), le64_to_cpu(shdr->MessageId)); | ||
| 2459 | return 0; | 2462 | return 0; |
| 2463 | } | ||
| 2460 | 2464 | ||
| 2461 | /* mask facility */ | 2465 | /* mask facility */ |
| 2462 | if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) && | 2466 | if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) && |
| @@ -2478,5 +2482,8 @@ map_smb2_to_linux_error(char *buf, bool log_err) | |||
| 2478 | cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n", | 2482 | cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n", |
| 2479 | __le32_to_cpu(smb2err), rc); | 2483 | __le32_to_cpu(smb2err), rc); |
| 2480 | 2484 | ||
| 2485 | trace_smb3_cmd_err(shdr->TreeId, shdr->SessionId, | ||
| 2486 | le16_to_cpu(shdr->Command), | ||
| 2487 | le64_to_cpu(shdr->MessageId), le32_to_cpu(smb2err), rc); | ||
| 2481 | return rc; | 2488 | return rc; |
| 2482 | } | 2489 | } |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 68ea8491c160..cb5728e3d87d 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
| @@ -94,8 +94,8 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | #ifdef CONFIG_CIFS_SMB311 | 96 | #ifdef CONFIG_CIFS_SMB311 |
| 97 | static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, | 97 | static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, |
| 98 | size_t hdr_preamble_size) | 98 | __u32 non_ctxlen) |
| 99 | { | 99 | { |
| 100 | __u16 neg_count; | 100 | __u16 neg_count; |
| 101 | __u32 nc_offset, size_of_pad_before_neg_ctxts; | 101 | __u32 nc_offset, size_of_pad_before_neg_ctxts; |
| @@ -109,12 +109,11 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, | |||
| 109 | 109 | ||
| 110 | /* Make sure that negotiate contexts start after gss security blob */ | 110 | /* Make sure that negotiate contexts start after gss security blob */ |
| 111 | nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); | 111 | nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); |
| 112 | if (nc_offset < non_ctxlen - hdr_preamble_size /* RFC1001 len */) { | 112 | if (nc_offset < non_ctxlen) { |
| 113 | printk_once(KERN_WARNING "invalid negotiate context offset\n"); | 113 | printk_once(KERN_WARNING "invalid negotiate context offset\n"); |
| 114 | return 0; | 114 | return 0; |
| 115 | } | 115 | } |
| 116 | size_of_pad_before_neg_ctxts = nc_offset - | 116 | size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; |
| 117 | (non_ctxlen - hdr_preamble_size); | ||
| 118 | 117 | ||
| 119 | /* Verify that at least minimal negotiate contexts fit within frame */ | 118 | /* Verify that at least minimal negotiate contexts fit within frame */ |
| 120 | if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { | 119 | if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { |
| @@ -131,25 +130,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, | |||
| 131 | #endif /* CIFS_SMB311 */ | 130 | #endif /* CIFS_SMB311 */ |
| 132 | 131 | ||
| 133 | int | 132 | int |
| 134 | smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | 133 | smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) |
| 135 | { | 134 | { |
| 136 | struct smb2_pdu *pdu = (struct smb2_pdu *)buf; | 135 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 137 | struct smb2_hdr *hdr = &pdu->hdr; | 136 | struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; |
| 138 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | ||
| 139 | __u64 mid; | 137 | __u64 mid; |
| 140 | __u32 len = get_rfc1002_length(buf); | ||
| 141 | __u32 clc_len; /* calculated length */ | 138 | __u32 clc_len; /* calculated length */ |
| 142 | int command; | 139 | int command; |
| 143 | 140 | int pdu_size = sizeof(struct smb2_sync_pdu); | |
| 144 | /* BB disable following printk later */ | 141 | int hdr_size = sizeof(struct smb2_sync_hdr); |
| 145 | cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n", | ||
| 146 | __func__, length, len); | ||
| 147 | 142 | ||
| 148 | /* | 143 | /* |
| 149 | * Add function to do table lookup of StructureSize by command | 144 | * Add function to do table lookup of StructureSize by command |
| 150 | * ie Validate the wct via smb2_struct_sizes table above | 145 | * ie Validate the wct via smb2_struct_sizes table above |
| 151 | */ | 146 | */ |
| 152 | |||
| 153 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 147 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
| 154 | struct smb2_transform_hdr *thdr = | 148 | struct smb2_transform_hdr *thdr = |
| 155 | (struct smb2_transform_hdr *)buf; | 149 | (struct smb2_transform_hdr *)buf; |
| @@ -173,8 +167,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
| 173 | } | 167 | } |
| 174 | 168 | ||
| 175 | mid = le64_to_cpu(shdr->MessageId); | 169 | mid = le64_to_cpu(shdr->MessageId); |
| 176 | if (length < sizeof(struct smb2_pdu)) { | 170 | if (len < pdu_size) { |
| 177 | if ((length >= sizeof(struct smb2_hdr)) | 171 | if ((len >= hdr_size) |
| 178 | && (shdr->Status != 0)) { | 172 | && (shdr->Status != 0)) { |
| 179 | pdu->StructureSize2 = 0; | 173 | pdu->StructureSize2 = 0; |
| 180 | /* | 174 | /* |
| @@ -187,8 +181,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
| 187 | } | 181 | } |
| 188 | return 1; | 182 | return 1; |
| 189 | } | 183 | } |
| 190 | if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - | 184 | if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) { |
| 191 | srvr->vals->header_preamble_size) { | ||
| 192 | cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n", | 185 | cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n", |
| 193 | mid); | 186 | mid); |
| 194 | return 1; | 187 | return 1; |
| @@ -227,44 +220,38 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) | |||
| 227 | } | 220 | } |
| 228 | } | 221 | } |
| 229 | 222 | ||
| 230 | if (srvr->vals->header_preamble_size + len != length) { | 223 | clc_len = smb2_calc_size(buf, srvr); |
| 231 | cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n", | ||
| 232 | length, srvr->vals->header_preamble_size + len, mid); | ||
| 233 | return 1; | ||
| 234 | } | ||
| 235 | |||
| 236 | clc_len = smb2_calc_size(hdr); | ||
| 237 | 224 | ||
| 238 | #ifdef CONFIG_CIFS_SMB311 | 225 | #ifdef CONFIG_CIFS_SMB311 |
| 239 | if (shdr->Command == SMB2_NEGOTIATE) | 226 | if (shdr->Command == SMB2_NEGOTIATE) |
| 240 | clc_len += get_neg_ctxt_len(hdr, len, clc_len, | 227 | clc_len += get_neg_ctxt_len(shdr, len, clc_len); |
| 241 | srvr->vals->header_preamble_size); | ||
| 242 | #endif /* SMB311 */ | 228 | #endif /* SMB311 */ |
| 243 | if (srvr->vals->header_preamble_size + len != clc_len) { | 229 | if (len != clc_len) { |
| 244 | cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n", | 230 | cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", |
| 245 | clc_len, srvr->vals->header_preamble_size + len, mid); | 231 | clc_len, len, mid); |
| 246 | /* create failed on symlink */ | 232 | /* create failed on symlink */ |
| 247 | if (command == SMB2_CREATE_HE && | 233 | if (command == SMB2_CREATE_HE && |
| 248 | shdr->Status == STATUS_STOPPED_ON_SYMLINK) | 234 | shdr->Status == STATUS_STOPPED_ON_SYMLINK) |
| 249 | return 0; | 235 | return 0; |
| 250 | /* Windows 7 server returns 24 bytes more */ | 236 | /* Windows 7 server returns 24 bytes more */ |
| 251 | if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE) | 237 | if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) |
| 252 | return 0; | 238 | return 0; |
| 253 | /* server can return one byte more due to implied bcc[0] */ | 239 | /* server can return one byte more due to implied bcc[0] */ |
| 254 | if (clc_len == srvr->vals->header_preamble_size + len + 1) | 240 | if (clc_len == len + 1) |
| 255 | return 0; | 241 | return 0; |
| 256 | 242 | ||
| 257 | /* | 243 | /* |
| 258 | * MacOS server pads after SMB2.1 write response with 3 bytes | 244 | * MacOS server pads after SMB2.1 write response with 3 bytes |
| 259 | * of junk. Other servers match RFC1001 len to actual | 245 | * of junk. Other servers match RFC1001 len to actual |
| 260 | * SMB2/SMB3 frame length (header + smb2 response specific data) | 246 | * SMB2/SMB3 frame length (header + smb2 response specific data) |
| 247 | * Some windows servers do too when compounding is used. | ||
| 261 | * Log the server error (once), but allow it and continue | 248 | * Log the server error (once), but allow it and continue |
| 262 | * since the frame is parseable. | 249 | * since the frame is parseable. |
| 263 | */ | 250 | */ |
| 264 | if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) { | 251 | if (clc_len < len) { |
| 265 | printk_once(KERN_WARNING | 252 | printk_once(KERN_WARNING |
| 266 | "SMB2 server sent bad RFC1001 len %d not %zu\n", | 253 | "SMB2 server sent bad RFC1001 len %d not %d\n", |
| 267 | len, clc_len - srvr->vals->header_preamble_size); | 254 | len, clc_len); |
| 268 | return 0; | 255 | return 0; |
| 269 | } | 256 | } |
| 270 | 257 | ||
| @@ -305,15 +292,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { | |||
| 305 | * area and the offset to it (from the beginning of the smb are also returned. | 292 | * area and the offset to it (from the beginning of the smb are also returned. |
| 306 | */ | 293 | */ |
| 307 | char * | 294 | char * |
| 308 | smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | 295 | smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) |
| 309 | { | 296 | { |
| 310 | struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); | ||
| 311 | *off = 0; | 297 | *off = 0; |
| 312 | *len = 0; | 298 | *len = 0; |
| 313 | 299 | ||
| 314 | /* error responses do not have data area */ | 300 | /* error responses do not have data area */ |
| 315 | if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && | 301 | if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && |
| 316 | (((struct smb2_err_rsp *)hdr)->StructureSize) == | 302 | (((struct smb2_err_rsp *)shdr)->StructureSize) == |
| 317 | SMB2_ERROR_STRUCTURE_SIZE2) | 303 | SMB2_ERROR_STRUCTURE_SIZE2) |
| 318 | return NULL; | 304 | return NULL; |
| 319 | 305 | ||
| @@ -325,42 +311,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
| 325 | switch (shdr->Command) { | 311 | switch (shdr->Command) { |
| 326 | case SMB2_NEGOTIATE: | 312 | case SMB2_NEGOTIATE: |
| 327 | *off = le16_to_cpu( | 313 | *off = le16_to_cpu( |
| 328 | ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); | 314 | ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset); |
| 329 | *len = le16_to_cpu( | 315 | *len = le16_to_cpu( |
| 330 | ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength); | 316 | ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength); |
| 331 | break; | 317 | break; |
| 332 | case SMB2_SESSION_SETUP: | 318 | case SMB2_SESSION_SETUP: |
| 333 | *off = le16_to_cpu( | 319 | *off = le16_to_cpu( |
| 334 | ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset); | 320 | ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); |
| 335 | *len = le16_to_cpu( | 321 | *len = le16_to_cpu( |
| 336 | ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength); | 322 | ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); |
| 337 | break; | 323 | break; |
| 338 | case SMB2_CREATE: | 324 | case SMB2_CREATE: |
| 339 | *off = le32_to_cpu( | 325 | *off = le32_to_cpu( |
| 340 | ((struct smb2_create_rsp *)hdr)->CreateContextsOffset); | 326 | ((struct smb2_create_rsp *)shdr)->CreateContextsOffset); |
| 341 | *len = le32_to_cpu( | 327 | *len = le32_to_cpu( |
| 342 | ((struct smb2_create_rsp *)hdr)->CreateContextsLength); | 328 | ((struct smb2_create_rsp *)shdr)->CreateContextsLength); |
| 343 | break; | 329 | break; |
| 344 | case SMB2_QUERY_INFO: | 330 | case SMB2_QUERY_INFO: |
| 345 | *off = le16_to_cpu( | 331 | *off = le16_to_cpu( |
| 346 | ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset); | 332 | ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset); |
| 347 | *len = le32_to_cpu( | 333 | *len = le32_to_cpu( |
| 348 | ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength); | 334 | ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength); |
| 349 | break; | 335 | break; |
| 350 | case SMB2_READ: | 336 | case SMB2_READ: |
| 351 | *off = ((struct smb2_read_rsp *)hdr)->DataOffset; | 337 | /* TODO: is this a bug ? */ |
| 352 | *len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength); | 338 | *off = ((struct smb2_read_rsp *)shdr)->DataOffset; |
| 339 | *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength); | ||
| 353 | break; | 340 | break; |
| 354 | case SMB2_QUERY_DIRECTORY: | 341 | case SMB2_QUERY_DIRECTORY: |
| 355 | *off = le16_to_cpu( | 342 | *off = le16_to_cpu( |
| 356 | ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset); | 343 | ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset); |
| 357 | *len = le32_to_cpu( | 344 | *len = le32_to_cpu( |
| 358 | ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength); | 345 | ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength); |
| 359 | break; | 346 | break; |
| 360 | case SMB2_IOCTL: | 347 | case SMB2_IOCTL: |
| 361 | *off = le32_to_cpu( | 348 | *off = le32_to_cpu( |
| 362 | ((struct smb2_ioctl_rsp *)hdr)->OutputOffset); | 349 | ((struct smb2_ioctl_rsp *)shdr)->OutputOffset); |
| 363 | *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount); | 350 | *len = le32_to_cpu( |
| 351 | ((struct smb2_ioctl_rsp *)shdr)->OutputCount); | ||
| 364 | break; | 352 | break; |
| 365 | case SMB2_CHANGE_NOTIFY: | 353 | case SMB2_CHANGE_NOTIFY: |
| 366 | default: | 354 | default: |
| @@ -403,15 +391,14 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
| 403 | * portion, the number of word parameters and the data portion of the message. | 391 | * portion, the number of word parameters and the data portion of the message. |
| 404 | */ | 392 | */ |
| 405 | unsigned int | 393 | unsigned int |
| 406 | smb2_calc_size(void *buf) | 394 | smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) |
| 407 | { | 395 | { |
| 408 | struct smb2_pdu *pdu = (struct smb2_pdu *)buf; | 396 | struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf; |
| 409 | struct smb2_hdr *hdr = &pdu->hdr; | 397 | struct smb2_sync_hdr *shdr = &pdu->sync_hdr; |
| 410 | struct smb2_sync_hdr *shdr = get_sync_hdr(hdr); | ||
| 411 | int offset; /* the offset from the beginning of SMB to data area */ | 398 | int offset; /* the offset from the beginning of SMB to data area */ |
| 412 | int data_length; /* the length of the variable length data area */ | 399 | int data_length; /* the length of the variable length data area */ |
| 413 | /* Structure Size has already been checked to make sure it is 64 */ | 400 | /* Structure Size has already been checked to make sure it is 64 */ |
| 414 | int len = 4 + le16_to_cpu(shdr->StructureSize); | 401 | int len = le16_to_cpu(shdr->StructureSize); |
| 415 | 402 | ||
| 416 | /* | 403 | /* |
| 417 | * StructureSize2, ie length of fixed parameter area has already | 404 | * StructureSize2, ie length of fixed parameter area has already |
| @@ -422,7 +409,7 @@ smb2_calc_size(void *buf) | |||
| 422 | if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) | 409 | if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) |
| 423 | goto calc_size_exit; | 410 | goto calc_size_exit; |
| 424 | 411 | ||
| 425 | smb2_get_data_area_len(&offset, &data_length, hdr); | 412 | smb2_get_data_area_len(&offset, &data_length, shdr); |
| 426 | cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset); | 413 | cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset); |
| 427 | 414 | ||
| 428 | if (data_length > 0) { | 415 | if (data_length > 0) { |
| @@ -430,15 +417,14 @@ smb2_calc_size(void *buf) | |||
| 430 | * Check to make sure that data area begins after fixed area, | 417 | * Check to make sure that data area begins after fixed area, |
| 431 | * Note that last byte of the fixed area is part of data area | 418 | * Note that last byte of the fixed area is part of data area |
| 432 | * for some commands, typically those with odd StructureSize, | 419 | * for some commands, typically those with odd StructureSize, |
| 433 | * so we must add one to the calculation (and 4 to account for | 420 | * so we must add one to the calculation. |
| 434 | * the size of the RFC1001 hdr. | ||
| 435 | */ | 421 | */ |
| 436 | if (offset + 4 + 1 < len) { | 422 | if (offset + 1 < len) { |
| 437 | cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n", | 423 | cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n", |
| 438 | offset + 4 + 1, len); | 424 | offset + 1, len); |
| 439 | data_length = 0; | 425 | data_length = 0; |
| 440 | } else { | 426 | } else { |
| 441 | len = 4 + offset + data_length; | 427 | len = offset + data_length; |
| 442 | } | 428 | } |
| 443 | } | 429 | } |
| 444 | calc_size_exit: | 430 | calc_size_exit: |
| @@ -465,8 +451,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) | |||
| 465 | /* Windows doesn't allow paths beginning with \ */ | 451 | /* Windows doesn't allow paths beginning with \ */ |
| 466 | if (from[0] == '\\') | 452 | if (from[0] == '\\') |
| 467 | start_of_path = from + 1; | 453 | start_of_path = from + 1; |
| 454 | #ifdef CONFIG_CIFS_SMB311 | ||
| 455 | /* SMB311 POSIX extensions paths do not include leading slash */ | ||
| 456 | else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions) | ||
| 457 | start_of_path = from + 1; | ||
| 458 | #endif /* 311 */ | ||
| 468 | else | 459 | else |
| 469 | start_of_path = from; | 460 | start_of_path = from; |
| 461 | |||
| 470 | to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, | 462 | to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, |
| 471 | cifs_sb->local_nls, map_type); | 463 | cifs_sb->local_nls, map_type); |
| 472 | return to; | 464 | return to; |
| @@ -621,7 +613,7 @@ smb2_is_valid_lease_break(char *buffer) | |||
| 621 | bool | 613 | bool |
| 622 | smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) | 614 | smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) |
| 623 | { | 615 | { |
| 624 | struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer; | 616 | struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer; |
| 625 | struct list_head *tmp, *tmp1, *tmp2; | 617 | struct list_head *tmp, *tmp1, *tmp2; |
| 626 | struct cifs_ses *ses; | 618 | struct cifs_ses *ses; |
| 627 | struct cifs_tcon *tcon; | 619 | struct cifs_tcon *tcon; |
| @@ -630,7 +622,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) | |||
| 630 | 622 | ||
| 631 | cifs_dbg(FYI, "Checking for oplock break\n"); | 623 | cifs_dbg(FYI, "Checking for oplock break\n"); |
| 632 | 624 | ||
| 633 | if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK) | 625 | if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK) |
| 634 | return false; | 626 | return false; |
| 635 | 627 | ||
| 636 | if (rsp->StructureSize != | 628 | if (rsp->StructureSize != |
| @@ -721,7 +713,7 @@ smb2_cancelled_close_fid(struct work_struct *work) | |||
| 721 | int | 713 | int |
| 722 | smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) | 714 | smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) |
| 723 | { | 715 | { |
| 724 | struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer); | 716 | struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; |
| 725 | struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; | 717 | struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; |
| 726 | struct cifs_tcon *tcon; | 718 | struct cifs_tcon *tcon; |
| 727 | struct close_cancelled_open *cancelled; | 719 | struct close_cancelled_open *cancelled; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 9c6d95ffca97..950d0ab2cc61 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -123,7 +123,7 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) | |||
| 123 | static unsigned int | 123 | static unsigned int |
| 124 | smb2_get_credits(struct mid_q_entry *mid) | 124 | smb2_get_credits(struct mid_q_entry *mid) |
| 125 | { | 125 | { |
| 126 | struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf); | 126 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf; |
| 127 | 127 | ||
| 128 | return le16_to_cpu(shdr->CreditRequest); | 128 | return le16_to_cpu(shdr->CreditRequest); |
| 129 | } | 129 | } |
| @@ -190,7 +190,7 @@ static struct mid_q_entry * | |||
| 190 | smb2_find_mid(struct TCP_Server_Info *server, char *buf) | 190 | smb2_find_mid(struct TCP_Server_Info *server, char *buf) |
| 191 | { | 191 | { |
| 192 | struct mid_q_entry *mid; | 192 | struct mid_q_entry *mid; |
| 193 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 193 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 194 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); | 194 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
| 195 | 195 | ||
| 196 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 196 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
| @@ -212,15 +212,16 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | static void | 214 | static void |
| 215 | smb2_dump_detail(void *buf) | 215 | smb2_dump_detail(void *buf, struct TCP_Server_Info *server) |
| 216 | { | 216 | { |
| 217 | #ifdef CONFIG_CIFS_DEBUG2 | 217 | #ifdef CONFIG_CIFS_DEBUG2 |
| 218 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 218 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 219 | 219 | ||
| 220 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", | 220 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", |
| 221 | shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, | 221 | shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, |
| 222 | shdr->ProcessId); | 222 | shdr->ProcessId); |
| 223 | cifs_dbg(VFS, "smb buf %p len %u\n", buf, smb2_calc_size(buf)); | 223 | cifs_dbg(VFS, "smb buf %p len %u\n", buf, |
| 224 | server->ops->calc_smb_size(buf, server)); | ||
| 224 | #endif | 225 | #endif |
| 225 | } | 226 | } |
| 226 | 227 | ||
| @@ -322,6 +323,40 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 322 | } | 323 | } |
| 323 | #endif /* STATS2 */ | 324 | #endif /* STATS2 */ |
| 324 | 325 | ||
| 326 | /* | ||
| 327 | * Open the directory at the root of a share | ||
| 328 | */ | ||
| 329 | int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | ||
| 330 | { | ||
| 331 | struct cifs_open_parms oparams; | ||
| 332 | int rc; | ||
| 333 | __le16 srch_path = 0; /* Null - since an open of top of share */ | ||
| 334 | u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
| 335 | |||
| 336 | mutex_lock(&tcon->prfid_mutex); | ||
| 337 | if (tcon->valid_root_fid) { | ||
| 338 | cifs_dbg(FYI, "found a cached root file handle\n"); | ||
| 339 | memcpy(pfid, tcon->prfid, sizeof(struct cifs_fid)); | ||
| 340 | mutex_unlock(&tcon->prfid_mutex); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | oparams.tcon = tcon; | ||
| 345 | oparams.create_options = 0; | ||
| 346 | oparams.desired_access = FILE_READ_ATTRIBUTES; | ||
| 347 | oparams.disposition = FILE_OPEN; | ||
| 348 | oparams.fid = pfid; | ||
| 349 | oparams.reconnect = false; | ||
| 350 | |||
| 351 | rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL); | ||
| 352 | if (rc == 0) { | ||
| 353 | memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid)); | ||
| 354 | tcon->valid_root_fid = true; | ||
| 355 | } | ||
| 356 | mutex_unlock(&tcon->prfid_mutex); | ||
| 357 | return rc; | ||
| 358 | } | ||
| 359 | |||
| 325 | static void | 360 | static void |
| 326 | smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | 361 | smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) |
| 327 | { | 362 | { |
| @@ -330,6 +365,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 330 | u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | 365 | u8 oplock = SMB2_OPLOCK_LEVEL_NONE; |
| 331 | struct cifs_open_parms oparms; | 366 | struct cifs_open_parms oparms; |
| 332 | struct cifs_fid fid; | 367 | struct cifs_fid fid; |
| 368 | bool no_cached_open = tcon->nohandlecache; | ||
| 333 | 369 | ||
| 334 | oparms.tcon = tcon; | 370 | oparms.tcon = tcon; |
| 335 | oparms.desired_access = FILE_READ_ATTRIBUTES; | 371 | oparms.desired_access = FILE_READ_ATTRIBUTES; |
| @@ -338,7 +374,11 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 338 | oparms.fid = &fid; | 374 | oparms.fid = &fid; |
| 339 | oparms.reconnect = false; | 375 | oparms.reconnect = false; |
| 340 | 376 | ||
| 341 | rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); | 377 | if (no_cached_open) |
| 378 | rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); | ||
| 379 | else | ||
| 380 | rc = open_shroot(xid, tcon, &fid); | ||
| 381 | |||
| 342 | if (rc) | 382 | if (rc) |
| 343 | return; | 383 | return; |
| 344 | 384 | ||
| @@ -352,7 +392,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 352 | FS_DEVICE_INFORMATION); | 392 | FS_DEVICE_INFORMATION); |
| 353 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, | 393 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| 354 | FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */ | 394 | FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */ |
| 355 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 395 | if (no_cached_open) |
| 396 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
| 356 | return; | 397 | return; |
| 357 | } | 398 | } |
| 358 | 399 | ||
| @@ -394,6 +435,9 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 394 | struct cifs_open_parms oparms; | 435 | struct cifs_open_parms oparms; |
| 395 | struct cifs_fid fid; | 436 | struct cifs_fid fid; |
| 396 | 437 | ||
| 438 | if ((*full_path == 0) && tcon->valid_root_fid) | ||
| 439 | return 0; | ||
| 440 | |||
| 397 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); | 441 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); |
| 398 | if (!utf16_path) | 442 | if (!utf16_path) |
| 399 | return -ENOMEM; | 443 | return -ENOMEM; |
| @@ -704,9 +748,11 @@ smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon) | |||
| 704 | seq_puts(m, " TRIM-support,"); | 748 | seq_puts(m, " TRIM-support,"); |
| 705 | 749 | ||
| 706 | seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags); | 750 | seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags); |
| 751 | seq_printf(m, "\n\ttid: 0x%x", tcon->tid); | ||
| 707 | if (tcon->perf_sector_size) | 752 | if (tcon->perf_sector_size) |
| 708 | seq_printf(m, "\tOptimal sector size: 0x%x", | 753 | seq_printf(m, "\tOptimal sector size: 0x%x", |
| 709 | tcon->perf_sector_size); | 754 | tcon->perf_sector_size); |
| 755 | seq_printf(m, "\tMaximal Access: 0x%x", tcon->maximal_access); | ||
| 710 | } | 756 | } |
| 711 | 757 | ||
| 712 | static void | 758 | static void |
| @@ -1257,7 +1303,7 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1257 | static bool | 1303 | static bool |
| 1258 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) | 1304 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) |
| 1259 | { | 1305 | { |
| 1260 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 1306 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 1261 | 1307 | ||
| 1262 | if (shdr->Status != STATUS_PENDING) | 1308 | if (shdr->Status != STATUS_PENDING) |
| 1263 | return false; | 1309 | return false; |
| @@ -1275,12 +1321,13 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) | |||
| 1275 | static bool | 1321 | static bool |
| 1276 | smb2_is_session_expired(char *buf) | 1322 | smb2_is_session_expired(char *buf) |
| 1277 | { | 1323 | { |
| 1278 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 1324 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 1279 | 1325 | ||
| 1280 | if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED) | 1326 | if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED && |
| 1327 | shdr->Status != STATUS_USER_SESSION_DELETED) | ||
| 1281 | return false; | 1328 | return false; |
| 1282 | 1329 | ||
| 1283 | cifs_dbg(FYI, "Session expired\n"); | 1330 | cifs_dbg(FYI, "Session expired or deleted\n"); |
| 1284 | return true; | 1331 | return true; |
| 1285 | } | 1332 | } |
| 1286 | 1333 | ||
| @@ -1474,8 +1521,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1474 | unsigned int sub_offset; | 1521 | unsigned int sub_offset; |
| 1475 | unsigned int print_len; | 1522 | unsigned int print_len; |
| 1476 | unsigned int print_offset; | 1523 | unsigned int print_offset; |
| 1477 | struct cifs_ses *ses = tcon->ses; | ||
| 1478 | struct TCP_Server_Info *server = ses->server; | ||
| 1479 | 1524 | ||
| 1480 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); | 1525 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); |
| 1481 | 1526 | ||
| @@ -1499,7 +1544,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1499 | 1544 | ||
| 1500 | err_buf = err_iov.iov_base; | 1545 | err_buf = err_iov.iov_base; |
| 1501 | if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || | 1546 | if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || |
| 1502 | err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) { | 1547 | err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) { |
| 1503 | kfree(utf16_path); | 1548 | kfree(utf16_path); |
| 1504 | return -ENOENT; | 1549 | return -ENOENT; |
| 1505 | } | 1550 | } |
| @@ -1512,14 +1557,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1512 | print_len = le16_to_cpu(symlink->PrintNameLength); | 1557 | print_len = le16_to_cpu(symlink->PrintNameLength); |
| 1513 | print_offset = le16_to_cpu(symlink->PrintNameOffset); | 1558 | print_offset = le16_to_cpu(symlink->PrintNameOffset); |
| 1514 | 1559 | ||
| 1515 | if (err_iov.iov_len + server->vals->header_preamble_size < | 1560 | if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { |
| 1516 | SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { | ||
| 1517 | kfree(utf16_path); | 1561 | kfree(utf16_path); |
| 1518 | return -ENOENT; | 1562 | return -ENOENT; |
| 1519 | } | 1563 | } |
| 1520 | 1564 | ||
| 1521 | if (err_iov.iov_len + server->vals->header_preamble_size < | 1565 | if (err_iov.iov_len < |
| 1522 | SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { | 1566 | SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { |
| 1523 | kfree(utf16_path); | 1567 | kfree(utf16_path); |
| 1524 | return -ENOENT; | 1568 | return -ENOENT; |
| 1525 | } | 1569 | } |
| @@ -1593,8 +1637,11 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 1593 | oparms.create_options = 0; | 1637 | oparms.create_options = 0; |
| 1594 | 1638 | ||
| 1595 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | 1639 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); |
| 1596 | if (!utf16_path) | 1640 | if (!utf16_path) { |
| 1597 | return ERR_PTR(-ENOMEM); | 1641 | rc = -ENOMEM; |
| 1642 | free_xid(xid); | ||
| 1643 | return ERR_PTR(rc); | ||
| 1644 | } | ||
| 1598 | 1645 | ||
| 1599 | oparms.tcon = tcon; | 1646 | oparms.tcon = tcon; |
| 1600 | oparms.desired_access = READ_CONTROL; | 1647 | oparms.desired_access = READ_CONTROL; |
| @@ -1652,8 +1699,11 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 1652 | access_flags = WRITE_DAC; | 1699 | access_flags = WRITE_DAC; |
| 1653 | 1700 | ||
| 1654 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | 1701 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); |
| 1655 | if (!utf16_path) | 1702 | if (!utf16_path) { |
| 1656 | return -ENOMEM; | 1703 | rc = -ENOMEM; |
| 1704 | free_xid(xid); | ||
| 1705 | return rc; | ||
| 1706 | } | ||
| 1657 | 1707 | ||
| 1658 | oparms.tcon = tcon; | 1708 | oparms.tcon = tcon; |
| 1659 | oparms.desired_access = access_flags; | 1709 | oparms.desired_access = access_flags; |
| @@ -1713,15 +1763,21 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 1713 | 1763 | ||
| 1714 | /* if file not oplocked can't be sure whether asking to extend size */ | 1764 | /* if file not oplocked can't be sure whether asking to extend size */ |
| 1715 | if (!CIFS_CACHE_READ(cifsi)) | 1765 | if (!CIFS_CACHE_READ(cifsi)) |
| 1716 | if (keep_size == false) | 1766 | if (keep_size == false) { |
| 1717 | return -EOPNOTSUPP; | 1767 | rc = -EOPNOTSUPP; |
| 1768 | free_xid(xid); | ||
| 1769 | return rc; | ||
| 1770 | } | ||
| 1718 | 1771 | ||
| 1719 | /* | 1772 | /* |
| 1720 | * Must check if file sparse since fallocate -z (zero range) assumes | 1773 | * Must check if file sparse since fallocate -z (zero range) assumes |
| 1721 | * non-sparse allocation | 1774 | * non-sparse allocation |
| 1722 | */ | 1775 | */ |
| 1723 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) | 1776 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) { |
| 1724 | return -EOPNOTSUPP; | 1777 | rc = -EOPNOTSUPP; |
| 1778 | free_xid(xid); | ||
| 1779 | return rc; | ||
| 1780 | } | ||
| 1725 | 1781 | ||
| 1726 | /* | 1782 | /* |
| 1727 | * need to make sure we are not asked to extend the file since the SMB3 | 1783 | * need to make sure we are not asked to extend the file since the SMB3 |
| @@ -1730,8 +1786,11 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 1730 | * which for a non sparse file would zero the newly extended range | 1786 | * which for a non sparse file would zero the newly extended range |
| 1731 | */ | 1787 | */ |
| 1732 | if (keep_size == false) | 1788 | if (keep_size == false) |
| 1733 | if (i_size_read(inode) < offset + len) | 1789 | if (i_size_read(inode) < offset + len) { |
| 1734 | return -EOPNOTSUPP; | 1790 | rc = -EOPNOTSUPP; |
| 1791 | free_xid(xid); | ||
| 1792 | return rc; | ||
| 1793 | } | ||
| 1735 | 1794 | ||
| 1736 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 1795 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); |
| 1737 | 1796 | ||
| @@ -1764,8 +1823,11 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | |||
| 1764 | 1823 | ||
| 1765 | /* Need to make file sparse, if not already, before freeing range. */ | 1824 | /* Need to make file sparse, if not already, before freeing range. */ |
| 1766 | /* Consider adding equivalent for compressed since it could also work */ | 1825 | /* Consider adding equivalent for compressed since it could also work */ |
| 1767 | if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) | 1826 | if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) { |
| 1768 | return -EOPNOTSUPP; | 1827 | rc = -EOPNOTSUPP; |
| 1828 | free_xid(xid); | ||
| 1829 | return rc; | ||
| 1830 | } | ||
| 1769 | 1831 | ||
| 1770 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 1832 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); |
| 1771 | 1833 | ||
| @@ -1796,8 +1858,10 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, | |||
| 1796 | 1858 | ||
| 1797 | /* if file not oplocked can't be sure whether asking to extend size */ | 1859 | /* if file not oplocked can't be sure whether asking to extend size */ |
| 1798 | if (!CIFS_CACHE_READ(cifsi)) | 1860 | if (!CIFS_CACHE_READ(cifsi)) |
| 1799 | if (keep_size == false) | 1861 | if (keep_size == false) { |
| 1800 | return -EOPNOTSUPP; | 1862 | free_xid(xid); |
| 1863 | return rc; | ||
| 1864 | } | ||
| 1801 | 1865 | ||
| 1802 | /* | 1866 | /* |
| 1803 | * Files are non-sparse by default so falloc may be a no-op | 1867 | * Files are non-sparse by default so falloc may be a no-op |
| @@ -1806,14 +1870,16 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, | |||
| 1806 | */ | 1870 | */ |
| 1807 | if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { | 1871 | if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { |
| 1808 | if (keep_size == true) | 1872 | if (keep_size == true) |
| 1809 | return 0; | 1873 | rc = 0; |
| 1810 | /* check if extending file */ | 1874 | /* check if extending file */ |
| 1811 | else if (i_size_read(inode) >= off + len) | 1875 | else if (i_size_read(inode) >= off + len) |
| 1812 | /* not extending file and already not sparse */ | 1876 | /* not extending file and already not sparse */ |
| 1813 | return 0; | 1877 | rc = 0; |
| 1814 | /* BB: in future add else clause to extend file */ | 1878 | /* BB: in future add else clause to extend file */ |
| 1815 | else | 1879 | else |
| 1816 | return -EOPNOTSUPP; | 1880 | rc = -EOPNOTSUPP; |
| 1881 | free_xid(xid); | ||
| 1882 | return rc; | ||
| 1817 | } | 1883 | } |
| 1818 | 1884 | ||
| 1819 | if ((keep_size == true) || (i_size_read(inode) >= off + len)) { | 1885 | if ((keep_size == true) || (i_size_read(inode) >= off + len)) { |
| @@ -1825,8 +1891,11 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, | |||
| 1825 | * ie potentially making a few extra pages at the beginning | 1891 | * ie potentially making a few extra pages at the beginning |
| 1826 | * or end of the file non-sparse via set_sparse is harmless. | 1892 | * or end of the file non-sparse via set_sparse is harmless. |
| 1827 | */ | 1893 | */ |
| 1828 | if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) | 1894 | if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) { |
| 1829 | return -EOPNOTSUPP; | 1895 | rc = -EOPNOTSUPP; |
| 1896 | free_xid(xid); | ||
| 1897 | return rc; | ||
| 1898 | } | ||
| 1830 | 1899 | ||
| 1831 | rc = smb2_set_sparse(xid, tcon, cfile, inode, false); | 1900 | rc = smb2_set_sparse(xid, tcon, cfile, inode, false); |
| 1832 | } | 1901 | } |
| @@ -2035,7 +2104,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock) | |||
| 2035 | } | 2104 | } |
| 2036 | 2105 | ||
| 2037 | static __u8 | 2106 | static __u8 |
| 2038 | smb2_parse_lease_buf(void *buf, unsigned int *epoch) | 2107 | smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) |
| 2039 | { | 2108 | { |
| 2040 | struct create_lease *lc = (struct create_lease *)buf; | 2109 | struct create_lease *lc = (struct create_lease *)buf; |
| 2041 | 2110 | ||
| @@ -2046,13 +2115,16 @@ smb2_parse_lease_buf(void *buf, unsigned int *epoch) | |||
| 2046 | } | 2115 | } |
| 2047 | 2116 | ||
| 2048 | static __u8 | 2117 | static __u8 |
| 2049 | smb3_parse_lease_buf(void *buf, unsigned int *epoch) | 2118 | smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) |
| 2050 | { | 2119 | { |
| 2051 | struct create_lease_v2 *lc = (struct create_lease_v2 *)buf; | 2120 | struct create_lease_v2 *lc = (struct create_lease_v2 *)buf; |
| 2052 | 2121 | ||
| 2053 | *epoch = le16_to_cpu(lc->lcontext.Epoch); | 2122 | *epoch = le16_to_cpu(lc->lcontext.Epoch); |
| 2054 | if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) | 2123 | if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) |
| 2055 | return SMB2_OPLOCK_LEVEL_NOCHANGE; | 2124 | return SMB2_OPLOCK_LEVEL_NOCHANGE; |
| 2125 | if (lease_key) | ||
| 2126 | memcpy(lease_key, &lc->lcontext.LeaseKeyLow, | ||
| 2127 | SMB2_LEASE_KEY_SIZE); | ||
| 2056 | return le32_to_cpu(lc->lcontext.LeaseState); | 2128 | return le32_to_cpu(lc->lcontext.LeaseState); |
| 2057 | } | 2129 | } |
| 2058 | 2130 | ||
| @@ -2070,12 +2142,11 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile) | |||
| 2070 | } | 2142 | } |
| 2071 | 2143 | ||
| 2072 | static void | 2144 | static void |
| 2073 | fill_transform_hdr(struct TCP_Server_Info *server, | 2145 | fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len, |
| 2074 | struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq) | 2146 | struct smb_rqst *old_rq) |
| 2075 | { | 2147 | { |
| 2076 | struct smb2_sync_hdr *shdr = | 2148 | struct smb2_sync_hdr *shdr = |
| 2077 | (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base; | 2149 | (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base; |
| 2078 | unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); | ||
| 2079 | 2150 | ||
| 2080 | memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); | 2151 | memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); |
| 2081 | tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; | 2152 | tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; |
| @@ -2083,8 +2154,6 @@ fill_transform_hdr(struct TCP_Server_Info *server, | |||
| 2083 | tr_hdr->Flags = cpu_to_le16(0x01); | 2154 | tr_hdr->Flags = cpu_to_le16(0x01); |
| 2084 | get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE); | 2155 | get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE); |
| 2085 | memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); | 2156 | memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); |
| 2086 | inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size); | ||
| 2087 | inc_rfc1001_len(tr_hdr, orig_len); | ||
| 2088 | } | 2157 | } |
| 2089 | 2158 | ||
| 2090 | /* We can not use the normal sg_set_buf() as we will sometimes pass a | 2159 | /* We can not use the normal sg_set_buf() as we will sometimes pass a |
| @@ -2096,11 +2165,16 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf, | |||
| 2096 | sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); | 2165 | sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); |
| 2097 | } | 2166 | } |
| 2098 | 2167 | ||
| 2168 | /* Assumes: | ||
| 2169 | * rqst->rq_iov[0] is rfc1002 length | ||
| 2170 | * rqst->rq_iov[1] is tranform header | ||
| 2171 | * rqst->rq_iov[2+] data to be encrypted/decrypted | ||
| 2172 | */ | ||
| 2099 | static struct scatterlist * | 2173 | static struct scatterlist * |
| 2100 | init_sg(struct smb_rqst *rqst, u8 *sign) | 2174 | init_sg(struct smb_rqst *rqst, u8 *sign) |
| 2101 | { | 2175 | { |
| 2102 | unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1; | 2176 | unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages; |
| 2103 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24; | 2177 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; |
| 2104 | struct scatterlist *sg; | 2178 | struct scatterlist *sg; |
| 2105 | unsigned int i; | 2179 | unsigned int i; |
| 2106 | unsigned int j; | 2180 | unsigned int j; |
| @@ -2110,10 +2184,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign) | |||
| 2110 | return NULL; | 2184 | return NULL; |
| 2111 | 2185 | ||
| 2112 | sg_init_table(sg, sg_len); | 2186 | sg_init_table(sg, sg_len); |
| 2113 | smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len); | 2187 | smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len); |
| 2114 | for (i = 1; i < rqst->rq_nvec; i++) | 2188 | for (i = 1; i < rqst->rq_nvec - 1; i++) |
| 2115 | smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base, | 2189 | smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base, |
| 2116 | rqst->rq_iov[i].iov_len); | 2190 | rqst->rq_iov[i+1].iov_len); |
| 2117 | for (j = 0; i < sg_len - 1; i++, j++) { | 2191 | for (j = 0; i < sg_len - 1; i++, j++) { |
| 2118 | unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz | 2192 | unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz |
| 2119 | : rqst->rq_tailsz; | 2193 | : rqst->rq_tailsz; |
| @@ -2145,9 +2219,10 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) | |||
| 2145 | } | 2219 | } |
| 2146 | /* | 2220 | /* |
| 2147 | * Encrypt or decrypt @rqst message. @rqst has the following format: | 2221 | * Encrypt or decrypt @rqst message. @rqst has the following format: |
| 2148 | * iov[0] - transform header (associate data), | 2222 | * iov[0] - rfc1002 length |
| 2149 | * iov[1-N] and pages - data to encrypt. | 2223 | * iov[1] - transform header (associate data), |
| 2150 | * On success return encrypted data in iov[1-N] and pages, leave iov[0] | 2224 | * iov[2-N] and pages - data to encrypt. |
| 2225 | * On success return encrypted data in iov[2-N] and pages, leave iov[0-1] | ||
| 2151 | * untouched. | 2226 | * untouched. |
| 2152 | */ | 2227 | */ |
| 2153 | static int | 2228 | static int |
| @@ -2155,7 +2230,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) | |||
| 2155 | { | 2230 | { |
| 2156 | struct smb2_transform_hdr *tr_hdr = | 2231 | struct smb2_transform_hdr *tr_hdr = |
| 2157 | (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base; | 2232 | (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base; |
| 2158 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20 - server->vals->header_preamble_size; | 2233 | unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; |
| 2159 | int rc = 0; | 2234 | int rc = 0; |
| 2160 | struct scatterlist *sg; | 2235 | struct scatterlist *sg; |
| 2161 | u8 sign[SMB2_SIGNATURE_SIZE] = {}; | 2236 | u8 sign[SMB2_SIGNATURE_SIZE] = {}; |
| @@ -2242,6 +2317,10 @@ free_req: | |||
| 2242 | return rc; | 2317 | return rc; |
| 2243 | } | 2318 | } |
| 2244 | 2319 | ||
| 2320 | /* | ||
| 2321 | * This is called from smb_send_rqst. At this point we have the rfc1002 | ||
| 2322 | * header as the first element in the vector. | ||
| 2323 | */ | ||
| 2245 | static int | 2324 | static int |
| 2246 | smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, | 2325 | smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, |
| 2247 | struct smb_rqst *old_rq) | 2326 | struct smb_rqst *old_rq) |
| @@ -2250,6 +2329,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, | |||
| 2250 | struct page **pages; | 2329 | struct page **pages; |
| 2251 | struct smb2_transform_hdr *tr_hdr; | 2330 | struct smb2_transform_hdr *tr_hdr; |
| 2252 | unsigned int npages = old_rq->rq_npages; | 2331 | unsigned int npages = old_rq->rq_npages; |
| 2332 | unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base); | ||
| 2253 | int i; | 2333 | int i; |
| 2254 | int rc = -ENOMEM; | 2334 | int rc = -ENOMEM; |
| 2255 | 2335 | ||
| @@ -2268,24 +2348,34 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq, | |||
| 2268 | goto err_free_pages; | 2348 | goto err_free_pages; |
| 2269 | } | 2349 | } |
| 2270 | 2350 | ||
| 2271 | iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL); | 2351 | /* Make space for one extra iov to hold the transform header */ |
| 2352 | iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec), | ||
| 2353 | GFP_KERNEL); | ||
| 2272 | if (!iov) | 2354 | if (!iov) |
| 2273 | goto err_free_pages; | 2355 | goto err_free_pages; |
| 2274 | 2356 | ||
| 2275 | /* copy all iovs from the old except the 1st one (rfc1002 length) */ | 2357 | /* copy all iovs from the old except the 1st one (rfc1002 length) */ |
| 2276 | memcpy(&iov[1], &old_rq->rq_iov[1], | 2358 | memcpy(&iov[2], &old_rq->rq_iov[1], |
| 2277 | sizeof(struct kvec) * (old_rq->rq_nvec - 1)); | 2359 | sizeof(struct kvec) * (old_rq->rq_nvec - 1)); |
| 2360 | /* copy the rfc1002 iov */ | ||
| 2361 | iov[0].iov_base = old_rq->rq_iov[0].iov_base; | ||
| 2362 | iov[0].iov_len = old_rq->rq_iov[0].iov_len; | ||
| 2363 | |||
| 2278 | new_rq->rq_iov = iov; | 2364 | new_rq->rq_iov = iov; |
| 2279 | new_rq->rq_nvec = old_rq->rq_nvec; | 2365 | new_rq->rq_nvec = old_rq->rq_nvec + 1; |
| 2280 | 2366 | ||
| 2281 | tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL); | 2367 | tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL); |
| 2282 | if (!tr_hdr) | 2368 | if (!tr_hdr) |
| 2283 | goto err_free_iov; | 2369 | goto err_free_iov; |
| 2284 | 2370 | ||
| 2285 | /* fill the 1st iov with a transform header */ | 2371 | /* fill the 2nd iov with a transform header */ |
| 2286 | fill_transform_hdr(server, tr_hdr, old_rq); | 2372 | fill_transform_hdr(tr_hdr, orig_len, old_rq); |
| 2287 | new_rq->rq_iov[0].iov_base = tr_hdr; | 2373 | new_rq->rq_iov[1].iov_base = tr_hdr; |
| 2288 | new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr); | 2374 | new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr); |
| 2375 | |||
| 2376 | /* Update rfc1002 header */ | ||
| 2377 | inc_rfc1001_len(new_rq->rq_iov[0].iov_base, | ||
| 2378 | sizeof(struct smb2_transform_hdr)); | ||
| 2289 | 2379 | ||
| 2290 | /* copy pages form the old */ | 2380 | /* copy pages form the old */ |
| 2291 | for (i = 0; i < npages; i++) { | 2381 | for (i = 0; i < npages; i++) { |
| @@ -2325,7 +2415,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst) | |||
| 2325 | put_page(rqst->rq_pages[i]); | 2415 | put_page(rqst->rq_pages[i]); |
| 2326 | kfree(rqst->rq_pages); | 2416 | kfree(rqst->rq_pages); |
| 2327 | /* free transform header */ | 2417 | /* free transform header */ |
| 2328 | kfree(rqst->rq_iov[0].iov_base); | 2418 | kfree(rqst->rq_iov[1].iov_base); |
| 2329 | kfree(rqst->rq_iov); | 2419 | kfree(rqst->rq_iov); |
| 2330 | } | 2420 | } |
| 2331 | 2421 | ||
| @@ -2342,18 +2432,19 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, | |||
| 2342 | unsigned int buf_data_size, struct page **pages, | 2432 | unsigned int buf_data_size, struct page **pages, |
| 2343 | unsigned int npages, unsigned int page_data_size) | 2433 | unsigned int npages, unsigned int page_data_size) |
| 2344 | { | 2434 | { |
| 2345 | struct kvec iov[2]; | 2435 | struct kvec iov[3]; |
| 2346 | struct smb_rqst rqst = {NULL}; | 2436 | struct smb_rqst rqst = {NULL}; |
| 2347 | struct smb2_hdr *hdr; | ||
| 2348 | int rc; | 2437 | int rc; |
| 2349 | 2438 | ||
| 2350 | iov[0].iov_base = buf; | 2439 | iov[0].iov_base = NULL; |
| 2351 | iov[0].iov_len = sizeof(struct smb2_transform_hdr); | 2440 | iov[0].iov_len = 0; |
| 2352 | iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); | 2441 | iov[1].iov_base = buf; |
| 2353 | iov[1].iov_len = buf_data_size; | 2442 | iov[1].iov_len = sizeof(struct smb2_transform_hdr); |
| 2443 | iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr); | ||
| 2444 | iov[2].iov_len = buf_data_size; | ||
| 2354 | 2445 | ||
| 2355 | rqst.rq_iov = iov; | 2446 | rqst.rq_iov = iov; |
| 2356 | rqst.rq_nvec = 2; | 2447 | rqst.rq_nvec = 3; |
| 2357 | rqst.rq_pages = pages; | 2448 | rqst.rq_pages = pages; |
| 2358 | rqst.rq_npages = npages; | 2449 | rqst.rq_npages = npages; |
| 2359 | rqst.rq_pagesz = PAGE_SIZE; | 2450 | rqst.rq_pagesz = PAGE_SIZE; |
| @@ -2365,10 +2456,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, | |||
| 2365 | if (rc) | 2456 | if (rc) |
| 2366 | return rc; | 2457 | return rc; |
| 2367 | 2458 | ||
| 2368 | memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size); | 2459 | memmove(buf, iov[2].iov_base, buf_data_size); |
| 2369 | hdr = (struct smb2_hdr *)buf; | 2460 | |
| 2370 | hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size); | 2461 | server->total_read = buf_data_size + page_data_size; |
| 2371 | server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size; | ||
| 2372 | 2462 | ||
| 2373 | return rc; | 2463 | return rc; |
| 2374 | } | 2464 | } |
| @@ -2393,7 +2483,7 @@ read_data_into_pages(struct TCP_Server_Info *server, struct page **pages, | |||
| 2393 | zero_user(page, len, PAGE_SIZE - len); | 2483 | zero_user(page, len, PAGE_SIZE - len); |
| 2394 | len = 0; | 2484 | len = 0; |
| 2395 | } | 2485 | } |
| 2396 | length = cifs_read_page_from_socket(server, page, n); | 2486 | length = cifs_read_page_from_socket(server, page, 0, n); |
| 2397 | if (length < 0) | 2487 | if (length < 0) |
| 2398 | return length; | 2488 | return length; |
| 2399 | server->total_read += length; | 2489 | server->total_read += length; |
| @@ -2441,7 +2531,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |||
| 2441 | unsigned int cur_page_idx; | 2531 | unsigned int cur_page_idx; |
| 2442 | unsigned int pad_len; | 2532 | unsigned int pad_len; |
| 2443 | struct cifs_readdata *rdata = mid->callback_data; | 2533 | struct cifs_readdata *rdata = mid->callback_data; |
| 2444 | struct smb2_sync_hdr *shdr = get_sync_hdr(buf); | 2534 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| 2445 | struct bio_vec *bvec = NULL; | 2535 | struct bio_vec *bvec = NULL; |
| 2446 | struct iov_iter iter; | 2536 | struct iov_iter iter; |
| 2447 | struct kvec iov; | 2537 | struct kvec iov; |
| @@ -2472,7 +2562,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |||
| 2472 | return 0; | 2562 | return 0; |
| 2473 | } | 2563 | } |
| 2474 | 2564 | ||
| 2475 | data_offset = server->ops->read_data_offset(buf) + server->vals->header_preamble_size; | 2565 | data_offset = server->ops->read_data_offset(buf); |
| 2476 | #ifdef CONFIG_CIFS_SMB_DIRECT | 2566 | #ifdef CONFIG_CIFS_SMB_DIRECT |
| 2477 | use_rdma_mr = rdata->mr; | 2567 | use_rdma_mr = rdata->mr; |
| 2478 | #endif | 2568 | #endif |
| @@ -2568,12 +2658,11 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
| 2568 | unsigned int npages; | 2658 | unsigned int npages; |
| 2569 | struct page **pages; | 2659 | struct page **pages; |
| 2570 | unsigned int len; | 2660 | unsigned int len; |
| 2571 | unsigned int buflen = server->pdu_size + server->vals->header_preamble_size; | 2661 | unsigned int buflen = server->pdu_size; |
| 2572 | int rc; | 2662 | int rc; |
| 2573 | int i = 0; | 2663 | int i = 0; |
| 2574 | 2664 | ||
| 2575 | len = min_t(unsigned int, buflen, server->vals->read_rsp_size - | 2665 | len = min_t(unsigned int, buflen, server->vals->read_rsp_size + |
| 2576 | server->vals->header_preamble_size + | ||
| 2577 | sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; | 2666 | sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; |
| 2578 | 2667 | ||
| 2579 | rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); | 2668 | rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); |
| @@ -2581,8 +2670,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
| 2581 | return rc; | 2670 | return rc; |
| 2582 | server->total_read += rc; | 2671 | server->total_read += rc; |
| 2583 | 2672 | ||
| 2584 | len = le32_to_cpu(tr_hdr->OriginalMessageSize) + | 2673 | len = le32_to_cpu(tr_hdr->OriginalMessageSize) - |
| 2585 | server->vals->header_preamble_size - | ||
| 2586 | server->vals->read_rsp_size; | 2674 | server->vals->read_rsp_size; |
| 2587 | npages = DIV_ROUND_UP(len, PAGE_SIZE); | 2675 | npages = DIV_ROUND_UP(len, PAGE_SIZE); |
| 2588 | 2676 | ||
| @@ -2609,8 +2697,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
| 2609 | if (rc) | 2697 | if (rc) |
| 2610 | goto free_pages; | 2698 | goto free_pages; |
| 2611 | 2699 | ||
| 2612 | rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - | 2700 | rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size, |
| 2613 | server->vals->header_preamble_size, | ||
| 2614 | pages, npages, len); | 2701 | pages, npages, len); |
| 2615 | if (rc) | 2702 | if (rc) |
| 2616 | goto free_pages; | 2703 | goto free_pages; |
| @@ -2647,7 +2734,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server, | |||
| 2647 | struct mid_q_entry *mid_entry; | 2734 | struct mid_q_entry *mid_entry; |
| 2648 | 2735 | ||
| 2649 | /* switch to large buffer if too big for a small one */ | 2736 | /* switch to large buffer if too big for a small one */ |
| 2650 | if (pdu_length + server->vals->header_preamble_size > MAX_CIFS_SMALL_BUFFER_SIZE) { | 2737 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) { |
| 2651 | server->large_buf = true; | 2738 | server->large_buf = true; |
| 2652 | memcpy(server->bigbuf, buf, server->total_read); | 2739 | memcpy(server->bigbuf, buf, server->total_read); |
| 2653 | buf = server->bigbuf; | 2740 | buf = server->bigbuf; |
| @@ -2655,13 +2742,12 @@ receive_encrypted_standard(struct TCP_Server_Info *server, | |||
| 2655 | 2742 | ||
| 2656 | /* now read the rest */ | 2743 | /* now read the rest */ |
| 2657 | length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, | 2744 | length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, |
| 2658 | pdu_length - HEADER_SIZE(server) + 1 + | 2745 | pdu_length - HEADER_SIZE(server) + 1); |
| 2659 | server->vals->header_preamble_size); | ||
| 2660 | if (length < 0) | 2746 | if (length < 0) |
| 2661 | return length; | 2747 | return length; |
| 2662 | server->total_read += length; | 2748 | server->total_read += length; |
| 2663 | 2749 | ||
| 2664 | buf_size = pdu_length + server->vals->header_preamble_size - sizeof(struct smb2_transform_hdr); | 2750 | buf_size = pdu_length - sizeof(struct smb2_transform_hdr); |
| 2665 | length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0); | 2751 | length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0); |
| 2666 | if (length) | 2752 | if (length) |
| 2667 | return length; | 2753 | return length; |
| @@ -2690,7 +2776,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
| 2690 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; | 2776 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; |
| 2691 | unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); | 2777 | unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); |
| 2692 | 2778 | ||
| 2693 | if (pdu_length + server->vals->header_preamble_size < sizeof(struct smb2_transform_hdr) + | 2779 | if (pdu_length < sizeof(struct smb2_transform_hdr) + |
| 2694 | sizeof(struct smb2_sync_hdr)) { | 2780 | sizeof(struct smb2_sync_hdr)) { |
| 2695 | cifs_dbg(VFS, "Transform message is too small (%u)\n", | 2781 | cifs_dbg(VFS, "Transform message is too small (%u)\n", |
| 2696 | pdu_length); | 2782 | pdu_length); |
| @@ -2699,14 +2785,14 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
| 2699 | return -ECONNABORTED; | 2785 | return -ECONNABORTED; |
| 2700 | } | 2786 | } |
| 2701 | 2787 | ||
| 2702 | if (pdu_length + server->vals->header_preamble_size < orig_len + sizeof(struct smb2_transform_hdr)) { | 2788 | if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) { |
| 2703 | cifs_dbg(VFS, "Transform message is broken\n"); | 2789 | cifs_dbg(VFS, "Transform message is broken\n"); |
| 2704 | cifs_reconnect(server); | 2790 | cifs_reconnect(server); |
| 2705 | wake_up(&server->response_q); | 2791 | wake_up(&server->response_q); |
| 2706 | return -ECONNABORTED; | 2792 | return -ECONNABORTED; |
| 2707 | } | 2793 | } |
| 2708 | 2794 | ||
| 2709 | if (pdu_length + server->vals->header_preamble_size > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) | 2795 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) |
| 2710 | return receive_encrypted_read(server, mid); | 2796 | return receive_encrypted_read(server, mid); |
| 2711 | 2797 | ||
| 2712 | return receive_encrypted_standard(server, mid); | 2798 | return receive_encrypted_standard(server, mid); |
| @@ -2717,11 +2803,23 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
| 2717 | { | 2803 | { |
| 2718 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; | 2804 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; |
| 2719 | 2805 | ||
| 2720 | return handle_read_data(server, mid, buf, server->pdu_size + | 2806 | return handle_read_data(server, mid, buf, server->pdu_size, |
| 2721 | server->vals->header_preamble_size, | ||
| 2722 | NULL, 0, 0); | 2807 | NULL, 0, 0); |
| 2723 | } | 2808 | } |
| 2724 | 2809 | ||
| 2810 | static int | ||
| 2811 | smb2_next_header(char *buf) | ||
| 2812 | { | ||
| 2813 | struct smb2_sync_hdr *hdr = (struct smb2_sync_hdr *)buf; | ||
| 2814 | struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf; | ||
| 2815 | |||
| 2816 | if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) | ||
| 2817 | return sizeof(struct smb2_transform_hdr) + | ||
| 2818 | le32_to_cpu(t_hdr->OriginalMessageSize); | ||
| 2819 | |||
| 2820 | return le32_to_cpu(hdr->NextCommand); | ||
| 2821 | } | ||
| 2822 | |||
| 2725 | struct smb_version_operations smb20_operations = { | 2823 | struct smb_version_operations smb20_operations = { |
| 2726 | .compare_fids = smb2_compare_fids, | 2824 | .compare_fids = smb2_compare_fids, |
| 2727 | .setup_request = smb2_setup_request, | 2825 | .setup_request = smb2_setup_request, |
| @@ -2813,6 +2911,7 @@ struct smb_version_operations smb20_operations = { | |||
| 2813 | .get_acl_by_fid = get_smb2_acl_by_fid, | 2911 | .get_acl_by_fid = get_smb2_acl_by_fid, |
| 2814 | .set_acl = set_smb2_acl, | 2912 | .set_acl = set_smb2_acl, |
| 2815 | #endif /* CIFS_ACL */ | 2913 | #endif /* CIFS_ACL */ |
| 2914 | .next_header = smb2_next_header, | ||
| 2816 | }; | 2915 | }; |
| 2817 | 2916 | ||
| 2818 | struct smb_version_operations smb21_operations = { | 2917 | struct smb_version_operations smb21_operations = { |
| @@ -2907,6 +3006,7 @@ struct smb_version_operations smb21_operations = { | |||
| 2907 | .get_acl_by_fid = get_smb2_acl_by_fid, | 3006 | .get_acl_by_fid = get_smb2_acl_by_fid, |
| 2908 | .set_acl = set_smb2_acl, | 3007 | .set_acl = set_smb2_acl, |
| 2909 | #endif /* CIFS_ACL */ | 3008 | #endif /* CIFS_ACL */ |
| 3009 | .next_header = smb2_next_header, | ||
| 2910 | }; | 3010 | }; |
| 2911 | 3011 | ||
| 2912 | struct smb_version_operations smb30_operations = { | 3012 | struct smb_version_operations smb30_operations = { |
| @@ -3011,6 +3111,7 @@ struct smb_version_operations smb30_operations = { | |||
| 3011 | .get_acl_by_fid = get_smb2_acl_by_fid, | 3111 | .get_acl_by_fid = get_smb2_acl_by_fid, |
| 3012 | .set_acl = set_smb2_acl, | 3112 | .set_acl = set_smb2_acl, |
| 3013 | #endif /* CIFS_ACL */ | 3113 | #endif /* CIFS_ACL */ |
| 3114 | .next_header = smb2_next_header, | ||
| 3014 | }; | 3115 | }; |
| 3015 | 3116 | ||
| 3016 | #ifdef CONFIG_CIFS_SMB311 | 3117 | #ifdef CONFIG_CIFS_SMB311 |
| @@ -3111,6 +3212,7 @@ struct smb_version_operations smb311_operations = { | |||
| 3111 | .query_all_EAs = smb2_query_eas, | 3212 | .query_all_EAs = smb2_query_eas, |
| 3112 | .set_EA = smb2_set_ea, | 3213 | .set_EA = smb2_set_ea, |
| 3113 | #endif /* CIFS_XATTR */ | 3214 | #endif /* CIFS_XATTR */ |
| 3215 | .next_header = smb2_next_header, | ||
| 3114 | }; | 3216 | }; |
| 3115 | #endif /* CIFS_SMB311 */ | 3217 | #endif /* CIFS_SMB311 */ |
| 3116 | 3218 | ||
| @@ -3122,8 +3224,8 @@ struct smb_version_values smb20_values = { | |||
| 3122 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3224 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3123 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3225 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3124 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3226 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3125 | .header_size = sizeof(struct smb2_hdr), | 3227 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3126 | .header_preamble_size = 4, | 3228 | .header_preamble_size = 0, |
| 3127 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3229 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3128 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3230 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3129 | .lock_cmd = SMB2_LOCK, | 3231 | .lock_cmd = SMB2_LOCK, |
| @@ -3143,8 +3245,8 @@ struct smb_version_values smb21_values = { | |||
| 3143 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3245 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3144 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3246 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3145 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3247 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3146 | .header_size = sizeof(struct smb2_hdr), | 3248 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3147 | .header_preamble_size = 4, | 3249 | .header_preamble_size = 0, |
| 3148 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3250 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3149 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3251 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3150 | .lock_cmd = SMB2_LOCK, | 3252 | .lock_cmd = SMB2_LOCK, |
| @@ -3164,8 +3266,8 @@ struct smb_version_values smb3any_values = { | |||
| 3164 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3266 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3165 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3267 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3166 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3268 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3167 | .header_size = sizeof(struct smb2_hdr), | 3269 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3168 | .header_preamble_size = 4, | 3270 | .header_preamble_size = 0, |
| 3169 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3271 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3170 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3272 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3171 | .lock_cmd = SMB2_LOCK, | 3273 | .lock_cmd = SMB2_LOCK, |
| @@ -3185,8 +3287,8 @@ struct smb_version_values smbdefault_values = { | |||
| 3185 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3287 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3186 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3288 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3187 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3289 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3188 | .header_size = sizeof(struct smb2_hdr), | 3290 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3189 | .header_preamble_size = 4, | 3291 | .header_preamble_size = 0, |
| 3190 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3292 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3191 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3293 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3192 | .lock_cmd = SMB2_LOCK, | 3294 | .lock_cmd = SMB2_LOCK, |
| @@ -3206,8 +3308,8 @@ struct smb_version_values smb30_values = { | |||
| 3206 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3308 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3207 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3309 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3208 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3310 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3209 | .header_size = sizeof(struct smb2_hdr), | 3311 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3210 | .header_preamble_size = 4, | 3312 | .header_preamble_size = 0, |
| 3211 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3313 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3212 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3314 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3213 | .lock_cmd = SMB2_LOCK, | 3315 | .lock_cmd = SMB2_LOCK, |
| @@ -3227,8 +3329,8 @@ struct smb_version_values smb302_values = { | |||
| 3227 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3329 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3228 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3330 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3229 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3331 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3230 | .header_size = sizeof(struct smb2_hdr), | 3332 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3231 | .header_preamble_size = 4, | 3333 | .header_preamble_size = 0, |
| 3232 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3334 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3233 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3335 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3234 | .lock_cmd = SMB2_LOCK, | 3336 | .lock_cmd = SMB2_LOCK, |
| @@ -3249,8 +3351,8 @@ struct smb_version_values smb311_values = { | |||
| 3249 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 3351 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
| 3250 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 3352 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
| 3251 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | 3353 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, |
| 3252 | .header_size = sizeof(struct smb2_hdr), | 3354 | .header_size = sizeof(struct smb2_sync_hdr), |
| 3253 | .header_preamble_size = 4, | 3355 | .header_preamble_size = 0, |
| 3254 | .max_header_size = MAX_SMB2_HDR_SIZE, | 3356 | .max_header_size = MAX_SMB2_HDR_SIZE, |
| 3255 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | 3357 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, |
| 3256 | .lock_cmd = SMB2_LOCK, | 3358 | .lock_cmd = SMB2_LOCK, |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 0f48741a0130..281fbc1dc720 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include "cifspdu.h" | 49 | #include "cifspdu.h" |
| 50 | #include "cifs_spnego.h" | 50 | #include "cifs_spnego.h" |
| 51 | #include "smbdirect.h" | 51 | #include "smbdirect.h" |
| 52 | #include "trace.h" | ||
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| 54 | * The following table defines the expected "StructureSize" of SMB2 requests | 55 | * The following table defines the expected "StructureSize" of SMB2 requests |
| @@ -79,7 +80,7 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
| 79 | /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */ | 80 | /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */ |
| 80 | }; | 81 | }; |
| 81 | 82 | ||
| 82 | static int encryption_required(const struct cifs_tcon *tcon) | 83 | static int smb3_encryption_required(const struct cifs_tcon *tcon) |
| 83 | { | 84 | { |
| 84 | if (!tcon) | 85 | if (!tcon) |
| 85 | return 0; | 86 | return 0; |
| @@ -145,7 +146,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, | |||
| 145 | shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ | 146 | shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ |
| 146 | 147 | ||
| 147 | if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && | 148 | if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && |
| 148 | !encryption_required(tcon)) | 149 | !smb3_encryption_required(tcon)) |
| 149 | shdr->Flags |= SMB2_FLAGS_SIGNED; | 150 | shdr->Flags |= SMB2_FLAGS_SIGNED; |
| 150 | out: | 151 | out: |
| 151 | return; | 152 | return; |
| @@ -367,6 +368,7 @@ smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, | |||
| 367 | 368 | ||
| 368 | #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) | 369 | #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) |
| 369 | #define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) | 370 | #define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) |
| 371 | #define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100) | ||
| 370 | 372 | ||
| 371 | static void | 373 | static void |
| 372 | build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) | 374 | build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) |
| @@ -390,21 +392,35 @@ build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) | |||
| 390 | } | 392 | } |
| 391 | 393 | ||
| 392 | static void | 394 | static void |
| 395 | build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt) | ||
| 396 | { | ||
| 397 | pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE; | ||
| 398 | pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); | ||
| 399 | } | ||
| 400 | |||
| 401 | static void | ||
| 393 | assemble_neg_contexts(struct smb2_negotiate_req *req, | 402 | assemble_neg_contexts(struct smb2_negotiate_req *req, |
| 394 | unsigned int *total_len) | 403 | unsigned int *total_len) |
| 395 | { | 404 | { |
| 396 | char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT; | 405 | char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT; |
| 406 | unsigned int ctxt_len; | ||
| 397 | 407 | ||
| 408 | *total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */ | ||
| 398 | build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); | 409 | build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); |
| 399 | /* Add 2 to size to round to 8 byte boundary */ | 410 | ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; |
| 411 | *total_len += ctxt_len; | ||
| 412 | pneg_ctxt += ctxt_len; | ||
| 400 | 413 | ||
| 401 | pneg_ctxt += 2 + sizeof(struct smb2_preauth_neg_context); | ||
| 402 | build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); | 414 | build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); |
| 403 | req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); | 415 | ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8; |
| 404 | req->NegotiateContextCount = cpu_to_le16(2); | 416 | *total_len += ctxt_len; |
| 417 | pneg_ctxt += ctxt_len; | ||
| 418 | |||
| 419 | build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); | ||
| 420 | *total_len += sizeof(struct smb2_posix_neg_context); | ||
| 405 | 421 | ||
| 406 | *total_len += 4 + sizeof(struct smb2_preauth_neg_context) | 422 | req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); |
| 407 | + sizeof(struct smb2_encryption_neg_context); | 423 | req->NegotiateContextCount = cpu_to_le16(3); |
| 408 | } | 424 | } |
| 409 | 425 | ||
| 410 | static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) | 426 | static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) |
| @@ -449,12 +465,12 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server, | |||
| 449 | } | 465 | } |
| 450 | 466 | ||
| 451 | static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | 467 | static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, |
| 452 | struct TCP_Server_Info *server) | 468 | struct TCP_Server_Info *server, |
| 469 | unsigned int len_of_smb) | ||
| 453 | { | 470 | { |
| 454 | struct smb2_neg_context *pctx; | 471 | struct smb2_neg_context *pctx; |
| 455 | unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset); | 472 | unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset); |
| 456 | unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount); | 473 | unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount); |
| 457 | unsigned int len_of_smb = be32_to_cpu(rsp->hdr.smb2_buf_length); | ||
| 458 | unsigned int len_of_ctxts, i; | 474 | unsigned int len_of_ctxts, i; |
| 459 | int rc = 0; | 475 | int rc = 0; |
| 460 | 476 | ||
| @@ -475,8 +491,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | |||
| 475 | if (len_of_ctxts < sizeof(struct smb2_neg_context)) | 491 | if (len_of_ctxts < sizeof(struct smb2_neg_context)) |
| 476 | break; | 492 | break; |
| 477 | 493 | ||
| 478 | pctx = (struct smb2_neg_context *)(offset + | 494 | pctx = (struct smb2_neg_context *)(offset + (char *)rsp); |
| 479 | server->vals->header_preamble_size + (char *)rsp); | ||
| 480 | clen = le16_to_cpu(pctx->DataLength); | 495 | clen = le16_to_cpu(pctx->DataLength); |
| 481 | if (clen > len_of_ctxts) | 496 | if (clen > len_of_ctxts) |
| 482 | break; | 497 | break; |
| @@ -487,6 +502,8 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | |||
| 487 | else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) | 502 | else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) |
| 488 | rc = decode_encrypt_ctx(server, | 503 | rc = decode_encrypt_ctx(server, |
| 489 | (struct smb2_encryption_neg_context *)pctx); | 504 | (struct smb2_encryption_neg_context *)pctx); |
| 505 | else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) | ||
| 506 | server->posix_ext_supported = true; | ||
| 490 | else | 507 | else |
| 491 | cifs_dbg(VFS, "unknown negcontext of type %d ignored\n", | 508 | cifs_dbg(VFS, "unknown negcontext of type %d ignored\n", |
| 492 | le16_to_cpu(pctx->ContextType)); | 509 | le16_to_cpu(pctx->ContextType)); |
| @@ -501,6 +518,64 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | |||
| 501 | return rc; | 518 | return rc; |
| 502 | } | 519 | } |
| 503 | 520 | ||
| 521 | static struct create_posix * | ||
| 522 | create_posix_buf(umode_t mode) | ||
| 523 | { | ||
| 524 | struct create_posix *buf; | ||
| 525 | |||
| 526 | buf = kzalloc(sizeof(struct create_posix), | ||
| 527 | GFP_KERNEL); | ||
| 528 | if (!buf) | ||
| 529 | return NULL; | ||
| 530 | |||
| 531 | buf->ccontext.DataOffset = | ||
| 532 | cpu_to_le16(offsetof(struct create_posix, Mode)); | ||
| 533 | buf->ccontext.DataLength = cpu_to_le32(4); | ||
| 534 | buf->ccontext.NameOffset = | ||
| 535 | cpu_to_le16(offsetof(struct create_posix, Name)); | ||
| 536 | buf->ccontext.NameLength = cpu_to_le16(16); | ||
| 537 | |||
| 538 | /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ | ||
| 539 | buf->Name[0] = 0x93; | ||
| 540 | buf->Name[1] = 0xAD; | ||
| 541 | buf->Name[2] = 0x25; | ||
| 542 | buf->Name[3] = 0x50; | ||
| 543 | buf->Name[4] = 0x9C; | ||
| 544 | buf->Name[5] = 0xB4; | ||
| 545 | buf->Name[6] = 0x11; | ||
| 546 | buf->Name[7] = 0xE7; | ||
| 547 | buf->Name[8] = 0xB4; | ||
| 548 | buf->Name[9] = 0x23; | ||
| 549 | buf->Name[10] = 0x83; | ||
| 550 | buf->Name[11] = 0xDE; | ||
| 551 | buf->Name[12] = 0x96; | ||
| 552 | buf->Name[13] = 0x8B; | ||
| 553 | buf->Name[14] = 0xCD; | ||
| 554 | buf->Name[15] = 0x7C; | ||
| 555 | buf->Mode = cpu_to_le32(mode); | ||
| 556 | cifs_dbg(FYI, "mode on posix create 0%o", mode); | ||
| 557 | return buf; | ||
| 558 | } | ||
| 559 | |||
| 560 | static int | ||
| 561 | add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) | ||
| 562 | { | ||
| 563 | struct smb2_create_req *req = iov[0].iov_base; | ||
| 564 | unsigned int num = *num_iovec; | ||
| 565 | |||
| 566 | iov[num].iov_base = create_posix_buf(mode); | ||
| 567 | if (iov[num].iov_base == NULL) | ||
| 568 | return -ENOMEM; | ||
| 569 | iov[num].iov_len = sizeof(struct create_posix); | ||
| 570 | if (!req->CreateContextsOffset) | ||
| 571 | req->CreateContextsOffset = cpu_to_le32( | ||
| 572 | sizeof(struct smb2_create_req) + | ||
| 573 | iov[num - 1].iov_len); | ||
| 574 | le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix)); | ||
| 575 | *num_iovec = num + 1; | ||
| 576 | return 0; | ||
| 577 | } | ||
| 578 | |||
| 504 | #else | 579 | #else |
| 505 | static void assemble_neg_contexts(struct smb2_negotiate_req *req, | 580 | static void assemble_neg_contexts(struct smb2_negotiate_req *req, |
| 506 | unsigned int *total_len) | 581 | unsigned int *total_len) |
| @@ -691,7 +766,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 691 | server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES; | 766 | server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES; |
| 692 | 767 | ||
| 693 | security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, | 768 | security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, |
| 694 | &rsp->hdr); | 769 | (struct smb2_sync_hdr *)rsp); |
| 695 | /* | 770 | /* |
| 696 | * See MS-SMB2 section 2.2.4: if no blob, client picks default which | 771 | * See MS-SMB2 section 2.2.4: if no blob, client picks default which |
| 697 | * for us will be | 772 | * for us will be |
| @@ -718,7 +793,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 718 | #ifdef CONFIG_CIFS_SMB311 | 793 | #ifdef CONFIG_CIFS_SMB311 |
| 719 | if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { | 794 | if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { |
| 720 | if (rsp->NegotiateContextCount) | 795 | if (rsp->NegotiateContextCount) |
| 721 | rc = smb311_decode_neg_context(rsp, server); | 796 | rc = smb311_decode_neg_context(rsp, server, |
| 797 | rsp_iov.iov_len); | ||
| 722 | else | 798 | else |
| 723 | cifs_dbg(VFS, "Missing expected negotiate contexts\n"); | 799 | cifs_dbg(VFS, "Missing expected negotiate contexts\n"); |
| 724 | } | 800 | } |
| @@ -1054,7 +1130,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) | |||
| 1054 | goto out_put_spnego_key; | 1130 | goto out_put_spnego_key; |
| 1055 | 1131 | ||
| 1056 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; | 1132 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
| 1057 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 1133 | ses->Suid = rsp->sync_hdr.SessionId; |
| 1058 | 1134 | ||
| 1059 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 1135 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 1060 | 1136 | ||
| @@ -1130,13 +1206,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) | |||
| 1130 | 1206 | ||
| 1131 | /* If true, rc here is expected and not an error */ | 1207 | /* If true, rc here is expected and not an error */ |
| 1132 | if (sess_data->buf0_type != CIFS_NO_BUFFER && | 1208 | if (sess_data->buf0_type != CIFS_NO_BUFFER && |
| 1133 | rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) | 1209 | rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) |
| 1134 | rc = 0; | 1210 | rc = 0; |
| 1135 | 1211 | ||
| 1136 | if (rc) | 1212 | if (rc) |
| 1137 | goto out; | 1213 | goto out; |
| 1138 | 1214 | ||
| 1139 | if (offsetof(struct smb2_sess_setup_rsp, Buffer) - ses->server->vals->header_preamble_size != | 1215 | if (offsetof(struct smb2_sess_setup_rsp, Buffer) != |
| 1140 | le16_to_cpu(rsp->SecurityBufferOffset)) { | 1216 | le16_to_cpu(rsp->SecurityBufferOffset)) { |
| 1141 | cifs_dbg(VFS, "Invalid security buffer offset %d\n", | 1217 | cifs_dbg(VFS, "Invalid security buffer offset %d\n", |
| 1142 | le16_to_cpu(rsp->SecurityBufferOffset)); | 1218 | le16_to_cpu(rsp->SecurityBufferOffset)); |
| @@ -1151,7 +1227,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) | |||
| 1151 | cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); | 1227 | cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); |
| 1152 | 1228 | ||
| 1153 | 1229 | ||
| 1154 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 1230 | ses->Suid = rsp->sync_hdr.SessionId; |
| 1155 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 1231 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 1156 | 1232 | ||
| 1157 | out: | 1233 | out: |
| @@ -1209,7 +1285,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) | |||
| 1209 | 1285 | ||
| 1210 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; | 1286 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
| 1211 | 1287 | ||
| 1212 | ses->Suid = rsp->hdr.sync_hdr.SessionId; | 1288 | ses->Suid = rsp->sync_hdr.SessionId; |
| 1213 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); | 1289 | ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
| 1214 | 1290 | ||
| 1215 | rc = SMB2_sess_establish_session(sess_data); | 1291 | rc = SMB2_sess_establish_session(sess_data); |
| @@ -1276,6 +1352,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
| 1276 | sess_data->ses = ses; | 1352 | sess_data->ses = ses; |
| 1277 | sess_data->buf0_type = CIFS_NO_BUFFER; | 1353 | sess_data->buf0_type = CIFS_NO_BUFFER; |
| 1278 | sess_data->nls_cp = (struct nls_table *) nls_cp; | 1354 | sess_data->nls_cp = (struct nls_table *) nls_cp; |
| 1355 | sess_data->previous_session = ses->Suid; | ||
| 1279 | 1356 | ||
| 1280 | #ifdef CONFIG_CIFS_SMB311 | 1357 | #ifdef CONFIG_CIFS_SMB311 |
| 1281 | /* | 1358 | /* |
| @@ -1403,7 +1480,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1403 | return rc; | 1480 | return rc; |
| 1404 | } | 1481 | } |
| 1405 | 1482 | ||
| 1406 | if (encryption_required(tcon)) | 1483 | if (smb3_encryption_required(tcon)) |
| 1407 | flags |= CIFS_TRANSFORM_REQ; | 1484 | flags |= CIFS_TRANSFORM_REQ; |
| 1408 | 1485 | ||
| 1409 | iov[0].iov_base = (char *)req; | 1486 | iov[0].iov_base = (char *)req; |
| @@ -1419,7 +1496,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1419 | 1496 | ||
| 1420 | /* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */ | 1497 | /* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */ |
| 1421 | if ((ses->server->dialect == SMB311_PROT_ID) && | 1498 | if ((ses->server->dialect == SMB311_PROT_ID) && |
| 1422 | !encryption_required(tcon)) | 1499 | !smb3_encryption_required(tcon)) |
| 1423 | req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; | 1500 | req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
| 1424 | 1501 | ||
| 1425 | rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov); | 1502 | rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov); |
| @@ -1457,7 +1534,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1457 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); | 1534 | tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); |
| 1458 | tcon->tidStatus = CifsGood; | 1535 | tcon->tidStatus = CifsGood; |
| 1459 | tcon->need_reconnect = false; | 1536 | tcon->need_reconnect = false; |
| 1460 | tcon->tid = rsp->hdr.sync_hdr.TreeId; | 1537 | tcon->tid = rsp->sync_hdr.TreeId; |
| 1461 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); | 1538 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
| 1462 | 1539 | ||
| 1463 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && | 1540 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
| @@ -1477,7 +1554,7 @@ tcon_exit: | |||
| 1477 | return rc; | 1554 | return rc; |
| 1478 | 1555 | ||
| 1479 | tcon_error_exit: | 1556 | tcon_error_exit: |
| 1480 | if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { | 1557 | if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
| 1481 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 1558 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
| 1482 | } | 1559 | } |
| 1483 | goto tcon_exit; | 1560 | goto tcon_exit; |
| @@ -1508,7 +1585,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 1508 | if (rc) | 1585 | if (rc) |
| 1509 | return rc; | 1586 | return rc; |
| 1510 | 1587 | ||
| 1511 | if (encryption_required(tcon)) | 1588 | if (smb3_encryption_required(tcon)) |
| 1512 | flags |= CIFS_TRANSFORM_REQ; | 1589 | flags |= CIFS_TRANSFORM_REQ; |
| 1513 | 1590 | ||
| 1514 | flags |= CIFS_NO_RESP; | 1591 | flags |= CIFS_NO_RESP; |
| @@ -1575,7 +1652,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid) | |||
| 1575 | 1652 | ||
| 1576 | static __u8 | 1653 | static __u8 |
| 1577 | parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, | 1654 | parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, |
| 1578 | unsigned int *epoch) | 1655 | unsigned int *epoch, char *lease_key) |
| 1579 | { | 1656 | { |
| 1580 | char *data_offset; | 1657 | char *data_offset; |
| 1581 | struct create_context *cc; | 1658 | struct create_context *cc; |
| @@ -1583,14 +1660,15 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, | |||
| 1583 | unsigned int remaining; | 1660 | unsigned int remaining; |
| 1584 | char *name; | 1661 | char *name; |
| 1585 | 1662 | ||
| 1586 | data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset); | 1663 | data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); |
| 1587 | remaining = le32_to_cpu(rsp->CreateContextsLength); | 1664 | remaining = le32_to_cpu(rsp->CreateContextsLength); |
| 1588 | cc = (struct create_context *)data_offset; | 1665 | cc = (struct create_context *)data_offset; |
| 1589 | while (remaining >= sizeof(struct create_context)) { | 1666 | while (remaining >= sizeof(struct create_context)) { |
| 1590 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; | 1667 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; |
| 1591 | if (le16_to_cpu(cc->NameLength) == 4 && | 1668 | if (le16_to_cpu(cc->NameLength) == 4 && |
| 1592 | strncmp(name, "RqLs", 4) == 0) | 1669 | strncmp(name, "RqLs", 4) == 0) |
| 1593 | return server->ops->parse_lease_buf(cc, epoch); | 1670 | return server->ops->parse_lease_buf(cc, epoch, |
| 1671 | lease_key); | ||
| 1594 | 1672 | ||
| 1595 | next = le32_to_cpu(cc->Next); | 1673 | next = le32_to_cpu(cc->Next); |
| 1596 | if (!next) | 1674 | if (!next) |
| @@ -1818,7 +1896,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1818 | struct TCP_Server_Info *server; | 1896 | struct TCP_Server_Info *server; |
| 1819 | struct cifs_tcon *tcon = oparms->tcon; | 1897 | struct cifs_tcon *tcon = oparms->tcon; |
| 1820 | struct cifs_ses *ses = tcon->ses; | 1898 | struct cifs_ses *ses = tcon->ses; |
| 1821 | struct kvec iov[4]; | 1899 | struct kvec iov[5]; /* make sure at least one for each open context */ |
| 1822 | struct kvec rsp_iov = {NULL, 0}; | 1900 | struct kvec rsp_iov = {NULL, 0}; |
| 1823 | int resp_buftype; | 1901 | int resp_buftype; |
| 1824 | int uni_path_len; | 1902 | int uni_path_len; |
| @@ -1827,7 +1905,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1827 | int rc = 0; | 1905 | int rc = 0; |
| 1828 | unsigned int n_iov = 2; | 1906 | unsigned int n_iov = 2; |
| 1829 | __u32 file_attributes = 0; | 1907 | __u32 file_attributes = 0; |
| 1830 | char *dhc_buf = NULL, *lc_buf = NULL; | 1908 | char *dhc_buf = NULL, *lc_buf = NULL, *pc_buf = NULL; |
| 1831 | int flags = 0; | 1909 | int flags = 0; |
| 1832 | unsigned int total_len; | 1910 | unsigned int total_len; |
| 1833 | 1911 | ||
| @@ -1843,7 +1921,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1843 | if (rc) | 1921 | if (rc) |
| 1844 | return rc; | 1922 | return rc; |
| 1845 | 1923 | ||
| 1846 | if (encryption_required(tcon)) | 1924 | if (smb3_encryption_required(tcon)) |
| 1847 | flags |= CIFS_TRANSFORM_REQ; | 1925 | flags |= CIFS_TRANSFORM_REQ; |
| 1848 | 1926 | ||
| 1849 | if (oparms->create_options & CREATE_OPTION_READONLY) | 1927 | if (oparms->create_options & CREATE_OPTION_READONLY) |
| @@ -1944,6 +2022,27 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1944 | dhc_buf = iov[n_iov-1].iov_base; | 2022 | dhc_buf = iov[n_iov-1].iov_base; |
| 1945 | } | 2023 | } |
| 1946 | 2024 | ||
| 2025 | #ifdef CONFIG_CIFS_SMB311 | ||
| 2026 | if (tcon->posix_extensions) { | ||
| 2027 | if (n_iov > 2) { | ||
| 2028 | struct create_context *ccontext = | ||
| 2029 | (struct create_context *)iov[n_iov-1].iov_base; | ||
| 2030 | ccontext->Next = | ||
| 2031 | cpu_to_le32(iov[n_iov-1].iov_len); | ||
| 2032 | } | ||
| 2033 | |||
| 2034 | rc = add_posix_context(iov, &n_iov, oparms->mode); | ||
| 2035 | if (rc) { | ||
| 2036 | cifs_small_buf_release(req); | ||
| 2037 | kfree(copy_path); | ||
| 2038 | kfree(lc_buf); | ||
| 2039 | kfree(dhc_buf); | ||
| 2040 | return rc; | ||
| 2041 | } | ||
| 2042 | pc_buf = iov[n_iov-1].iov_base; | ||
| 2043 | } | ||
| 2044 | #endif /* SMB311 */ | ||
| 2045 | |||
| 1947 | rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags, | 2046 | rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags, |
| 1948 | &rsp_iov); | 2047 | &rsp_iov); |
| 1949 | cifs_small_buf_release(req); | 2048 | cifs_small_buf_release(req); |
| @@ -1956,8 +2055,13 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1956 | resp_buftype = CIFS_NO_BUFFER; | 2055 | resp_buftype = CIFS_NO_BUFFER; |
| 1957 | rsp = NULL; | 2056 | rsp = NULL; |
| 1958 | } | 2057 | } |
| 2058 | trace_smb3_open_err(xid, tcon->tid, ses->Suid, | ||
| 2059 | oparms->create_options, oparms->desired_access, rc); | ||
| 1959 | goto creat_exit; | 2060 | goto creat_exit; |
| 1960 | } | 2061 | } else |
| 2062 | trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, | ||
| 2063 | ses->Suid, oparms->create_options, | ||
| 2064 | oparms->desired_access); | ||
| 1961 | 2065 | ||
| 1962 | oparms->fid->persistent_fid = rsp->PersistentFileId; | 2066 | oparms->fid->persistent_fid = rsp->PersistentFileId; |
| 1963 | oparms->fid->volatile_fid = rsp->VolatileFileId; | 2067 | oparms->fid->volatile_fid = rsp->VolatileFileId; |
| @@ -1972,13 +2076,15 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 1972 | } | 2076 | } |
| 1973 | 2077 | ||
| 1974 | if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) | 2078 | if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) |
| 1975 | *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch); | 2079 | *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch, |
| 2080 | oparms->fid->lease_key); | ||
| 1976 | else | 2081 | else |
| 1977 | *oplock = rsp->OplockLevel; | 2082 | *oplock = rsp->OplockLevel; |
| 1978 | creat_exit: | 2083 | creat_exit: |
| 1979 | kfree(copy_path); | 2084 | kfree(copy_path); |
| 1980 | kfree(lc_buf); | 2085 | kfree(lc_buf); |
| 1981 | kfree(dhc_buf); | 2086 | kfree(dhc_buf); |
| 2087 | kfree(pc_buf); | ||
| 1982 | free_rsp_buf(resp_buftype, rsp); | 2088 | free_rsp_buf(resp_buftype, rsp); |
| 1983 | return rc; | 2089 | return rc; |
| 1984 | } | 2090 | } |
| @@ -1994,7 +2100,6 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 1994 | { | 2100 | { |
| 1995 | struct smb2_ioctl_req *req; | 2101 | struct smb2_ioctl_req *req; |
| 1996 | struct smb2_ioctl_rsp *rsp; | 2102 | struct smb2_ioctl_rsp *rsp; |
| 1997 | struct smb2_sync_hdr *shdr; | ||
| 1998 | struct cifs_ses *ses; | 2103 | struct cifs_ses *ses; |
| 1999 | struct kvec iov[2]; | 2104 | struct kvec iov[2]; |
| 2000 | struct kvec rsp_iov; | 2105 | struct kvec rsp_iov; |
| @@ -2025,7 +2130,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2025 | if (rc) | 2130 | if (rc) |
| 2026 | return rc; | 2131 | return rc; |
| 2027 | 2132 | ||
| 2028 | if (encryption_required(tcon)) | 2133 | if (smb3_encryption_required(tcon)) |
| 2029 | flags |= CIFS_TRANSFORM_REQ; | 2134 | flags |= CIFS_TRANSFORM_REQ; |
| 2030 | 2135 | ||
| 2031 | req->CtlCode = cpu_to_le32(opcode); | 2136 | req->CtlCode = cpu_to_le32(opcode); |
| @@ -2088,6 +2193,10 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2088 | cifs_small_buf_release(req); | 2193 | cifs_small_buf_release(req); |
| 2089 | rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; | 2194 | rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; |
| 2090 | 2195 | ||
| 2196 | if (rc != 0) | ||
| 2197 | trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid, | ||
| 2198 | ses->Suid, 0, opcode, rc); | ||
| 2199 | |||
| 2091 | if ((rc != 0) && (rc != -EINVAL)) { | 2200 | if ((rc != 0) && (rc != -EINVAL)) { |
| 2092 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); | 2201 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
| 2093 | goto ioctl_exit; | 2202 | goto ioctl_exit; |
| @@ -2115,7 +2224,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2115 | goto ioctl_exit; | 2224 | goto ioctl_exit; |
| 2116 | } | 2225 | } |
| 2117 | 2226 | ||
| 2118 | if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) { | 2227 | if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) { |
| 2119 | cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, | 2228 | cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, |
| 2120 | le32_to_cpu(rsp->OutputOffset)); | 2229 | le32_to_cpu(rsp->OutputOffset)); |
| 2121 | *plen = 0; | 2230 | *plen = 0; |
| @@ -2129,8 +2238,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2129 | goto ioctl_exit; | 2238 | goto ioctl_exit; |
| 2130 | } | 2239 | } |
| 2131 | 2240 | ||
| 2132 | shdr = get_sync_hdr(rsp); | 2241 | memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen); |
| 2133 | memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen); | ||
| 2134 | ioctl_exit: | 2242 | ioctl_exit: |
| 2135 | free_rsp_buf(resp_buftype, rsp); | 2243 | free_rsp_buf(resp_buftype, rsp); |
| 2136 | return rc; | 2244 | return rc; |
| @@ -2162,8 +2270,8 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2162 | } | 2270 | } |
| 2163 | 2271 | ||
| 2164 | int | 2272 | int |
| 2165 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | 2273 | SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, |
| 2166 | u64 persistent_fid, u64 volatile_fid) | 2274 | u64 persistent_fid, u64 volatile_fid, int flags) |
| 2167 | { | 2275 | { |
| 2168 | struct smb2_close_req *req; | 2276 | struct smb2_close_req *req; |
| 2169 | struct smb2_close_rsp *rsp; | 2277 | struct smb2_close_rsp *rsp; |
| @@ -2172,7 +2280,6 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2172 | struct kvec rsp_iov; | 2280 | struct kvec rsp_iov; |
| 2173 | int resp_buftype; | 2281 | int resp_buftype; |
| 2174 | int rc = 0; | 2282 | int rc = 0; |
| 2175 | int flags = 0; | ||
| 2176 | unsigned int total_len; | 2283 | unsigned int total_len; |
| 2177 | 2284 | ||
| 2178 | cifs_dbg(FYI, "Close\n"); | 2285 | cifs_dbg(FYI, "Close\n"); |
| @@ -2184,7 +2291,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2184 | if (rc) | 2291 | if (rc) |
| 2185 | return rc; | 2292 | return rc; |
| 2186 | 2293 | ||
| 2187 | if (encryption_required(tcon)) | 2294 | if (smb3_encryption_required(tcon)) |
| 2188 | flags |= CIFS_TRANSFORM_REQ; | 2295 | flags |= CIFS_TRANSFORM_REQ; |
| 2189 | 2296 | ||
| 2190 | req->PersistentFileId = persistent_fid; | 2297 | req->PersistentFileId = persistent_fid; |
| @@ -2199,6 +2306,8 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2199 | 2306 | ||
| 2200 | if (rc != 0) { | 2307 | if (rc != 0) { |
| 2201 | cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); | 2308 | cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); |
| 2309 | trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, | ||
| 2310 | rc); | ||
| 2202 | goto close_exit; | 2311 | goto close_exit; |
| 2203 | } | 2312 | } |
| 2204 | 2313 | ||
| @@ -2209,14 +2318,20 @@ close_exit: | |||
| 2209 | return rc; | 2318 | return rc; |
| 2210 | } | 2319 | } |
| 2211 | 2320 | ||
| 2321 | int | ||
| 2322 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | ||
| 2323 | u64 persistent_fid, u64 volatile_fid) | ||
| 2324 | { | ||
| 2325 | return SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); | ||
| 2326 | } | ||
| 2327 | |||
| 2212 | static int | 2328 | static int |
| 2213 | validate_iov(struct TCP_Server_Info *server, | 2329 | validate_iov(unsigned int offset, unsigned int buffer_length, |
| 2214 | unsigned int offset, unsigned int buffer_length, | ||
| 2215 | struct kvec *iov, unsigned int min_buf_size) | 2330 | struct kvec *iov, unsigned int min_buf_size) |
| 2216 | { | 2331 | { |
| 2217 | unsigned int smb_len = iov->iov_len; | 2332 | unsigned int smb_len = iov->iov_len; |
| 2218 | char *end_of_smb = smb_len + server->vals->header_preamble_size + (char *)iov->iov_base; | 2333 | char *end_of_smb = smb_len + (char *)iov->iov_base; |
| 2219 | char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)iov->iov_base; | 2334 | char *begin_of_buf = offset + (char *)iov->iov_base; |
| 2220 | char *end_of_buf = begin_of_buf + buffer_length; | 2335 | char *end_of_buf = begin_of_buf + buffer_length; |
| 2221 | 2336 | ||
| 2222 | 2337 | ||
| @@ -2246,18 +2361,17 @@ validate_iov(struct TCP_Server_Info *server, | |||
| 2246 | * Caller must free buffer. | 2361 | * Caller must free buffer. |
| 2247 | */ | 2362 | */ |
| 2248 | static int | 2363 | static int |
| 2249 | validate_and_copy_iov(struct TCP_Server_Info *server, | 2364 | validate_and_copy_iov(unsigned int offset, unsigned int buffer_length, |
| 2250 | unsigned int offset, unsigned int buffer_length, | ||
| 2251 | struct kvec *iov, unsigned int minbufsize, | 2365 | struct kvec *iov, unsigned int minbufsize, |
| 2252 | char *data) | 2366 | char *data) |
| 2253 | { | 2367 | { |
| 2254 | char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)(iov->iov_base); | 2368 | char *begin_of_buf = offset + (char *)iov->iov_base; |
| 2255 | int rc; | 2369 | int rc; |
| 2256 | 2370 | ||
| 2257 | if (!data) | 2371 | if (!data) |
| 2258 | return -EINVAL; | 2372 | return -EINVAL; |
| 2259 | 2373 | ||
| 2260 | rc = validate_iov(server, offset, buffer_length, iov, minbufsize); | 2374 | rc = validate_iov(offset, buffer_length, iov, minbufsize); |
| 2261 | if (rc) | 2375 | if (rc) |
| 2262 | return rc; | 2376 | return rc; |
| 2263 | 2377 | ||
| @@ -2292,7 +2406,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2292 | if (rc) | 2406 | if (rc) |
| 2293 | return rc; | 2407 | return rc; |
| 2294 | 2408 | ||
| 2295 | if (encryption_required(tcon)) | 2409 | if (smb3_encryption_required(tcon)) |
| 2296 | flags |= CIFS_TRANSFORM_REQ; | 2410 | flags |= CIFS_TRANSFORM_REQ; |
| 2297 | 2411 | ||
| 2298 | req->InfoType = info_type; | 2412 | req->InfoType = info_type; |
| @@ -2318,6 +2432,8 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2318 | 2432 | ||
| 2319 | if (rc) { | 2433 | if (rc) { |
| 2320 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | 2434 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
| 2435 | trace_smb3_query_info_err(xid, persistent_fid, tcon->tid, | ||
| 2436 | ses->Suid, info_class, (__u32)info_type, rc); | ||
| 2321 | goto qinf_exit; | 2437 | goto qinf_exit; |
| 2322 | } | 2438 | } |
| 2323 | 2439 | ||
| @@ -2335,8 +2451,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2335 | } | 2451 | } |
| 2336 | } | 2452 | } |
| 2337 | 2453 | ||
| 2338 | rc = validate_and_copy_iov(ses->server, | 2454 | rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), |
| 2339 | le16_to_cpu(rsp->OutputBufferOffset), | ||
| 2340 | le32_to_cpu(rsp->OutputBufferLength), | 2455 | le32_to_cpu(rsp->OutputBufferLength), |
| 2341 | &rsp_iov, min_len, *data); | 2456 | &rsp_iov, min_len, *data); |
| 2342 | 2457 | ||
| @@ -2407,7 +2522,7 @@ smb2_echo_callback(struct mid_q_entry *mid) | |||
| 2407 | unsigned int credits_received = 1; | 2522 | unsigned int credits_received = 1; |
| 2408 | 2523 | ||
| 2409 | if (mid->mid_state == MID_RESPONSE_RECEIVED) | 2524 | if (mid->mid_state == MID_RESPONSE_RECEIVED) |
| 2410 | credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest); | 2525 | credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
| 2411 | 2526 | ||
| 2412 | DeleteMidQEntry(mid); | 2527 | DeleteMidQEntry(mid); |
| 2413 | add_credits(server, credits_received, CIFS_ECHO_OP); | 2528 | add_credits(server, credits_received, CIFS_ECHO_OP); |
| @@ -2536,7 +2651,7 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2536 | if (rc) | 2651 | if (rc) |
| 2537 | return rc; | 2652 | return rc; |
| 2538 | 2653 | ||
| 2539 | if (encryption_required(tcon)) | 2654 | if (smb3_encryption_required(tcon)) |
| 2540 | flags |= CIFS_TRANSFORM_REQ; | 2655 | flags |= CIFS_TRANSFORM_REQ; |
| 2541 | 2656 | ||
| 2542 | req->PersistentFileId = persistent_fid; | 2657 | req->PersistentFileId = persistent_fid; |
| @@ -2548,8 +2663,11 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 2548 | rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); | 2663 | rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov); |
| 2549 | cifs_small_buf_release(req); | 2664 | cifs_small_buf_release(req); |
| 2550 | 2665 | ||
| 2551 | if (rc != 0) | 2666 | if (rc != 0) { |
| 2552 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); | 2667 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); |
| 2668 | trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, | ||
| 2669 | rc); | ||
| 2670 | } | ||
| 2553 | 2671 | ||
| 2554 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | 2672 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
| 2555 | return rc; | 2673 | return rc; |
| @@ -2658,11 +2776,12 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
| 2658 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | 2776 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
| 2659 | struct TCP_Server_Info *server = tcon->ses->server; | 2777 | struct TCP_Server_Info *server = tcon->ses->server; |
| 2660 | struct smb2_sync_hdr *shdr = | 2778 | struct smb2_sync_hdr *shdr = |
| 2661 | (struct smb2_sync_hdr *)rdata->iov[1].iov_base; | 2779 | (struct smb2_sync_hdr *)rdata->iov[0].iov_base; |
| 2662 | unsigned int credits_received = 1; | 2780 | unsigned int credits_received = 1; |
| 2663 | struct smb_rqst rqst = { .rq_iov = rdata->iov, | 2781 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
| 2664 | .rq_nvec = 2, | 2782 | .rq_nvec = 2, |
| 2665 | .rq_pages = rdata->pages, | 2783 | .rq_pages = rdata->pages, |
| 2784 | .rq_offset = rdata->page_offset, | ||
| 2666 | .rq_npages = rdata->nr_pages, | 2785 | .rq_npages = rdata->nr_pages, |
| 2667 | .rq_pagesz = rdata->pagesz, | 2786 | .rq_pagesz = rdata->pagesz, |
| 2668 | .rq_tailsz = rdata->tailsz }; | 2787 | .rq_tailsz = rdata->tailsz }; |
| @@ -2760,7 +2879,7 @@ smb2_async_readv(struct cifs_readdata *rdata) | |||
| 2760 | return rc; | 2879 | return rc; |
| 2761 | } | 2880 | } |
| 2762 | 2881 | ||
| 2763 | if (encryption_required(io_parms.tcon)) | 2882 | if (smb3_encryption_required(io_parms.tcon)) |
| 2764 | flags |= CIFS_TRANSFORM_REQ; | 2883 | flags |= CIFS_TRANSFORM_REQ; |
| 2765 | 2884 | ||
| 2766 | req_len = cpu_to_be32(total_len); | 2885 | req_len = cpu_to_be32(total_len); |
| @@ -2791,7 +2910,13 @@ smb2_async_readv(struct cifs_readdata *rdata) | |||
| 2791 | if (rc) { | 2910 | if (rc) { |
| 2792 | kref_put(&rdata->refcount, cifs_readdata_release); | 2911 | kref_put(&rdata->refcount, cifs_readdata_release); |
| 2793 | cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); | 2912 | cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); |
| 2794 | } | 2913 | trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid, |
| 2914 | io_parms.tcon->tid, io_parms.tcon->ses->Suid, | ||
| 2915 | io_parms.offset, io_parms.length); | ||
| 2916 | } else | ||
| 2917 | trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid, | ||
| 2918 | io_parms.tcon->tid, io_parms.tcon->ses->Suid, | ||
| 2919 | io_parms.offset, io_parms.length); | ||
| 2795 | 2920 | ||
| 2796 | cifs_small_buf_release(buf); | 2921 | cifs_small_buf_release(buf); |
| 2797 | return rc; | 2922 | return rc; |
| @@ -2804,7 +2929,6 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 2804 | int resp_buftype, rc = -EACCES; | 2929 | int resp_buftype, rc = -EACCES; |
| 2805 | struct smb2_read_plain_req *req = NULL; | 2930 | struct smb2_read_plain_req *req = NULL; |
| 2806 | struct smb2_read_rsp *rsp = NULL; | 2931 | struct smb2_read_rsp *rsp = NULL; |
| 2807 | struct smb2_sync_hdr *shdr; | ||
| 2808 | struct kvec iov[1]; | 2932 | struct kvec iov[1]; |
| 2809 | struct kvec rsp_iov; | 2933 | struct kvec rsp_iov; |
| 2810 | unsigned int total_len; | 2934 | unsigned int total_len; |
| @@ -2816,7 +2940,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 2816 | if (rc) | 2940 | if (rc) |
| 2817 | return rc; | 2941 | return rc; |
| 2818 | 2942 | ||
| 2819 | if (encryption_required(io_parms->tcon)) | 2943 | if (smb3_encryption_required(io_parms->tcon)) |
| 2820 | flags |= CIFS_TRANSFORM_REQ; | 2944 | flags |= CIFS_TRANSFORM_REQ; |
| 2821 | 2945 | ||
| 2822 | iov[0].iov_base = (char *)req; | 2946 | iov[0].iov_base = (char *)req; |
| @@ -2832,9 +2956,15 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 2832 | cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); | 2956 | cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); |
| 2833 | cifs_dbg(VFS, "Send error in read = %d\n", rc); | 2957 | cifs_dbg(VFS, "Send error in read = %d\n", rc); |
| 2834 | } | 2958 | } |
| 2959 | trace_smb3_read_err(rc, xid, req->PersistentFileId, | ||
| 2960 | io_parms->tcon->tid, ses->Suid, | ||
| 2961 | io_parms->offset, io_parms->length); | ||
| 2835 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | 2962 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
| 2836 | return rc == -ENODATA ? 0 : rc; | 2963 | return rc == -ENODATA ? 0 : rc; |
| 2837 | } | 2964 | } else |
| 2965 | trace_smb3_read_done(xid, req->PersistentFileId, | ||
| 2966 | io_parms->tcon->tid, ses->Suid, | ||
| 2967 | io_parms->offset, io_parms->length); | ||
| 2838 | 2968 | ||
| 2839 | *nbytes = le32_to_cpu(rsp->DataLength); | 2969 | *nbytes = le32_to_cpu(rsp->DataLength); |
| 2840 | if ((*nbytes > CIFS_MAX_MSGSIZE) || | 2970 | if ((*nbytes > CIFS_MAX_MSGSIZE) || |
| @@ -2845,10 +2975,8 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 2845 | *nbytes = 0; | 2975 | *nbytes = 0; |
| 2846 | } | 2976 | } |
| 2847 | 2977 | ||
| 2848 | shdr = get_sync_hdr(rsp); | ||
| 2849 | |||
| 2850 | if (*buf) { | 2978 | if (*buf) { |
| 2851 | memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes); | 2979 | memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes); |
| 2852 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | 2980 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
| 2853 | } else if (resp_buftype != CIFS_NO_BUFFER) { | 2981 | } else if (resp_buftype != CIFS_NO_BUFFER) { |
| 2854 | *buf = rsp_iov.iov_base; | 2982 | *buf = rsp_iov.iov_base; |
| @@ -2875,7 +3003,7 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 2875 | 3003 | ||
| 2876 | switch (mid->mid_state) { | 3004 | switch (mid->mid_state) { |
| 2877 | case MID_RESPONSE_RECEIVED: | 3005 | case MID_RESPONSE_RECEIVED: |
| 2878 | credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest); | 3006 | credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
| 2879 | wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); | 3007 | wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); |
| 2880 | if (wdata->result != 0) | 3008 | if (wdata->result != 0) |
| 2881 | break; | 3009 | break; |
| @@ -2952,7 +3080,7 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
| 2952 | goto async_writev_out; | 3080 | goto async_writev_out; |
| 2953 | } | 3081 | } |
| 2954 | 3082 | ||
| 2955 | if (encryption_required(tcon)) | 3083 | if (smb3_encryption_required(tcon)) |
| 2956 | flags |= CIFS_TRANSFORM_REQ; | 3084 | flags |= CIFS_TRANSFORM_REQ; |
| 2957 | 3085 | ||
| 2958 | shdr = (struct smb2_sync_hdr *)req; | 3086 | shdr = (struct smb2_sync_hdr *)req; |
| @@ -3013,6 +3141,7 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
| 3013 | rqst.rq_iov = iov; | 3141 | rqst.rq_iov = iov; |
| 3014 | rqst.rq_nvec = 2; | 3142 | rqst.rq_nvec = 2; |
| 3015 | rqst.rq_pages = wdata->pages; | 3143 | rqst.rq_pages = wdata->pages; |
| 3144 | rqst.rq_offset = wdata->page_offset; | ||
| 3016 | rqst.rq_npages = wdata->nr_pages; | 3145 | rqst.rq_npages = wdata->nr_pages; |
| 3017 | rqst.rq_pagesz = wdata->pagesz; | 3146 | rqst.rq_pagesz = wdata->pagesz; |
| 3018 | rqst.rq_tailsz = wdata->tailsz; | 3147 | rqst.rq_tailsz = wdata->tailsz; |
| @@ -3050,9 +3179,15 @@ smb2_async_writev(struct cifs_writedata *wdata, | |||
| 3050 | wdata, flags); | 3179 | wdata, flags); |
| 3051 | 3180 | ||
| 3052 | if (rc) { | 3181 | if (rc) { |
| 3182 | trace_smb3_write_err(0 /* no xid */, req->PersistentFileId, | ||
| 3183 | tcon->tid, tcon->ses->Suid, wdata->offset, | ||
| 3184 | wdata->bytes, rc); | ||
| 3053 | kref_put(&wdata->refcount, release); | 3185 | kref_put(&wdata->refcount, release); |
| 3054 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | 3186 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
| 3055 | } | 3187 | } else |
| 3188 | trace_smb3_write_done(0 /* no xid */, req->PersistentFileId, | ||
| 3189 | tcon->tid, tcon->ses->Suid, wdata->offset, | ||
| 3190 | wdata->bytes); | ||
| 3056 | 3191 | ||
| 3057 | async_writev_out: | 3192 | async_writev_out: |
| 3058 | cifs_small_buf_release(req); | 3193 | cifs_small_buf_release(req); |
| @@ -3090,7 +3225,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 3090 | if (io_parms->tcon->ses->server == NULL) | 3225 | if (io_parms->tcon->ses->server == NULL) |
| 3091 | return -ECONNABORTED; | 3226 | return -ECONNABORTED; |
| 3092 | 3227 | ||
| 3093 | if (encryption_required(io_parms->tcon)) | 3228 | if (smb3_encryption_required(io_parms->tcon)) |
| 3094 | flags |= CIFS_TRANSFORM_REQ; | 3229 | flags |= CIFS_TRANSFORM_REQ; |
| 3095 | 3230 | ||
| 3096 | req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid); | 3231 | req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid); |
| @@ -3116,10 +3251,19 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 3116 | rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; | 3251 | rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; |
| 3117 | 3252 | ||
| 3118 | if (rc) { | 3253 | if (rc) { |
| 3254 | trace_smb3_write_err(xid, req->PersistentFileId, | ||
| 3255 | io_parms->tcon->tid, | ||
| 3256 | io_parms->tcon->ses->Suid, | ||
| 3257 | io_parms->offset, io_parms->length, rc); | ||
| 3119 | cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); | 3258 | cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); |
| 3120 | cifs_dbg(VFS, "Send error in write = %d\n", rc); | 3259 | cifs_dbg(VFS, "Send error in write = %d\n", rc); |
| 3121 | } else | 3260 | } else { |
| 3122 | *nbytes = le32_to_cpu(rsp->DataLength); | 3261 | *nbytes = le32_to_cpu(rsp->DataLength); |
| 3262 | trace_smb3_write_done(xid, req->PersistentFileId, | ||
| 3263 | io_parms->tcon->tid, | ||
| 3264 | io_parms->tcon->ses->Suid, | ||
| 3265 | io_parms->offset, *nbytes); | ||
| 3266 | } | ||
| 3123 | 3267 | ||
| 3124 | free_rsp_buf(resp_buftype, rsp); | 3268 | free_rsp_buf(resp_buftype, rsp); |
| 3125 | return rc; | 3269 | return rc; |
| @@ -3200,7 +3344,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3200 | if (rc) | 3344 | if (rc) |
| 3201 | return rc; | 3345 | return rc; |
| 3202 | 3346 | ||
| 3203 | if (encryption_required(tcon)) | 3347 | if (smb3_encryption_required(tcon)) |
| 3204 | flags |= CIFS_TRANSFORM_REQ; | 3348 | flags |= CIFS_TRANSFORM_REQ; |
| 3205 | 3349 | ||
| 3206 | switch (srch_inf->info_level) { | 3350 | switch (srch_inf->info_level) { |
| @@ -3251,7 +3395,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3251 | 3395 | ||
| 3252 | if (rc) { | 3396 | if (rc) { |
| 3253 | if (rc == -ENODATA && | 3397 | if (rc == -ENODATA && |
| 3254 | rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) { | 3398 | rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { |
| 3255 | srch_inf->endOfSearch = true; | 3399 | srch_inf->endOfSearch = true; |
| 3256 | rc = 0; | 3400 | rc = 0; |
| 3257 | } | 3401 | } |
| @@ -3259,8 +3403,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3259 | goto qdir_exit; | 3403 | goto qdir_exit; |
| 3260 | } | 3404 | } |
| 3261 | 3405 | ||
| 3262 | rc = validate_iov(server, | 3406 | rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset), |
| 3263 | le16_to_cpu(rsp->OutputBufferOffset), | ||
| 3264 | le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, | 3407 | le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, |
| 3265 | info_buf_size); | 3408 | info_buf_size); |
| 3266 | if (rc) | 3409 | if (rc) |
| @@ -3275,10 +3418,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3275 | cifs_buf_release(srch_inf->ntwrk_buf_start); | 3418 | cifs_buf_release(srch_inf->ntwrk_buf_start); |
| 3276 | } | 3419 | } |
| 3277 | srch_inf->ntwrk_buf_start = (char *)rsp; | 3420 | srch_inf->ntwrk_buf_start = (char *)rsp; |
| 3278 | srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ + | 3421 | srch_inf->srch_entries_start = srch_inf->last_entry = |
| 3279 | (char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset); | 3422 | (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset); |
| 3280 | /* 4 for rfc1002 length field */ | 3423 | end_of_smb = rsp_iov.iov_len + (char *)rsp; |
| 3281 | end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr; | ||
| 3282 | srch_inf->entries_in_buffer = | 3424 | srch_inf->entries_in_buffer = |
| 3283 | num_entries(srch_inf->srch_entries_start, end_of_smb, | 3425 | num_entries(srch_inf->srch_entries_start, end_of_smb, |
| 3284 | &srch_inf->last_entry, info_buf_size); | 3426 | &srch_inf->last_entry, info_buf_size); |
| @@ -3333,7 +3475,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3333 | return rc; | 3475 | return rc; |
| 3334 | } | 3476 | } |
| 3335 | 3477 | ||
| 3336 | if (encryption_required(tcon)) | 3478 | if (smb3_encryption_required(tcon)) |
| 3337 | flags |= CIFS_TRANSFORM_REQ; | 3479 | flags |= CIFS_TRANSFORM_REQ; |
| 3338 | 3480 | ||
| 3339 | req->sync_hdr.ProcessId = cpu_to_le32(pid); | 3481 | req->sync_hdr.ProcessId = cpu_to_le32(pid); |
| @@ -3366,8 +3508,11 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3366 | cifs_small_buf_release(req); | 3508 | cifs_small_buf_release(req); |
| 3367 | rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; | 3509 | rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; |
| 3368 | 3510 | ||
| 3369 | if (rc != 0) | 3511 | if (rc != 0) { |
| 3370 | cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); | 3512 | cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); |
| 3513 | trace_smb3_set_info_err(xid, persistent_fid, tcon->tid, | ||
| 3514 | ses->Suid, info_class, (__u32)info_type, rc); | ||
| 3515 | } | ||
| 3371 | 3516 | ||
| 3372 | free_rsp_buf(resp_buftype, rsp); | 3517 | free_rsp_buf(resp_buftype, rsp); |
| 3373 | kfree(iov); | 3518 | kfree(iov); |
| @@ -3514,7 +3659,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3514 | __u8 oplock_level) | 3659 | __u8 oplock_level) |
| 3515 | { | 3660 | { |
| 3516 | int rc; | 3661 | int rc; |
| 3517 | struct smb2_oplock_break_req *req = NULL; | 3662 | struct smb2_oplock_break *req = NULL; |
| 3518 | struct cifs_ses *ses = tcon->ses; | 3663 | struct cifs_ses *ses = tcon->ses; |
| 3519 | int flags = CIFS_OBREAK_OP; | 3664 | int flags = CIFS_OBREAK_OP; |
| 3520 | unsigned int total_len; | 3665 | unsigned int total_len; |
| @@ -3528,7 +3673,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3528 | if (rc) | 3673 | if (rc) |
| 3529 | return rc; | 3674 | return rc; |
| 3530 | 3675 | ||
| 3531 | if (encryption_required(tcon)) | 3676 | if (smb3_encryption_required(tcon)) |
| 3532 | flags |= CIFS_TRANSFORM_REQ; | 3677 | flags |= CIFS_TRANSFORM_REQ; |
| 3533 | 3678 | ||
| 3534 | req->VolatileFid = volatile_fid; | 3679 | req->VolatileFid = volatile_fid; |
| @@ -3593,7 +3738,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, | |||
| 3593 | req->InputBufferOffset = | 3738 | req->InputBufferOffset = |
| 3594 | cpu_to_le16(sizeof(struct smb2_query_info_req) - 1); | 3739 | cpu_to_le16(sizeof(struct smb2_query_info_req) - 1); |
| 3595 | req->OutputBufferLength = cpu_to_le32( | 3740 | req->OutputBufferLength = cpu_to_le32( |
| 3596 | outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size); | 3741 | outbuf_len + sizeof(struct smb2_query_info_rsp) - 1); |
| 3597 | 3742 | ||
| 3598 | iov->iov_base = (char *)req; | 3743 | iov->iov_base = (char *)req; |
| 3599 | iov->iov_len = total_len; | 3744 | iov->iov_len = total_len; |
| @@ -3610,7 +3755,6 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3610 | int rc = 0; | 3755 | int rc = 0; |
| 3611 | int resp_buftype; | 3756 | int resp_buftype; |
| 3612 | struct cifs_ses *ses = tcon->ses; | 3757 | struct cifs_ses *ses = tcon->ses; |
| 3613 | struct TCP_Server_Info *server = ses->server; | ||
| 3614 | struct smb2_fs_full_size_info *info = NULL; | 3758 | struct smb2_fs_full_size_info *info = NULL; |
| 3615 | int flags = 0; | 3759 | int flags = 0; |
| 3616 | 3760 | ||
| @@ -3620,7 +3764,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3620 | if (rc) | 3764 | if (rc) |
| 3621 | return rc; | 3765 | return rc; |
| 3622 | 3766 | ||
| 3623 | if (encryption_required(tcon)) | 3767 | if (smb3_encryption_required(tcon)) |
| 3624 | flags |= CIFS_TRANSFORM_REQ; | 3768 | flags |= CIFS_TRANSFORM_REQ; |
| 3625 | 3769 | ||
| 3626 | rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); | 3770 | rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); |
| @@ -3631,10 +3775,9 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3631 | } | 3775 | } |
| 3632 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; | 3776 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
| 3633 | 3777 | ||
| 3634 | info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size + | 3778 | info = (struct smb2_fs_full_size_info *)( |
| 3635 | le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr); | 3779 | le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp); |
| 3636 | rc = validate_iov(server, | 3780 | rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset), |
| 3637 | le16_to_cpu(rsp->OutputBufferOffset), | ||
| 3638 | le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, | 3781 | le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, |
| 3639 | sizeof(struct smb2_fs_full_size_info)); | 3782 | sizeof(struct smb2_fs_full_size_info)); |
| 3640 | if (!rc) | 3783 | if (!rc) |
| @@ -3655,7 +3798,6 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3655 | int rc = 0; | 3798 | int rc = 0; |
| 3656 | int resp_buftype, max_len, min_len; | 3799 | int resp_buftype, max_len, min_len; |
| 3657 | struct cifs_ses *ses = tcon->ses; | 3800 | struct cifs_ses *ses = tcon->ses; |
| 3658 | struct TCP_Server_Info *server = ses->server; | ||
| 3659 | unsigned int rsp_len, offset; | 3801 | unsigned int rsp_len, offset; |
| 3660 | int flags = 0; | 3802 | int flags = 0; |
| 3661 | 3803 | ||
| @@ -3678,7 +3820,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3678 | if (rc) | 3820 | if (rc) |
| 3679 | return rc; | 3821 | return rc; |
| 3680 | 3822 | ||
| 3681 | if (encryption_required(tcon)) | 3823 | if (smb3_encryption_required(tcon)) |
| 3682 | flags |= CIFS_TRANSFORM_REQ; | 3824 | flags |= CIFS_TRANSFORM_REQ; |
| 3683 | 3825 | ||
| 3684 | rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); | 3826 | rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov); |
| @@ -3691,20 +3833,20 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3691 | 3833 | ||
| 3692 | rsp_len = le32_to_cpu(rsp->OutputBufferLength); | 3834 | rsp_len = le32_to_cpu(rsp->OutputBufferLength); |
| 3693 | offset = le16_to_cpu(rsp->OutputBufferOffset); | 3835 | offset = le16_to_cpu(rsp->OutputBufferOffset); |
| 3694 | rc = validate_iov(server, offset, rsp_len, &rsp_iov, min_len); | 3836 | rc = validate_iov(offset, rsp_len, &rsp_iov, min_len); |
| 3695 | if (rc) | 3837 | if (rc) |
| 3696 | goto qfsattr_exit; | 3838 | goto qfsattr_exit; |
| 3697 | 3839 | ||
| 3698 | if (level == FS_ATTRIBUTE_INFORMATION) | 3840 | if (level == FS_ATTRIBUTE_INFORMATION) |
| 3699 | memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset | 3841 | memcpy(&tcon->fsAttrInfo, offset |
| 3700 | + (char *)&rsp->hdr, min_t(unsigned int, | 3842 | + (char *)rsp, min_t(unsigned int, |
| 3701 | rsp_len, max_len)); | 3843 | rsp_len, max_len)); |
| 3702 | else if (level == FS_DEVICE_INFORMATION) | 3844 | else if (level == FS_DEVICE_INFORMATION) |
| 3703 | memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset | 3845 | memcpy(&tcon->fsDevInfo, offset |
| 3704 | + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO)); | 3846 | + (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO)); |
| 3705 | else if (level == FS_SECTOR_SIZE_INFORMATION) { | 3847 | else if (level == FS_SECTOR_SIZE_INFORMATION) { |
| 3706 | struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *) | 3848 | struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *) |
| 3707 | (server->vals->header_preamble_size + offset + (char *)&rsp->hdr); | 3849 | (offset + (char *)rsp); |
| 3708 | tcon->ss_flags = le32_to_cpu(ss_info->Flags); | 3850 | tcon->ss_flags = le32_to_cpu(ss_info->Flags); |
| 3709 | tcon->perf_sector_size = | 3851 | tcon->perf_sector_size = |
| 3710 | le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); | 3852 | le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); |
| @@ -3735,7 +3877,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3735 | if (rc) | 3877 | if (rc) |
| 3736 | return rc; | 3878 | return rc; |
| 3737 | 3879 | ||
| 3738 | if (encryption_required(tcon)) | 3880 | if (smb3_encryption_required(tcon)) |
| 3739 | flags |= CIFS_TRANSFORM_REQ; | 3881 | flags |= CIFS_TRANSFORM_REQ; |
| 3740 | 3882 | ||
| 3741 | req->sync_hdr.ProcessId = cpu_to_le32(pid); | 3883 | req->sync_hdr.ProcessId = cpu_to_le32(pid); |
| @@ -3758,6 +3900,8 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3758 | if (rc) { | 3900 | if (rc) { |
| 3759 | cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc); | 3901 | cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc); |
| 3760 | cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); | 3902 | cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); |
| 3903 | trace_smb3_lock_err(xid, persist_fid, tcon->tid, | ||
| 3904 | tcon->ses->Suid, rc); | ||
| 3761 | } | 3905 | } |
| 3762 | 3906 | ||
| 3763 | return rc; | 3907 | return rc; |
| @@ -3799,7 +3943,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 3799 | if (rc) | 3943 | if (rc) |
| 3800 | return rc; | 3944 | return rc; |
| 3801 | 3945 | ||
| 3802 | if (encryption_required(tcon)) | 3946 | if (smb3_encryption_required(tcon)) |
| 3803 | flags |= CIFS_TRANSFORM_REQ; | 3947 | flags |= CIFS_TRANSFORM_REQ; |
| 3804 | 3948 | ||
| 3805 | req->sync_hdr.CreditRequest = cpu_to_le16(1); | 3949 | req->sync_hdr.CreditRequest = cpu_to_le16(1); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index d28f358022c5..a345560001ce 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
| @@ -122,25 +122,10 @@ struct smb2_sync_pdu { | |||
| 122 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ | 122 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ |
| 123 | } __packed; | 123 | } __packed; |
| 124 | 124 | ||
| 125 | struct smb2_hdr { | ||
| 126 | __be32 smb2_buf_length; /* big endian on wire */ | ||
| 127 | /* length is only two or three bytes - with */ | ||
| 128 | /* one or two byte type preceding it that MBZ */ | ||
| 129 | struct smb2_sync_hdr sync_hdr; | ||
| 130 | } __packed; | ||
| 131 | |||
| 132 | struct smb2_pdu { | ||
| 133 | struct smb2_hdr hdr; | ||
| 134 | __le16 StructureSize2; /* size of wct area (varies, request specific) */ | ||
| 135 | } __packed; | ||
| 136 | |||
| 137 | #define SMB3_AES128CMM_NONCE 11 | 125 | #define SMB3_AES128CMM_NONCE 11 |
| 138 | #define SMB3_AES128GCM_NONCE 12 | 126 | #define SMB3_AES128GCM_NONCE 12 |
| 139 | 127 | ||
| 140 | struct smb2_transform_hdr { | 128 | struct smb2_transform_hdr { |
| 141 | __be32 smb2_buf_length; /* big endian on wire */ | ||
| 142 | /* length is only two or three bytes - with | ||
| 143 | one or two byte type preceding it that MBZ */ | ||
| 144 | __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ | 129 | __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ |
| 145 | __u8 Signature[16]; | 130 | __u8 Signature[16]; |
| 146 | __u8 Nonce[16]; | 131 | __u8 Nonce[16]; |
| @@ -171,7 +156,7 @@ struct smb2_transform_hdr { | |||
| 171 | #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9) | 156 | #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9) |
| 172 | 157 | ||
| 173 | struct smb2_err_rsp { | 158 | struct smb2_err_rsp { |
| 174 | struct smb2_hdr hdr; | 159 | struct smb2_sync_hdr sync_hdr; |
| 175 | __le16 StructureSize; | 160 | __le16 StructureSize; |
| 176 | __le16 Reserved; /* MBZ */ | 161 | __le16 Reserved; /* MBZ */ |
| 177 | __le32 ByteCount; /* even if zero, at least one byte follows */ | 162 | __le32 ByteCount; /* even if zero, at least one byte follows */ |
| @@ -300,8 +285,16 @@ struct smb2_encryption_neg_context { | |||
| 300 | __le16 Ciphers[1]; /* Ciphers[0] since only one used now */ | 285 | __le16 Ciphers[1]; /* Ciphers[0] since only one used now */ |
| 301 | } __packed; | 286 | } __packed; |
| 302 | 287 | ||
| 288 | #define POSIX_CTXT_DATA_LEN 8 | ||
| 289 | struct smb2_posix_neg_context { | ||
| 290 | __le16 ContextType; /* 0x100 */ | ||
| 291 | __le16 DataLength; | ||
| 292 | __le32 Reserved; | ||
| 293 | __le64 Reserved1; /* In case needed for future (eg version or caps) */ | ||
| 294 | } __packed; | ||
| 295 | |||
| 303 | struct smb2_negotiate_rsp { | 296 | struct smb2_negotiate_rsp { |
| 304 | struct smb2_hdr hdr; | 297 | struct smb2_sync_hdr sync_hdr; |
| 305 | __le16 StructureSize; /* Must be 65 */ | 298 | __le16 StructureSize; /* Must be 65 */ |
| 306 | __le16 SecurityMode; | 299 | __le16 SecurityMode; |
| 307 | __le16 DialectRevision; | 300 | __le16 DialectRevision; |
| @@ -341,7 +334,7 @@ struct smb2_sess_setup_req { | |||
| 341 | #define SMB2_SESSION_FLAG_IS_NULL 0x0002 | 334 | #define SMB2_SESSION_FLAG_IS_NULL 0x0002 |
| 342 | #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004 | 335 | #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004 |
| 343 | struct smb2_sess_setup_rsp { | 336 | struct smb2_sess_setup_rsp { |
| 344 | struct smb2_hdr hdr; | 337 | struct smb2_sync_hdr sync_hdr; |
| 345 | __le16 StructureSize; /* Must be 9 */ | 338 | __le16 StructureSize; /* Must be 9 */ |
| 346 | __le16 SessionFlags; | 339 | __le16 SessionFlags; |
| 347 | __le16 SecurityBufferOffset; | 340 | __le16 SecurityBufferOffset; |
| @@ -356,7 +349,7 @@ struct smb2_logoff_req { | |||
| 356 | } __packed; | 349 | } __packed; |
| 357 | 350 | ||
| 358 | struct smb2_logoff_rsp { | 351 | struct smb2_logoff_rsp { |
| 359 | struct smb2_hdr hdr; | 352 | struct smb2_sync_hdr sync_hdr; |
| 360 | __le16 StructureSize; /* Must be 4 */ | 353 | __le16 StructureSize; /* Must be 4 */ |
| 361 | __le16 Reserved; | 354 | __le16 Reserved; |
| 362 | } __packed; | 355 | } __packed; |
| @@ -452,7 +445,7 @@ struct smb2_tree_connect_req_extension { | |||
| 452 | } __packed; | 445 | } __packed; |
| 453 | 446 | ||
| 454 | struct smb2_tree_connect_rsp { | 447 | struct smb2_tree_connect_rsp { |
| 455 | struct smb2_hdr hdr; | 448 | struct smb2_sync_hdr sync_hdr; |
| 456 | __le16 StructureSize; /* Must be 16 */ | 449 | __le16 StructureSize; /* Must be 16 */ |
| 457 | __u8 ShareType; /* see below */ | 450 | __u8 ShareType; /* see below */ |
| 458 | __u8 Reserved; | 451 | __u8 Reserved; |
| @@ -503,7 +496,7 @@ struct smb2_tree_disconnect_req { | |||
| 503 | } __packed; | 496 | } __packed; |
| 504 | 497 | ||
| 505 | struct smb2_tree_disconnect_rsp { | 498 | struct smb2_tree_disconnect_rsp { |
| 506 | struct smb2_hdr hdr; | 499 | struct smb2_sync_hdr sync_hdr; |
| 507 | __le16 StructureSize; /* Must be 4 */ | 500 | __le16 StructureSize; /* Must be 4 */ |
| 508 | __le16 Reserved; | 501 | __le16 Reserved; |
| 509 | } __packed; | 502 | } __packed; |
| @@ -615,7 +608,9 @@ struct smb2_tree_disconnect_rsp { | |||
| 615 | #define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q" | 608 | #define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q" |
| 616 | #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C" | 609 | #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C" |
| 617 | #define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74 | 610 | #define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74 |
| 618 | #define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9 | 611 | #define SVHDX_OPEN_DEVICE_CONTEX 0x9CCBCF9E04C1E643980E158DA1F6EC83 |
| 612 | #define SMB2_CREATE_TAG_POSIX 0x93AD25509CB411E7B42383DE968BCD7C | ||
| 613 | |||
| 619 | 614 | ||
| 620 | struct smb2_create_req { | 615 | struct smb2_create_req { |
| 621 | struct smb2_sync_hdr sync_hdr; | 616 | struct smb2_sync_hdr sync_hdr; |
| @@ -638,7 +633,7 @@ struct smb2_create_req { | |||
| 638 | } __packed; | 633 | } __packed; |
| 639 | 634 | ||
| 640 | struct smb2_create_rsp { | 635 | struct smb2_create_rsp { |
| 641 | struct smb2_hdr hdr; | 636 | struct smb2_sync_hdr sync_hdr; |
| 642 | __le16 StructureSize; /* Must be 89 */ | 637 | __le16 StructureSize; /* Must be 89 */ |
| 643 | __u8 OplockLevel; | 638 | __u8 OplockLevel; |
| 644 | __u8 Reserved; | 639 | __u8 Reserved; |
| @@ -727,6 +722,13 @@ struct create_durable { | |||
| 727 | } Data; | 722 | } Data; |
| 728 | } __packed; | 723 | } __packed; |
| 729 | 724 | ||
| 725 | struct create_posix { | ||
| 726 | struct create_context ccontext; | ||
| 727 | __u8 Name[16]; | ||
| 728 | __le32 Mode; | ||
| 729 | __u32 Reserved; | ||
| 730 | } __packed; | ||
| 731 | |||
| 730 | /* See MS-SMB2 2.2.13.2.11 */ | 732 | /* See MS-SMB2 2.2.13.2.11 */ |
| 731 | /* Flags */ | 733 | /* Flags */ |
| 732 | #define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002 | 734 | #define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002 |
| @@ -894,7 +896,7 @@ struct smb2_ioctl_req { | |||
| 894 | } __packed; | 896 | } __packed; |
| 895 | 897 | ||
| 896 | struct smb2_ioctl_rsp { | 898 | struct smb2_ioctl_rsp { |
| 897 | struct smb2_hdr hdr; | 899 | struct smb2_sync_hdr sync_hdr; |
| 898 | __le16 StructureSize; /* Must be 57 */ | 900 | __le16 StructureSize; /* Must be 57 */ |
| 899 | __u16 Reserved; | 901 | __u16 Reserved; |
| 900 | __le32 CtlCode; | 902 | __le32 CtlCode; |
| @@ -921,7 +923,7 @@ struct smb2_close_req { | |||
| 921 | } __packed; | 923 | } __packed; |
| 922 | 924 | ||
| 923 | struct smb2_close_rsp { | 925 | struct smb2_close_rsp { |
| 924 | struct smb2_hdr hdr; | 926 | struct smb2_sync_hdr sync_hdr; |
| 925 | __le16 StructureSize; /* 60 */ | 927 | __le16 StructureSize; /* 60 */ |
| 926 | __le16 Flags; | 928 | __le16 Flags; |
| 927 | __le32 Reserved; | 929 | __le32 Reserved; |
| @@ -944,7 +946,7 @@ struct smb2_flush_req { | |||
| 944 | } __packed; | 946 | } __packed; |
| 945 | 947 | ||
| 946 | struct smb2_flush_rsp { | 948 | struct smb2_flush_rsp { |
| 947 | struct smb2_hdr hdr; | 949 | struct smb2_sync_hdr sync_hdr; |
| 948 | __le16 StructureSize; | 950 | __le16 StructureSize; |
| 949 | __le16 Reserved; | 951 | __le16 Reserved; |
| 950 | } __packed; | 952 | } __packed; |
| @@ -976,7 +978,7 @@ struct smb2_read_plain_req { | |||
| 976 | } __packed; | 978 | } __packed; |
| 977 | 979 | ||
| 978 | struct smb2_read_rsp { | 980 | struct smb2_read_rsp { |
| 979 | struct smb2_hdr hdr; | 981 | struct smb2_sync_hdr sync_hdr; |
| 980 | __le16 StructureSize; /* Must be 17 */ | 982 | __le16 StructureSize; /* Must be 17 */ |
| 981 | __u8 DataOffset; | 983 | __u8 DataOffset; |
| 982 | __u8 Reserved; | 984 | __u8 Reserved; |
| @@ -1007,7 +1009,7 @@ struct smb2_write_req { | |||
| 1007 | } __packed; | 1009 | } __packed; |
| 1008 | 1010 | ||
| 1009 | struct smb2_write_rsp { | 1011 | struct smb2_write_rsp { |
| 1010 | struct smb2_hdr hdr; | 1012 | struct smb2_sync_hdr sync_hdr; |
| 1011 | __le16 StructureSize; /* Must be 17 */ | 1013 | __le16 StructureSize; /* Must be 17 */ |
| 1012 | __u8 DataOffset; | 1014 | __u8 DataOffset; |
| 1013 | __u8 Reserved; | 1015 | __u8 Reserved; |
| @@ -1041,7 +1043,7 @@ struct smb2_lock_req { | |||
| 1041 | } __packed; | 1043 | } __packed; |
| 1042 | 1044 | ||
| 1043 | struct smb2_lock_rsp { | 1045 | struct smb2_lock_rsp { |
| 1044 | struct smb2_hdr hdr; | 1046 | struct smb2_sync_hdr sync_hdr; |
| 1045 | __le16 StructureSize; /* Must be 4 */ | 1047 | __le16 StructureSize; /* Must be 4 */ |
| 1046 | __le16 Reserved; | 1048 | __le16 Reserved; |
| 1047 | } __packed; | 1049 | } __packed; |
| @@ -1053,7 +1055,7 @@ struct smb2_echo_req { | |||
| 1053 | } __packed; | 1055 | } __packed; |
| 1054 | 1056 | ||
| 1055 | struct smb2_echo_rsp { | 1057 | struct smb2_echo_rsp { |
| 1056 | struct smb2_hdr hdr; | 1058 | struct smb2_sync_hdr sync_hdr; |
| 1057 | __le16 StructureSize; /* Must be 4 */ | 1059 | __le16 StructureSize; /* Must be 4 */ |
| 1058 | __u16 Reserved; | 1060 | __u16 Reserved; |
| 1059 | } __packed; | 1061 | } __packed; |
| @@ -1079,7 +1081,7 @@ struct smb2_query_directory_req { | |||
| 1079 | } __packed; | 1081 | } __packed; |
| 1080 | 1082 | ||
| 1081 | struct smb2_query_directory_rsp { | 1083 | struct smb2_query_directory_rsp { |
| 1082 | struct smb2_hdr hdr; | 1084 | struct smb2_sync_hdr sync_hdr; |
| 1083 | __le16 StructureSize; /* Must be 9 */ | 1085 | __le16 StructureSize; /* Must be 9 */ |
| 1084 | __le16 OutputBufferOffset; | 1086 | __le16 OutputBufferOffset; |
| 1085 | __le32 OutputBufferLength; | 1087 | __le32 OutputBufferLength; |
| @@ -1128,7 +1130,7 @@ struct smb2_query_info_req { | |||
| 1128 | } __packed; | 1130 | } __packed; |
| 1129 | 1131 | ||
| 1130 | struct smb2_query_info_rsp { | 1132 | struct smb2_query_info_rsp { |
| 1131 | struct smb2_hdr hdr; | 1133 | struct smb2_sync_hdr sync_hdr; |
| 1132 | __le16 StructureSize; /* Must be 9 */ | 1134 | __le16 StructureSize; /* Must be 9 */ |
| 1133 | __le16 OutputBufferOffset; | 1135 | __le16 OutputBufferOffset; |
| 1134 | __le32 OutputBufferLength; | 1136 | __le32 OutputBufferLength; |
| @@ -1150,12 +1152,11 @@ struct smb2_set_info_req { | |||
| 1150 | } __packed; | 1152 | } __packed; |
| 1151 | 1153 | ||
| 1152 | struct smb2_set_info_rsp { | 1154 | struct smb2_set_info_rsp { |
| 1153 | struct smb2_hdr hdr; | 1155 | struct smb2_sync_hdr sync_hdr; |
| 1154 | __le16 StructureSize; /* Must be 2 */ | 1156 | __le16 StructureSize; /* Must be 2 */ |
| 1155 | } __packed; | 1157 | } __packed; |
| 1156 | 1158 | ||
| 1157 | /* oplock break without an rfc1002 header */ | 1159 | struct smb2_oplock_break { |
| 1158 | struct smb2_oplock_break_req { | ||
| 1159 | struct smb2_sync_hdr sync_hdr; | 1160 | struct smb2_sync_hdr sync_hdr; |
| 1160 | __le16 StructureSize; /* Must be 24 */ | 1161 | __le16 StructureSize; /* Must be 24 */ |
| 1161 | __u8 OplockLevel; | 1162 | __u8 OplockLevel; |
| @@ -1165,21 +1166,10 @@ struct smb2_oplock_break_req { | |||
| 1165 | __u64 VolatileFid; | 1166 | __u64 VolatileFid; |
| 1166 | } __packed; | 1167 | } __packed; |
| 1167 | 1168 | ||
| 1168 | /* oplock break with an rfc1002 header */ | ||
| 1169 | struct smb2_oplock_break_rsp { | ||
| 1170 | struct smb2_hdr hdr; | ||
| 1171 | __le16 StructureSize; /* Must be 24 */ | ||
| 1172 | __u8 OplockLevel; | ||
| 1173 | __u8 Reserved; | ||
| 1174 | __le32 Reserved2; | ||
| 1175 | __u64 PersistentFid; | ||
| 1176 | __u64 VolatileFid; | ||
| 1177 | } __packed; | ||
| 1178 | |||
| 1179 | #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01) | 1169 | #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01) |
| 1180 | 1170 | ||
| 1181 | struct smb2_lease_break { | 1171 | struct smb2_lease_break { |
| 1182 | struct smb2_hdr hdr; | 1172 | struct smb2_sync_hdr sync_hdr; |
| 1183 | __le16 StructureSize; /* Must be 44 */ | 1173 | __le16 StructureSize; /* Must be 44 */ |
| 1184 | __le16 Reserved; | 1174 | __le16 Reserved; |
| 1185 | __le32 Flags; | 1175 | __le32 Flags; |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 8ba24a95db71..908555b1c6b5 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
| @@ -36,8 +36,9 @@ struct smb_rqst; | |||
| 36 | extern int map_smb2_to_linux_error(char *buf, bool log_err); | 36 | extern int map_smb2_to_linux_error(char *buf, bool log_err); |
| 37 | extern int smb2_check_message(char *buf, unsigned int length, | 37 | extern int smb2_check_message(char *buf, unsigned int length, |
| 38 | struct TCP_Server_Info *server); | 38 | struct TCP_Server_Info *server); |
| 39 | extern unsigned int smb2_calc_size(void *buf); | 39 | extern unsigned int smb2_calc_size(void *buf, struct TCP_Server_Info *server); |
| 40 | extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr); | 40 | extern char *smb2_get_data_area_len(int *off, int *len, |
| 41 | struct smb2_sync_hdr *shdr); | ||
| 41 | extern __le16 *cifs_convert_path_to_utf16(const char *from, | 42 | extern __le16 *cifs_convert_path_to_utf16(const char *from, |
| 42 | struct cifs_sb_info *cifs_sb); | 43 | struct cifs_sb_info *cifs_sb); |
| 43 | 44 | ||
| @@ -65,6 +66,8 @@ extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, | |||
| 65 | extern int smb3_handle_read_data(struct TCP_Server_Info *server, | 66 | extern int smb3_handle_read_data(struct TCP_Server_Info *server, |
| 66 | struct mid_q_entry *mid); | 67 | struct mid_q_entry *mid); |
| 67 | 68 | ||
| 69 | extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon, | ||
| 70 | struct cifs_fid *pfid); | ||
| 68 | extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, | 71 | extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, |
| 69 | struct smb2_file_all_info *src); | 72 | struct smb2_file_all_info *src); |
| 70 | extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | 73 | extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, |
| @@ -129,6 +132,8 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 129 | char **out_data, u32 *plen /* returned data len */); | 132 | char **out_data, u32 *plen /* returned data len */); |
| 130 | extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | 133 | extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
| 131 | u64 persistent_file_id, u64 volatile_file_id); | 134 | u64 persistent_file_id, u64 volatile_file_id); |
| 135 | extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, | ||
| 136 | u64 persistent_fid, u64 volatile_fid, int flags); | ||
| 132 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, | 137 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, |
| 133 | u64 persistent_file_id, u64 volatile_file_id); | 138 | u64 persistent_file_id, u64 volatile_file_id); |
| 134 | extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | 139 | extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 8806f3f76c1d..2c671123a6bf 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
| @@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
| 480 | unsigned int rc; | 480 | unsigned int rc; |
| 481 | char server_response_sig[16]; | 481 | char server_response_sig[16]; |
| 482 | struct smb2_sync_hdr *shdr = | 482 | struct smb2_sync_hdr *shdr = |
| 483 | (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; | 483 | (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; |
| 484 | 484 | ||
| 485 | if ((shdr->Command == SMB2_NEGOTIATE) || | 485 | if ((shdr->Command == SMB2_NEGOTIATE) || |
| 486 | (shdr->Command == SMB2_SESSION_SETUP) || | 486 | (shdr->Command == SMB2_SESSION_SETUP) || |
| @@ -605,14 +605,12 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
| 605 | bool log_error) | 605 | bool log_error) |
| 606 | { | 606 | { |
| 607 | unsigned int len = mid->resp_buf_size; | 607 | unsigned int len = mid->resp_buf_size; |
| 608 | struct kvec iov[2]; | 608 | struct kvec iov[1]; |
| 609 | struct smb_rqst rqst = { .rq_iov = iov, | 609 | struct smb_rqst rqst = { .rq_iov = iov, |
| 610 | .rq_nvec = 2 }; | 610 | .rq_nvec = 1 }; |
| 611 | 611 | ||
| 612 | iov[0].iov_base = (char *)mid->resp_buf; | 612 | iov[0].iov_base = (char *)mid->resp_buf; |
| 613 | iov[0].iov_len = 4; | 613 | iov[0].iov_len = len; |
| 614 | iov[1].iov_base = (char *)mid->resp_buf + 4; | ||
| 615 | iov[1].iov_len = len; | ||
| 616 | 614 | ||
| 617 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); | 615 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); |
| 618 | /* convert the length into a more usable form */ | 616 | /* convert the length into a more usable form */ |
diff --git a/fs/cifs/trace.c b/fs/cifs/trace.c new file mode 100644 index 000000000000..bd4a546feec1 --- /dev/null +++ b/fs/cifs/trace.c | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2018, Microsoft Corporation. | ||
| 4 | * | ||
| 5 | * Author(s): Steve French <stfrench@microsoft.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
| 15 | * the GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | #define CREATE_TRACE_POINTS | ||
| 18 | #include "trace.h" | ||
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h new file mode 100644 index 000000000000..61e74d455d90 --- /dev/null +++ b/fs/cifs/trace.h | |||
| @@ -0,0 +1,429 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2018, Microsoft Corporation. | ||
| 4 | * | ||
| 5 | * Author(s): Steve French <stfrench@microsoft.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
| 15 | * the GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | #undef TRACE_SYSTEM | ||
| 18 | #define TRACE_SYSTEM cifs | ||
| 19 | |||
| 20 | #if !defined(_CIFS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
| 21 | #define _CIFS_TRACE_H | ||
| 22 | |||
| 23 | #include <linux/tracepoint.h> | ||
| 24 | |||
| 25 | /* For logging errors in read or write */ | ||
| 26 | DECLARE_EVENT_CLASS(smb3_rw_err_class, | ||
| 27 | TP_PROTO(unsigned int xid, | ||
| 28 | __u64 fid, | ||
| 29 | __u32 tid, | ||
| 30 | __u64 sesid, | ||
| 31 | __u64 offset, | ||
| 32 | __u32 len, | ||
| 33 | int rc), | ||
| 34 | TP_ARGS(xid, fid, tid, sesid, offset, len, rc), | ||
| 35 | TP_STRUCT__entry( | ||
| 36 | __field(unsigned int, xid) | ||
| 37 | __field(__u64, fid) | ||
| 38 | __field(__u32, tid) | ||
| 39 | __field(__u64, sesid) | ||
| 40 | __field(__u64, offset) | ||
| 41 | __field(__u32, len) | ||
| 42 | __field(int, rc) | ||
| 43 | ), | ||
| 44 | TP_fast_assign( | ||
| 45 | __entry->xid = xid; | ||
| 46 | __entry->fid = fid; | ||
| 47 | __entry->tid = tid; | ||
| 48 | __entry->sesid = sesid; | ||
| 49 | __entry->offset = offset; | ||
| 50 | __entry->len = len; | ||
| 51 | __entry->rc = rc; | ||
| 52 | ), | ||
| 53 | TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", | ||
| 54 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||
| 55 | __entry->offset, __entry->len, __entry->rc) | ||
| 56 | ) | ||
| 57 | |||
| 58 | #define DEFINE_SMB3_RW_ERR_EVENT(name) \ | ||
| 59 | DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \ | ||
| 60 | TP_PROTO(unsigned int xid, \ | ||
| 61 | __u64 fid, \ | ||
| 62 | __u32 tid, \ | ||
| 63 | __u64 sesid, \ | ||
| 64 | __u64 offset, \ | ||
| 65 | __u32 len, \ | ||
| 66 | int rc), \ | ||
| 67 | TP_ARGS(xid, fid, tid, sesid, offset, len, rc)) | ||
| 68 | |||
| 69 | DEFINE_SMB3_RW_ERR_EVENT(write_err); | ||
| 70 | DEFINE_SMB3_RW_ERR_EVENT(read_err); | ||
| 71 | |||
| 72 | |||
| 73 | /* For logging successful read or write */ | ||
| 74 | DECLARE_EVENT_CLASS(smb3_rw_done_class, | ||
| 75 | TP_PROTO(unsigned int xid, | ||
| 76 | __u64 fid, | ||
| 77 | __u32 tid, | ||
| 78 | __u64 sesid, | ||
| 79 | __u64 offset, | ||
| 80 | __u32 len), | ||
| 81 | TP_ARGS(xid, fid, tid, sesid, offset, len), | ||
| 82 | TP_STRUCT__entry( | ||
| 83 | __field(unsigned int, xid) | ||
| 84 | __field(__u64, fid) | ||
| 85 | __field(__u32, tid) | ||
| 86 | __field(__u64, sesid) | ||
| 87 | __field(__u64, offset) | ||
| 88 | __field(__u32, len) | ||
| 89 | ), | ||
| 90 | TP_fast_assign( | ||
| 91 | __entry->xid = xid; | ||
| 92 | __entry->fid = fid; | ||
| 93 | __entry->tid = tid; | ||
| 94 | __entry->sesid = sesid; | ||
| 95 | __entry->offset = offset; | ||
| 96 | __entry->len = len; | ||
| 97 | ), | ||
| 98 | TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x", | ||
| 99 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||
| 100 | __entry->offset, __entry->len) | ||
| 101 | ) | ||
| 102 | |||
| 103 | #define DEFINE_SMB3_RW_DONE_EVENT(name) \ | ||
| 104 | DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \ | ||
| 105 | TP_PROTO(unsigned int xid, \ | ||
| 106 | __u64 fid, \ | ||
| 107 | __u32 tid, \ | ||
| 108 | __u64 sesid, \ | ||
| 109 | __u64 offset, \ | ||
| 110 | __u32 len), \ | ||
| 111 | TP_ARGS(xid, fid, tid, sesid, offset, len)) | ||
| 112 | |||
| 113 | DEFINE_SMB3_RW_DONE_EVENT(write_done); | ||
| 114 | DEFINE_SMB3_RW_DONE_EVENT(read_done); | ||
| 115 | |||
| 116 | /* | ||
| 117 | * For handle based calls other than read and write, and get/set info | ||
| 118 | */ | ||
| 119 | DECLARE_EVENT_CLASS(smb3_fd_err_class, | ||
| 120 | TP_PROTO(unsigned int xid, | ||
| 121 | __u64 fid, | ||
| 122 | __u32 tid, | ||
| 123 | __u64 sesid, | ||
| 124 | int rc), | ||
| 125 | TP_ARGS(xid, fid, tid, sesid, rc), | ||
| 126 | TP_STRUCT__entry( | ||
| 127 | __field(unsigned int, xid) | ||
| 128 | __field(__u64, fid) | ||
| 129 | __field(__u32, tid) | ||
| 130 | __field(__u64, sesid) | ||
| 131 | __field(int, rc) | ||
| 132 | ), | ||
| 133 | TP_fast_assign( | ||
| 134 | __entry->xid = xid; | ||
| 135 | __entry->fid = fid; | ||
| 136 | __entry->tid = tid; | ||
| 137 | __entry->sesid = sesid; | ||
| 138 | __entry->rc = rc; | ||
| 139 | ), | ||
| 140 | TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d", | ||
| 141 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||
| 142 | __entry->rc) | ||
| 143 | ) | ||
| 144 | |||
| 145 | #define DEFINE_SMB3_FD_ERR_EVENT(name) \ | ||
| 146 | DEFINE_EVENT(smb3_fd_err_class, smb3_##name, \ | ||
| 147 | TP_PROTO(unsigned int xid, \ | ||
| 148 | __u64 fid, \ | ||
| 149 | __u32 tid, \ | ||
| 150 | __u64 sesid, \ | ||
| 151 | int rc), \ | ||
| 152 | TP_ARGS(xid, fid, tid, sesid, rc)) | ||
| 153 | |||
| 154 | DEFINE_SMB3_FD_ERR_EVENT(flush_err); | ||
| 155 | DEFINE_SMB3_FD_ERR_EVENT(lock_err); | ||
| 156 | DEFINE_SMB3_FD_ERR_EVENT(close_err); | ||
| 157 | |||
| 158 | /* | ||
| 159 | * For handle based query/set info calls | ||
| 160 | */ | ||
| 161 | DECLARE_EVENT_CLASS(smb3_inf_err_class, | ||
| 162 | TP_PROTO(unsigned int xid, | ||
| 163 | __u64 fid, | ||
| 164 | __u32 tid, | ||
| 165 | __u64 sesid, | ||
| 166 | __u8 infclass, | ||
| 167 | __u32 type, | ||
| 168 | int rc), | ||
| 169 | TP_ARGS(xid, fid, tid, sesid, infclass, type, rc), | ||
| 170 | TP_STRUCT__entry( | ||
| 171 | __field(unsigned int, xid) | ||
| 172 | __field(__u64, fid) | ||
| 173 | __field(__u32, tid) | ||
| 174 | __field(__u64, sesid) | ||
| 175 | __field(__u8, infclass) | ||
| 176 | __field(__u32, type) | ||
| 177 | __field(int, rc) | ||
| 178 | ), | ||
| 179 | TP_fast_assign( | ||
| 180 | __entry->xid = xid; | ||
| 181 | __entry->fid = fid; | ||
| 182 | __entry->tid = tid; | ||
| 183 | __entry->sesid = sesid; | ||
| 184 | __entry->infclass = infclass; | ||
| 185 | __entry->type = type; | ||
| 186 | __entry->rc = rc; | ||
| 187 | ), | ||
| 188 | TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x rc=%d", | ||
| 189 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||
| 190 | __entry->infclass, __entry->type, __entry->rc) | ||
| 191 | ) | ||
| 192 | |||
| 193 | #define DEFINE_SMB3_INF_ERR_EVENT(name) \ | ||
| 194 | DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \ | ||
| 195 | TP_PROTO(unsigned int xid, \ | ||
| 196 | __u64 fid, \ | ||
| 197 | __u32 tid, \ | ||
| 198 | __u64 sesid, \ | ||
| 199 | __u8 infclass, \ | ||
| 200 | __u32 type, \ | ||
| 201 | int rc), \ | ||
| 202 | TP_ARGS(xid, fid, tid, sesid, infclass, type, rc)) | ||
| 203 | |||
| 204 | DEFINE_SMB3_INF_ERR_EVENT(query_info_err); | ||
| 205 | DEFINE_SMB3_INF_ERR_EVENT(set_info_err); | ||
| 206 | DEFINE_SMB3_INF_ERR_EVENT(fsctl_err); | ||
| 207 | |||
| 208 | /* | ||
| 209 | * For logging SMB3 Status code and Command for responses which return errors | ||
| 210 | */ | ||
| 211 | DECLARE_EVENT_CLASS(smb3_cmd_err_class, | ||
| 212 | TP_PROTO(__u32 tid, | ||
| 213 | __u64 sesid, | ||
| 214 | __u16 cmd, | ||
| 215 | __u64 mid, | ||
| 216 | __u32 status, | ||
| 217 | int rc), | ||
| 218 | TP_ARGS(tid, sesid, cmd, mid, status, rc), | ||
| 219 | TP_STRUCT__entry( | ||
| 220 | __field(__u32, tid) | ||
| 221 | __field(__u64, sesid) | ||
| 222 | __field(__u16, cmd) | ||
| 223 | __field(__u64, mid) | ||
| 224 | __field(__u32, status) | ||
| 225 | __field(int, rc) | ||
| 226 | ), | ||
| 227 | TP_fast_assign( | ||
| 228 | __entry->tid = tid; | ||
| 229 | __entry->sesid = sesid; | ||
| 230 | __entry->cmd = cmd; | ||
| 231 | __entry->mid = mid; | ||
| 232 | __entry->status = status; | ||
| 233 | __entry->rc = rc; | ||
| 234 | ), | ||
| 235 | TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d", | ||
| 236 | __entry->sesid, __entry->tid, __entry->cmd, __entry->mid, | ||
| 237 | __entry->status, __entry->rc) | ||
| 238 | ) | ||
| 239 | |||
| 240 | #define DEFINE_SMB3_CMD_ERR_EVENT(name) \ | ||
| 241 | DEFINE_EVENT(smb3_cmd_err_class, smb3_##name, \ | ||
| 242 | TP_PROTO(__u32 tid, \ | ||
| 243 | __u64 sesid, \ | ||
| 244 | __u16 cmd, \ | ||
| 245 | __u64 mid, \ | ||
| 246 | __u32 status, \ | ||
| 247 | int rc), \ | ||
| 248 | TP_ARGS(tid, sesid, cmd, mid, status, rc)) | ||
| 249 | |||
| 250 | DEFINE_SMB3_CMD_ERR_EVENT(cmd_err); | ||
| 251 | |||
| 252 | DECLARE_EVENT_CLASS(smb3_cmd_done_class, | ||
| 253 | TP_PROTO(__u32 tid, | ||
| 254 | __u64 sesid, | ||
| 255 | __u16 cmd, | ||
| 256 | __u64 mid), | ||
| 257 | TP_ARGS(tid, sesid, cmd, mid), | ||
| 258 | TP_STRUCT__entry( | ||
| 259 | __field(__u32, tid) | ||
| 260 | __field(__u64, sesid) | ||
| 261 | __field(__u16, cmd) | ||
| 262 | __field(__u64, mid) | ||
| 263 | ), | ||
| 264 | TP_fast_assign( | ||
| 265 | __entry->tid = tid; | ||
| 266 | __entry->sesid = sesid; | ||
| 267 | __entry->cmd = cmd; | ||
| 268 | __entry->mid = mid; | ||
| 269 | ), | ||
| 270 | TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu", | ||
| 271 | __entry->sesid, __entry->tid, | ||
| 272 | __entry->cmd, __entry->mid) | ||
| 273 | ) | ||
| 274 | |||
| 275 | #define DEFINE_SMB3_CMD_DONE_EVENT(name) \ | ||
| 276 | DEFINE_EVENT(smb3_cmd_done_class, smb3_##name, \ | ||
| 277 | TP_PROTO(__u32 tid, \ | ||
| 278 | __u64 sesid, \ | ||
| 279 | __u16 cmd, \ | ||
| 280 | __u64 mid), \ | ||
| 281 | TP_ARGS(tid, sesid, cmd, mid)) | ||
| 282 | |||
| 283 | DEFINE_SMB3_CMD_DONE_EVENT(cmd_done); | ||
| 284 | |||
| 285 | DECLARE_EVENT_CLASS(smb3_exit_err_class, | ||
| 286 | TP_PROTO(unsigned int xid, | ||
| 287 | const char *func_name, | ||
| 288 | int rc), | ||
| 289 | TP_ARGS(xid, func_name, rc), | ||
| 290 | TP_STRUCT__entry( | ||
| 291 | __field(unsigned int, xid) | ||
| 292 | __field(const char *, func_name) | ||
| 293 | __field(int, rc) | ||
| 294 | ), | ||
| 295 | TP_fast_assign( | ||
| 296 | __entry->xid = xid; | ||
| 297 | __entry->func_name = func_name; | ||
| 298 | __entry->rc = rc; | ||
| 299 | ), | ||
| 300 | TP_printk("\t%s: xid=%u rc=%d", | ||
| 301 | __entry->func_name, __entry->xid, __entry->rc) | ||
| 302 | ) | ||
| 303 | |||
| 304 | #define DEFINE_SMB3_EXIT_ERR_EVENT(name) \ | ||
| 305 | DEFINE_EVENT(smb3_exit_err_class, smb3_##name, \ | ||
| 306 | TP_PROTO(unsigned int xid, \ | ||
| 307 | const char *func_name, \ | ||
| 308 | int rc), \ | ||
| 309 | TP_ARGS(xid, func_name, rc)) | ||
| 310 | |||
| 311 | DEFINE_SMB3_EXIT_ERR_EVENT(exit_err); | ||
| 312 | |||
| 313 | DECLARE_EVENT_CLASS(smb3_enter_exit_class, | ||
| 314 | TP_PROTO(unsigned int xid, | ||
| 315 | const char *func_name), | ||
| 316 | TP_ARGS(xid, func_name), | ||
| 317 | TP_STRUCT__entry( | ||
| 318 | __field(unsigned int, xid) | ||
| 319 | __field(const char *, func_name) | ||
| 320 | ), | ||
| 321 | TP_fast_assign( | ||
| 322 | __entry->xid = xid; | ||
| 323 | __entry->func_name = func_name; | ||
| 324 | ), | ||
| 325 | TP_printk("\t%s: xid=%u", | ||
| 326 | __entry->func_name, __entry->xid) | ||
| 327 | ) | ||
| 328 | |||
| 329 | #define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \ | ||
| 330 | DEFINE_EVENT(smb3_enter_exit_class, smb3_##name, \ | ||
| 331 | TP_PROTO(unsigned int xid, \ | ||
| 332 | const char *func_name), \ | ||
| 333 | TP_ARGS(xid, func_name)) | ||
| 334 | |||
| 335 | DEFINE_SMB3_ENTER_EXIT_EVENT(enter); | ||
| 336 | DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done); | ||
| 337 | |||
| 338 | /* | ||
| 339 | * For smb2/smb3 open call | ||
| 340 | */ | ||
| 341 | DECLARE_EVENT_CLASS(smb3_open_err_class, | ||
| 342 | TP_PROTO(unsigned int xid, | ||
| 343 | __u32 tid, | ||
| 344 | __u64 sesid, | ||
| 345 | int create_options, | ||
| 346 | int desired_access, | ||
| 347 | int rc), | ||
| 348 | TP_ARGS(xid, tid, sesid, create_options, desired_access, rc), | ||
| 349 | TP_STRUCT__entry( | ||
| 350 | __field(unsigned int, xid) | ||
| 351 | __field(__u32, tid) | ||
| 352 | __field(__u64, sesid) | ||
| 353 | __field(int, create_options) | ||
| 354 | __field(int, desired_access) | ||
| 355 | __field(int, rc) | ||
| 356 | ), | ||
| 357 | TP_fast_assign( | ||
| 358 | __entry->xid = xid; | ||
| 359 | __entry->tid = tid; | ||
| 360 | __entry->sesid = sesid; | ||
| 361 | __entry->create_options = create_options; | ||
| 362 | __entry->desired_access = desired_access; | ||
| 363 | __entry->rc = rc; | ||
| 364 | ), | ||
| 365 | TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x rc=%d", | ||
| 366 | __entry->xid, __entry->sesid, __entry->tid, | ||
| 367 | __entry->create_options, __entry->desired_access, __entry->rc) | ||
| 368 | ) | ||
| 369 | |||
| 370 | #define DEFINE_SMB3_OPEN_ERR_EVENT(name) \ | ||
| 371 | DEFINE_EVENT(smb3_open_err_class, smb3_##name, \ | ||
| 372 | TP_PROTO(unsigned int xid, \ | ||
| 373 | __u32 tid, \ | ||
| 374 | __u64 sesid, \ | ||
| 375 | int create_options, \ | ||
| 376 | int desired_access, \ | ||
| 377 | int rc), \ | ||
| 378 | TP_ARGS(xid, tid, sesid, create_options, desired_access, rc)) | ||
| 379 | |||
| 380 | DEFINE_SMB3_OPEN_ERR_EVENT(open_err); | ||
| 381 | |||
| 382 | |||
| 383 | DECLARE_EVENT_CLASS(smb3_open_done_class, | ||
| 384 | TP_PROTO(unsigned int xid, | ||
| 385 | __u64 fid, | ||
| 386 | __u32 tid, | ||
| 387 | __u64 sesid, | ||
| 388 | int create_options, | ||
| 389 | int desired_access), | ||
| 390 | TP_ARGS(xid, fid, tid, sesid, create_options, desired_access), | ||
| 391 | TP_STRUCT__entry( | ||
| 392 | __field(unsigned int, xid) | ||
| 393 | __field(__u64, fid) | ||
| 394 | __field(__u32, tid) | ||
| 395 | __field(__u64, sesid) | ||
| 396 | __field(int, create_options) | ||
| 397 | __field(int, desired_access) | ||
| 398 | ), | ||
| 399 | TP_fast_assign( | ||
| 400 | __entry->xid = xid; | ||
| 401 | __entry->fid = fid; | ||
| 402 | __entry->tid = tid; | ||
| 403 | __entry->sesid = sesid; | ||
| 404 | __entry->create_options = create_options; | ||
| 405 | __entry->desired_access = desired_access; | ||
| 406 | ), | ||
| 407 | TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx cr_opts=0x%x des_access=0x%x", | ||
| 408 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||
| 409 | __entry->create_options, __entry->desired_access) | ||
| 410 | ) | ||
| 411 | |||
| 412 | #define DEFINE_SMB3_OPEN_DONE_EVENT(name) \ | ||
| 413 | DEFINE_EVENT(smb3_open_done_class, smb3_##name, \ | ||
| 414 | TP_PROTO(unsigned int xid, \ | ||
| 415 | __u64 fid, \ | ||
| 416 | __u32 tid, \ | ||
| 417 | __u64 sesid, \ | ||
| 418 | int create_options, \ | ||
| 419 | int desired_access), \ | ||
| 420 | TP_ARGS(xid, fid, tid, sesid, create_options, desired_access)) | ||
| 421 | |||
| 422 | DEFINE_SMB3_OPEN_DONE_EVENT(open_done); | ||
| 423 | |||
| 424 | #endif /* _CIFS_TRACE_H */ | ||
| 425 | |||
| 426 | #undef TRACE_INCLUDE_PATH | ||
| 427 | #define TRACE_INCLUDE_PATH . | ||
| 428 | #define TRACE_INCLUDE_FILE trace | ||
| 429 | #include <trace/define_trace.h> | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 927226a2122f..e7254e386b79 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -800,8 +800,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, | |||
| 800 | #ifdef CONFIG_CIFS_SMB311 | 800 | #ifdef CONFIG_CIFS_SMB311 |
| 801 | if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { | 801 | if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { |
| 802 | struct kvec iov = { | 802 | struct kvec iov = { |
| 803 | .iov_base = buf + 4, | 803 | .iov_base = buf, |
| 804 | .iov_len = get_rfc1002_length(buf) | 804 | .iov_len = midQ->resp_buf_size |
| 805 | }; | 805 | }; |
| 806 | smb311_update_preauth_hash(ses, &iov, 1); | 806 | smb311_update_preauth_hash(ses, &iov, 1); |
| 807 | } | 807 | } |
