diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-24 15:31:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-24 15:31:12 -0500 |
commit | 772950ed21c36f4157ff34e7d10fb61975f64558 (patch) | |
tree | 2d8fbac099a5064d20342ba7cb6e8e9539bf6fb5 /fs | |
parent | 587198ba5206cdf0d30855f7361af950a4172cd6 (diff) | |
parent | 01b9b0b28626db4a47d7f48744d70abca9914ef1 (diff) |
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull SMB3 fixes from Steve French:
"A collection of CIFS/SMB3 fixes.
It includes a couple bug fixes, a few for improved debugging of
cifs.ko and some improvements to the way cifs does key generation.
I do have some additional bug fixes I expect in the next week or two
(to address a problem found by xfstest, and some fixes for SMB3.11
dialect, and a couple patches that just came in yesterday that I am
reviewing)"
* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
cifs_dbg() outputs an uninitialized buffer in cifs_readdir()
cifs: fix race between call_async() and reconnect()
Prepare for encryption support (first part). Add decryption and encryption key generation. Thanks to Metze for helping with this.
cifs: Allow using O_DIRECT with cache=loose
cifs: Make echo interval tunable
cifs: Check uniqueid for SMB2+ and return -ESTALE if necessary
Print IP address of unresponsive server
cifs: Ratelimit kernel log messages
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 9 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 17 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 16 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 36 | ||||
-rw-r--r-- | fs/cifs/inode.c | 24 | ||||
-rw-r--r-- | fs/cifs/misc.c | 2 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 1 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 36 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 13 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 10 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 8 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 3 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 102 | ||||
-rw-r--r-- | fs/cifs/transport.c | 6 |
16 files changed, 238 insertions, 52 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 7febcf2475c5..50b268483302 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -50,7 +50,7 @@ void cifs_vfs_err(const char *fmt, ...) | |||
50 | vaf.fmt = fmt; | 50 | vaf.fmt = fmt; |
51 | vaf.va = &args; | 51 | vaf.va = &args; |
52 | 52 | ||
53 | pr_err("CIFS VFS: %pV", &vaf); | 53 | pr_err_ratelimited("CIFS VFS: %pV", &vaf); |
54 | 54 | ||
55 | va_end(args); | 55 | va_end(args); |
56 | } | 56 | } |
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index f40fbaca1b2a..66cf0f9fff89 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h | |||
@@ -51,14 +51,13 @@ __printf(1, 2) void cifs_vfs_err(const char *fmt, ...); | |||
51 | /* information message: e.g., configuration, major event */ | 51 | /* information message: e.g., configuration, major event */ |
52 | #define cifs_dbg(type, fmt, ...) \ | 52 | #define cifs_dbg(type, fmt, ...) \ |
53 | do { \ | 53 | do { \ |
54 | if (type == FYI) { \ | 54 | if (type == FYI && cifsFYI & CIFS_INFO) { \ |
55 | if (cifsFYI & CIFS_INFO) { \ | 55 | pr_debug_ratelimited("%s: " \ |
56 | pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__); \ | 56 | fmt, __FILE__, ##__VA_ARGS__); \ |
57 | } \ | ||
58 | } else if (type == VFS) { \ | 57 | } else if (type == VFS) { \ |
59 | cifs_vfs_err(fmt, ##__VA_ARGS__); \ | 58 | cifs_vfs_err(fmt, ##__VA_ARGS__); \ |
60 | } else if (type == NOISY && type != 0) { \ | 59 | } else if (type == NOISY && type != 0) { \ |
61 | pr_debug(fmt, ##__VA_ARGS__); \ | 60 | pr_debug_ratelimited(fmt, ##__VA_ARGS__); \ |
62 | } \ | 61 | } \ |
63 | } while (0) | 62 | } while (0) |
64 | 63 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e24ca79b140c..c48ca13673e3 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -507,6 +507,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
507 | 507 | ||
508 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); | 508 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); |
509 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); | 509 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); |
510 | seq_printf(s, ",echo_interval=%lu", | ||
511 | tcon->ses->server->echo_interval / HZ); | ||
510 | /* convert actimeo and display it in seconds */ | 512 | /* convert actimeo and display it in seconds */ |
511 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); | 513 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); |
512 | 514 | ||
@@ -752,6 +754,9 @@ cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter) | |||
752 | ssize_t rc; | 754 | ssize_t rc; |
753 | struct inode *inode = file_inode(iocb->ki_filp); | 755 | struct inode *inode = file_inode(iocb->ki_filp); |
754 | 756 | ||
757 | if (iocb->ki_filp->f_flags & O_DIRECT) | ||
758 | return cifs_user_readv(iocb, iter); | ||
759 | |||
755 | rc = cifs_revalidate_mapping(inode); | 760 | rc = cifs_revalidate_mapping(inode); |
756 | if (rc) | 761 | if (rc) |
757 | return rc; | 762 | return rc; |
@@ -766,6 +771,18 @@ static ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
766 | ssize_t written; | 771 | ssize_t written; |
767 | int rc; | 772 | int rc; |
768 | 773 | ||
774 | if (iocb->ki_filp->f_flags & O_DIRECT) { | ||
775 | written = cifs_user_writev(iocb, from); | ||
776 | if (written > 0 && CIFS_CACHE_READ(cinode)) { | ||
777 | cifs_zap_mapping(inode); | ||
778 | cifs_dbg(FYI, | ||
779 | "Set no oplock for inode=%p after a write operation\n", | ||
780 | inode); | ||
781 | cinode->oplock = 0; | ||
782 | } | ||
783 | return written; | ||
784 | } | ||
785 | |||
769 | written = cifs_get_writer(cinode); | 786 | written = cifs_get_writer(cinode); |
770 | if (written) | 787 | if (written) |
771 | return written; | 788 | return written; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 2b510c537a0d..a25b2513f146 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -70,8 +70,10 @@ | |||
70 | #define SERVER_NAME_LENGTH 40 | 70 | #define SERVER_NAME_LENGTH 40 |
71 | #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) | 71 | #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) |
72 | 72 | ||
73 | /* SMB echo "timeout" -- FIXME: tunable? */ | 73 | /* echo interval in seconds */ |
74 | #define SMB_ECHO_INTERVAL (60 * HZ) | 74 | #define SMB_ECHO_INTERVAL_MIN 1 |
75 | #define SMB_ECHO_INTERVAL_MAX 600 | ||
76 | #define SMB_ECHO_INTERVAL_DEFAULT 60 | ||
75 | 77 | ||
76 | #include "cifspdu.h" | 78 | #include "cifspdu.h" |
77 | 79 | ||
@@ -225,7 +227,7 @@ struct smb_version_operations { | |||
225 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); | 227 | void (*print_stats)(struct seq_file *m, struct cifs_tcon *); |
226 | void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); | 228 | void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); |
227 | /* verify the message */ | 229 | /* verify the message */ |
228 | int (*check_message)(char *, unsigned int); | 230 | int (*check_message)(char *, unsigned int, struct TCP_Server_Info *); |
229 | bool (*is_oplock_break)(char *, struct TCP_Server_Info *); | 231 | bool (*is_oplock_break)(char *, struct TCP_Server_Info *); |
230 | void (*downgrade_oplock)(struct TCP_Server_Info *, | 232 | void (*downgrade_oplock)(struct TCP_Server_Info *, |
231 | struct cifsInodeInfo *, bool); | 233 | struct cifsInodeInfo *, bool); |
@@ -507,6 +509,7 @@ struct smb_vol { | |||
507 | struct sockaddr_storage dstaddr; /* destination address */ | 509 | struct sockaddr_storage dstaddr; /* destination address */ |
508 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ | 510 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ |
509 | struct nls_table *local_nls; | 511 | struct nls_table *local_nls; |
512 | unsigned int echo_interval; /* echo interval in secs */ | ||
510 | }; | 513 | }; |
511 | 514 | ||
512 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ | 515 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ |
@@ -627,7 +630,9 @@ struct TCP_Server_Info { | |||
627 | #ifdef CONFIG_CIFS_SMB2 | 630 | #ifdef CONFIG_CIFS_SMB2 |
628 | unsigned int max_read; | 631 | unsigned int max_read; |
629 | unsigned int max_write; | 632 | unsigned int max_write; |
633 | __u8 preauth_hash[512]; | ||
630 | #endif /* CONFIG_CIFS_SMB2 */ | 634 | #endif /* CONFIG_CIFS_SMB2 */ |
635 | unsigned long echo_interval; | ||
631 | }; | 636 | }; |
632 | 637 | ||
633 | static inline unsigned int | 638 | static inline unsigned int |
@@ -809,7 +814,10 @@ struct cifs_ses { | |||
809 | bool need_reconnect:1; /* connection reset, uid now invalid */ | 814 | bool need_reconnect:1; /* connection reset, uid now invalid */ |
810 | #ifdef CONFIG_CIFS_SMB2 | 815 | #ifdef CONFIG_CIFS_SMB2 |
811 | __u16 session_flags; | 816 | __u16 session_flags; |
812 | char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */ | 817 | __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; |
818 | __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; | ||
819 | __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; | ||
820 | __u8 preauth_hash[512]; | ||
813 | #endif /* CONFIG_CIFS_SMB2 */ | 821 | #endif /* CONFIG_CIFS_SMB2 */ |
814 | }; | 822 | }; |
815 | 823 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c63fd1dde25b..eed7ff50faf0 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -102,7 +102,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid, | |||
102 | struct smb_hdr *out_buf, | 102 | struct smb_hdr *out_buf, |
103 | int *bytes_returned); | 103 | int *bytes_returned); |
104 | extern int cifs_reconnect(struct TCP_Server_Info *server); | 104 | extern int cifs_reconnect(struct TCP_Server_Info *server); |
105 | extern int checkSMB(char *buf, unsigned int length); | 105 | extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr); |
106 | extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); | 106 | extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); |
107 | extern bool backup_cred(struct cifs_sb_info *); | 107 | extern bool backup_cred(struct cifs_sb_info *); |
108 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 108 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
@@ -439,7 +439,8 @@ extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); | |||
439 | extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); | 439 | extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); |
440 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | 440 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); |
441 | extern int calc_seckey(struct cifs_ses *); | 441 | extern int calc_seckey(struct cifs_ses *); |
442 | extern int generate_smb3signingkey(struct cifs_ses *); | 442 | extern int generate_smb30signingkey(struct cifs_ses *); |
443 | extern int generate_smb311signingkey(struct cifs_ses *); | ||
443 | 444 | ||
444 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 445 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
445 | extern int calc_lanman_hash(const char *password, const char *cryptkey, | 446 | extern int calc_lanman_hash(const char *password, const char *cryptkey, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ecb0803bdb0e..4fbd92d2e113 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -95,6 +95,7 @@ enum { | |||
95 | Opt_cruid, Opt_gid, Opt_file_mode, | 95 | Opt_cruid, Opt_gid, Opt_file_mode, |
96 | Opt_dirmode, Opt_port, | 96 | Opt_dirmode, Opt_port, |
97 | Opt_rsize, Opt_wsize, Opt_actimeo, | 97 | Opt_rsize, Opt_wsize, Opt_actimeo, |
98 | Opt_echo_interval, | ||
98 | 99 | ||
99 | /* Mount options which take string value */ | 100 | /* Mount options which take string value */ |
100 | Opt_user, Opt_pass, Opt_ip, | 101 | Opt_user, Opt_pass, Opt_ip, |
@@ -188,6 +189,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
188 | { Opt_rsize, "rsize=%s" }, | 189 | { Opt_rsize, "rsize=%s" }, |
189 | { Opt_wsize, "wsize=%s" }, | 190 | { Opt_wsize, "wsize=%s" }, |
190 | { Opt_actimeo, "actimeo=%s" }, | 191 | { Opt_actimeo, "actimeo=%s" }, |
192 | { Opt_echo_interval, "echo_interval=%s" }, | ||
191 | 193 | ||
192 | { Opt_blank_user, "user=" }, | 194 | { Opt_blank_user, "user=" }, |
193 | { Opt_blank_user, "username=" }, | 195 | { Opt_blank_user, "username=" }, |
@@ -368,7 +370,6 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
368 | server->session_key.response = NULL; | 370 | server->session_key.response = NULL; |
369 | server->session_key.len = 0; | 371 | server->session_key.len = 0; |
370 | server->lstrp = jiffies; | 372 | server->lstrp = jiffies; |
371 | mutex_unlock(&server->srv_mutex); | ||
372 | 373 | ||
373 | /* mark submitted MIDs for retry and issue callback */ | 374 | /* mark submitted MIDs for retry and issue callback */ |
374 | INIT_LIST_HEAD(&retry_list); | 375 | INIT_LIST_HEAD(&retry_list); |
@@ -381,6 +382,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
381 | list_move(&mid_entry->qhead, &retry_list); | 382 | list_move(&mid_entry->qhead, &retry_list); |
382 | } | 383 | } |
383 | spin_unlock(&GlobalMid_Lock); | 384 | spin_unlock(&GlobalMid_Lock); |
385 | mutex_unlock(&server->srv_mutex); | ||
384 | 386 | ||
385 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); | 387 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); |
386 | list_for_each_safe(tmp, tmp2, &retry_list) { | 388 | list_for_each_safe(tmp, tmp2, &retry_list) { |
@@ -418,6 +420,7 @@ cifs_echo_request(struct work_struct *work) | |||
418 | int rc; | 420 | int rc; |
419 | struct TCP_Server_Info *server = container_of(work, | 421 | struct TCP_Server_Info *server = container_of(work, |
420 | struct TCP_Server_Info, echo.work); | 422 | struct TCP_Server_Info, echo.work); |
423 | unsigned long echo_interval = server->echo_interval; | ||
421 | 424 | ||
422 | /* | 425 | /* |
423 | * We cannot send an echo if it is disabled or until the | 426 | * We cannot send an echo if it is disabled or until the |
@@ -427,7 +430,7 @@ cifs_echo_request(struct work_struct *work) | |||
427 | */ | 430 | */ |
428 | if (!server->ops->need_neg || server->ops->need_neg(server) || | 431 | if (!server->ops->need_neg || server->ops->need_neg(server) || |
429 | (server->ops->can_echo && !server->ops->can_echo(server)) || | 432 | (server->ops->can_echo && !server->ops->can_echo(server)) || |
430 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | 433 | time_before(jiffies, server->lstrp + echo_interval - HZ)) |
431 | goto requeue_echo; | 434 | goto requeue_echo; |
432 | 435 | ||
433 | rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; | 436 | rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; |
@@ -436,7 +439,7 @@ cifs_echo_request(struct work_struct *work) | |||
436 | server->hostname); | 439 | server->hostname); |
437 | 440 | ||
438 | requeue_echo: | 441 | requeue_echo: |
439 | queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL); | 442 | queue_delayed_work(cifsiod_wq, &server->echo, echo_interval); |
440 | } | 443 | } |
441 | 444 | ||
442 | static bool | 445 | static bool |
@@ -487,9 +490,9 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
487 | * a response in >60s. | 490 | * a response in >60s. |
488 | */ | 491 | */ |
489 | if (server->tcpStatus == CifsGood && | 492 | if (server->tcpStatus == CifsGood && |
490 | time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) { | 493 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { |
491 | cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n", | 494 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", |
492 | server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ); | 495 | server->hostname, (2 * server->echo_interval) / HZ); |
493 | cifs_reconnect(server); | 496 | cifs_reconnect(server); |
494 | wake_up(&server->response_q); | 497 | wake_up(&server->response_q); |
495 | return true; | 498 | return true; |
@@ -828,7 +831,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
828 | * 48 bytes is enough to display the header and a little bit | 831 | * 48 bytes is enough to display the header and a little bit |
829 | * into the payload for debugging purposes. | 832 | * into the payload for debugging purposes. |
830 | */ | 833 | */ |
831 | length = server->ops->check_message(buf, server->total_read); | 834 | length = server->ops->check_message(buf, server->total_read, server); |
832 | if (length != 0) | 835 | if (length != 0) |
833 | cifs_dump_mem("Bad SMB: ", buf, | 836 | cifs_dump_mem("Bad SMB: ", buf, |
834 | min_t(unsigned int, server->total_read, 48)); | 837 | min_t(unsigned int, server->total_read, 48)); |
@@ -1624,6 +1627,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1624 | goto cifs_parse_mount_err; | 1627 | goto cifs_parse_mount_err; |
1625 | } | 1628 | } |
1626 | break; | 1629 | break; |
1630 | case Opt_echo_interval: | ||
1631 | if (get_option_ul(args, &option)) { | ||
1632 | cifs_dbg(VFS, "%s: Invalid echo interval value\n", | ||
1633 | __func__); | ||
1634 | goto cifs_parse_mount_err; | ||
1635 | } | ||
1636 | vol->echo_interval = option; | ||
1637 | break; | ||
1627 | 1638 | ||
1628 | /* String Arguments */ | 1639 | /* String Arguments */ |
1629 | 1640 | ||
@@ -2089,6 +2100,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2089 | if (!match_security(server, vol)) | 2100 | if (!match_security(server, vol)) |
2090 | return 0; | 2101 | return 0; |
2091 | 2102 | ||
2103 | if (server->echo_interval != vol->echo_interval) | ||
2104 | return 0; | ||
2105 | |||
2092 | return 1; | 2106 | return 1; |
2093 | } | 2107 | } |
2094 | 2108 | ||
@@ -2208,6 +2222,12 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2208 | tcp_ses->tcpStatus = CifsNew; | 2222 | tcp_ses->tcpStatus = CifsNew; |
2209 | ++tcp_ses->srv_count; | 2223 | ++tcp_ses->srv_count; |
2210 | 2224 | ||
2225 | if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN && | ||
2226 | volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX) | ||
2227 | tcp_ses->echo_interval = volume_info->echo_interval * HZ; | ||
2228 | else | ||
2229 | tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; | ||
2230 | |||
2211 | rc = ip_connect(tcp_ses); | 2231 | rc = ip_connect(tcp_ses); |
2212 | if (rc < 0) { | 2232 | if (rc < 0) { |
2213 | cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n"); | 2233 | cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n"); |
@@ -2237,7 +2257,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2237 | cifs_fscache_get_client_cookie(tcp_ses); | 2257 | cifs_fscache_get_client_cookie(tcp_ses); |
2238 | 2258 | ||
2239 | /* queue echo request delayed work */ | 2259 | /* queue echo request delayed work */ |
2240 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); | 2260 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); |
2241 | 2261 | ||
2242 | return tcp_ses; | 2262 | return tcp_ses; |
2243 | 2263 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a329f5ba35aa..aeb26dbfa1bf 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -814,8 +814,21 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
814 | } | 814 | } |
815 | } else | 815 | } else |
816 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 816 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
817 | } else | 817 | } else { |
818 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; | 818 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && |
819 | validinum == false && server->ops->get_srv_inum) { | ||
820 | /* | ||
821 | * Pass a NULL tcon to ensure we don't make a round | ||
822 | * trip to the server. This only works for SMB2+. | ||
823 | */ | ||
824 | tmprc = server->ops->get_srv_inum(xid, | ||
825 | NULL, cifs_sb, full_path, | ||
826 | &fattr.cf_uniqueid, data); | ||
827 | if (tmprc) | ||
828 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; | ||
829 | } else | ||
830 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; | ||
831 | } | ||
819 | 832 | ||
820 | /* query for SFU type info if supported and needed */ | 833 | /* query for SFU type info if supported and needed */ |
821 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && | 834 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
@@ -856,6 +869,13 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
856 | } else { | 869 | } else { |
857 | /* we already have inode, update it */ | 870 | /* we already have inode, update it */ |
858 | 871 | ||
872 | /* if uniqueid is different, return error */ | ||
873 | if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM && | ||
874 | CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) { | ||
875 | rc = -ESTALE; | ||
876 | goto cgii_exit; | ||
877 | } | ||
878 | |||
859 | /* if filetype is different, return error */ | 879 | /* if filetype is different, return error */ |
860 | if (unlikely(((*inode)->i_mode & S_IFMT) != | 880 | if (unlikely(((*inode)->i_mode & S_IFMT) != |
861 | (fattr.cf_mode & S_IFMT))) { | 881 | (fattr.cf_mode & S_IFMT))) { |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 8442b8b8e0be..813fe13c2ae1 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -310,7 +310,7 @@ check_smb_hdr(struct smb_hdr *smb) | |||
310 | } | 310 | } |
311 | 311 | ||
312 | int | 312 | int |
313 | checkSMB(char *buf, unsigned int total_read) | 313 | checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) |
314 | { | 314 | { |
315 | struct smb_hdr *smb = (struct smb_hdr *)buf; | 315 | struct smb_hdr *smb = (struct smb_hdr *)buf; |
316 | __u32 rfclen = be32_to_cpu(smb->smb_buf_length); | 316 | __u32 rfclen = be32_to_cpu(smb->smb_buf_length); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 0557c45e9c33..b30a4a6d98a0 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -847,6 +847,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) | |||
847 | * if buggy server returns . and .. late do we want to | 847 | * if buggy server returns . and .. late do we want to |
848 | * check for that here? | 848 | * check for that here? |
849 | */ | 849 | */ |
850 | *tmp_buf = 0; | ||
850 | rc = cifs_filldir(current_entry, file, ctx, | 851 | rc = cifs_filldir(current_entry, file, ctx, |
851 | tmp_buf, max_len); | 852 | tmp_buf, max_len); |
852 | if (rc) { | 853 | if (rc) { |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 1c5907019045..389fb9f8c84e 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -38,7 +38,7 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
38 | * Make sure that this really is an SMB, that it is a response, | 38 | * Make sure that this really is an SMB, that it is a response, |
39 | * and that the message ids match. | 39 | * and that the message ids match. |
40 | */ | 40 | */ |
41 | if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && | 41 | if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) && |
42 | (mid == wire_mid)) { | 42 | (mid == wire_mid)) { |
43 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) | 43 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
44 | return 0; | 44 | return 0; |
@@ -50,9 +50,9 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
50 | cifs_dbg(VFS, "Received Request not response\n"); | 50 | cifs_dbg(VFS, "Received Request not response\n"); |
51 | } | 51 | } |
52 | } else { /* bad signature or mid */ | 52 | } else { /* bad signature or mid */ |
53 | if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) | 53 | if (hdr->ProtocolId != SMB2_PROTO_NUMBER) |
54 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", | 54 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", |
55 | *(unsigned int *) hdr->ProtocolId); | 55 | le32_to_cpu(hdr->ProtocolId)); |
56 | if (mid != wire_mid) | 56 | if (mid != wire_mid) |
57 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", | 57 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", |
58 | mid, wire_mid); | 58 | mid, wire_mid); |
@@ -93,11 +93,11 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | int | 95 | int |
96 | smb2_check_message(char *buf, unsigned int length) | 96 | smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) |
97 | { | 97 | { |
98 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 98 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
99 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 99 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; |
100 | __u64 mid = le64_to_cpu(hdr->MessageId); | 100 | __u64 mid; |
101 | __u32 len = get_rfc1002_length(buf); | 101 | __u32 len = get_rfc1002_length(buf); |
102 | __u32 clc_len; /* calculated length */ | 102 | __u32 clc_len; /* calculated length */ |
103 | int command; | 103 | int command; |
@@ -111,6 +111,30 @@ smb2_check_message(char *buf, unsigned int length) | |||
111 | * ie Validate the wct via smb2_struct_sizes table above | 111 | * ie Validate the wct via smb2_struct_sizes table above |
112 | */ | 112 | */ |
113 | 113 | ||
114 | if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | ||
115 | struct smb2_transform_hdr *thdr = | ||
116 | (struct smb2_transform_hdr *)buf; | ||
117 | struct cifs_ses *ses = NULL; | ||
118 | struct list_head *tmp; | ||
119 | |||
120 | /* decrypt frame now that it is completely read in */ | ||
121 | spin_lock(&cifs_tcp_ses_lock); | ||
122 | list_for_each(tmp, &srvr->smb_ses_list) { | ||
123 | ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | ||
124 | if (ses->Suid == thdr->SessionId) | ||
125 | break; | ||
126 | |||
127 | ses = NULL; | ||
128 | } | ||
129 | spin_unlock(&cifs_tcp_ses_lock); | ||
130 | if (ses == NULL) { | ||
131 | cifs_dbg(VFS, "no decryption - session id not found\n"); | ||
132 | return 1; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | |||
137 | mid = le64_to_cpu(hdr->MessageId); | ||
114 | if (length < sizeof(struct smb2_pdu)) { | 138 | if (length < sizeof(struct smb2_pdu)) { |
115 | if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { | 139 | if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { |
116 | pdu->StructureSize2 = 0; | 140 | pdu->StructureSize2 = 0; |
@@ -322,7 +346,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) | |||
322 | 346 | ||
323 | /* return pointer to beginning of data area, ie offset from SMB start */ | 347 | /* return pointer to beginning of data area, ie offset from SMB start */ |
324 | if ((*off != 0) && (*len != 0)) | 348 | if ((*off != 0) && (*len != 0)) |
325 | return (char *)(&hdr->ProtocolId[0]) + *off; | 349 | return (char *)(&hdr->ProtocolId) + *off; |
326 | else | 350 | else |
327 | return NULL; | 351 | return NULL; |
328 | } | 352 | } |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 53ccdde6ff18..3525ed756173 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -182,6 +182,11 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
182 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 182 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
183 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | 183 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); |
184 | 184 | ||
185 | if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | ||
186 | cifs_dbg(VFS, "encrypted frame parsing not supported yet"); | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
185 | spin_lock(&GlobalMid_Lock); | 190 | spin_lock(&GlobalMid_Lock); |
186 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { | 191 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
187 | if ((mid->mid == wire_mid) && | 192 | if ((mid->mid == wire_mid) && |
@@ -1692,7 +1697,7 @@ struct smb_version_operations smb30_operations = { | |||
1692 | .get_lease_key = smb2_get_lease_key, | 1697 | .get_lease_key = smb2_get_lease_key, |
1693 | .set_lease_key = smb2_set_lease_key, | 1698 | .set_lease_key = smb2_set_lease_key, |
1694 | .new_lease_key = smb2_new_lease_key, | 1699 | .new_lease_key = smb2_new_lease_key, |
1695 | .generate_signingkey = generate_smb3signingkey, | 1700 | .generate_signingkey = generate_smb30signingkey, |
1696 | .calc_signature = smb3_calc_signature, | 1701 | .calc_signature = smb3_calc_signature, |
1697 | .set_integrity = smb3_set_integrity, | 1702 | .set_integrity = smb3_set_integrity, |
1698 | .is_read_op = smb21_is_read_op, | 1703 | .is_read_op = smb21_is_read_op, |
@@ -1779,7 +1784,7 @@ struct smb_version_operations smb311_operations = { | |||
1779 | .get_lease_key = smb2_get_lease_key, | 1784 | .get_lease_key = smb2_get_lease_key, |
1780 | .set_lease_key = smb2_set_lease_key, | 1785 | .set_lease_key = smb2_set_lease_key, |
1781 | .new_lease_key = smb2_new_lease_key, | 1786 | .new_lease_key = smb2_new_lease_key, |
1782 | .generate_signingkey = generate_smb3signingkey, | 1787 | .generate_signingkey = generate_smb311signingkey, |
1783 | .calc_signature = smb3_calc_signature, | 1788 | .calc_signature = smb3_calc_signature, |
1784 | .set_integrity = smb3_set_integrity, | 1789 | .set_integrity = smb3_set_integrity, |
1785 | .is_read_op = smb21_is_read_op, | 1790 | .is_read_op = smb21_is_read_op, |
@@ -1838,7 +1843,7 @@ struct smb_version_values smb21_values = { | |||
1838 | struct smb_version_values smb30_values = { | 1843 | struct smb_version_values smb30_values = { |
1839 | .version_string = SMB30_VERSION_STRING, | 1844 | .version_string = SMB30_VERSION_STRING, |
1840 | .protocol_id = SMB30_PROT_ID, | 1845 | .protocol_id = SMB30_PROT_ID, |
1841 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, | 1846 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION, |
1842 | .large_lock_type = 0, | 1847 | .large_lock_type = 0, |
1843 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 1848 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
1844 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 1849 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
@@ -1858,7 +1863,7 @@ struct smb_version_values smb30_values = { | |||
1858 | struct smb_version_values smb302_values = { | 1863 | struct smb_version_values smb302_values = { |
1859 | .version_string = SMB302_VERSION_STRING, | 1864 | .version_string = SMB302_VERSION_STRING, |
1860 | .protocol_id = SMB302_PROT_ID, | 1865 | .protocol_id = SMB302_PROT_ID, |
1861 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, | 1866 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION, |
1862 | .large_lock_type = 0, | 1867 | .large_lock_type = 0, |
1863 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 1868 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
1864 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 1869 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 767555518d40..10f8d5cf5681 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -97,10 +97,7 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , | |||
97 | hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr) | 97 | hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr) |
98 | - 4 /* RFC 1001 length field itself not counted */); | 98 | - 4 /* RFC 1001 length field itself not counted */); |
99 | 99 | ||
100 | hdr->ProtocolId[0] = 0xFE; | 100 | hdr->ProtocolId = SMB2_PROTO_NUMBER; |
101 | hdr->ProtocolId[1] = 'S'; | ||
102 | hdr->ProtocolId[2] = 'M'; | ||
103 | hdr->ProtocolId[3] = 'B'; | ||
104 | hdr->StructureSize = cpu_to_le16(64); | 101 | hdr->StructureSize = cpu_to_le16(64); |
105 | hdr->Command = smb2_cmd; | 102 | hdr->Command = smb2_cmd; |
106 | hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */ | 103 | hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */ |
@@ -1573,7 +1570,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1573 | goto ioctl_exit; | 1570 | goto ioctl_exit; |
1574 | } | 1571 | } |
1575 | 1572 | ||
1576 | memcpy(*out_data, rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), | 1573 | memcpy(*out_data, |
1574 | (char *)&rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), | ||
1577 | *plen); | 1575 | *plen); |
1578 | ioctl_exit: | 1576 | ioctl_exit: |
1579 | free_rsp_buf(resp_buftype, rsp); | 1577 | free_rsp_buf(resp_buftype, rsp); |
@@ -2093,7 +2091,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
2093 | } | 2091 | } |
2094 | 2092 | ||
2095 | if (*buf) { | 2093 | if (*buf) { |
2096 | memcpy(*buf, (char *)rsp->hdr.ProtocolId + rsp->DataOffset, | 2094 | memcpy(*buf, (char *)&rsp->hdr.ProtocolId + rsp->DataOffset, |
2097 | *nbytes); | 2095 | *nbytes); |
2098 | free_rsp_buf(resp_buftype, iov[0].iov_base); | 2096 | free_rsp_buf(resp_buftype, iov[0].iov_base); |
2099 | } else if (resp_buftype != CIFS_NO_BUFFER) { | 2097 | } else if (resp_buftype != CIFS_NO_BUFFER) { |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 4af52780ec35..ff88d9feb01e 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -86,6 +86,7 @@ | |||
86 | #define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ | 86 | #define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ |
87 | 87 | ||
88 | #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) | 88 | #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) |
89 | #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) | ||
89 | 90 | ||
90 | /* | 91 | /* |
91 | * SMB2 Header Definition | 92 | * SMB2 Header Definition |
@@ -102,7 +103,7 @@ struct smb2_hdr { | |||
102 | __be32 smb2_buf_length; /* big endian on wire */ | 103 | __be32 smb2_buf_length; /* big endian on wire */ |
103 | /* length is only two or three bytes - with | 104 | /* length is only two or three bytes - with |
104 | one or two byte type preceding it that MBZ */ | 105 | one or two byte type preceding it that MBZ */ |
105 | __u8 ProtocolId[4]; /* 0xFE 'S' 'M' 'B' */ | 106 | __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ |
106 | __le16 StructureSize; /* 64 */ | 107 | __le16 StructureSize; /* 64 */ |
107 | __le16 CreditCharge; /* MBZ */ | 108 | __le16 CreditCharge; /* MBZ */ |
108 | __le32 Status; /* Error from server */ | 109 | __le32 Status; /* Error from server */ |
@@ -128,11 +129,10 @@ struct smb2_transform_hdr { | |||
128 | one or two byte type preceding it that MBZ */ | 129 | one or two byte type preceding it that MBZ */ |
129 | __u8 ProtocolId[4]; /* 0xFD 'S' 'M' 'B' */ | 130 | __u8 ProtocolId[4]; /* 0xFD 'S' 'M' 'B' */ |
130 | __u8 Signature[16]; | 131 | __u8 Signature[16]; |
131 | __u8 Nonce[11]; | 132 | __u8 Nonce[16]; |
132 | __u8 Reserved[5]; | ||
133 | __le32 OriginalMessageSize; | 133 | __le32 OriginalMessageSize; |
134 | __u16 Reserved1; | 134 | __u16 Reserved1; |
135 | __le16 EncryptionAlgorithm; | 135 | __le16 Flags; /* EncryptionAlgorithm */ |
136 | __u64 SessionId; | 136 | __u64 SessionId; |
137 | } __packed; | 137 | } __packed; |
138 | 138 | ||
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 79dc650c18b2..4f07dc93608d 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -34,7 +34,8 @@ struct smb_rqst; | |||
34 | ***************************************************************** | 34 | ***************************************************************** |
35 | */ | 35 | */ |
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 | extern unsigned int smb2_calc_size(void *buf); | 39 | extern unsigned int smb2_calc_size(void *buf); |
39 | 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, struct smb2_hdr *hdr); |
40 | extern __le16 *cifs_convert_path_to_utf16(const char *from, | 41 | extern __le16 *cifs_convert_path_to_utf16(const char *from, |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index d4c5b6f109a7..8732a43b1008 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -222,8 +222,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
222 | return rc; | 222 | return rc; |
223 | } | 223 | } |
224 | 224 | ||
225 | int | 225 | static int generate_key(struct cifs_ses *ses, struct kvec label, |
226 | generate_smb3signingkey(struct cifs_ses *ses) | 226 | struct kvec context, __u8 *key, unsigned int key_size) |
227 | { | 227 | { |
228 | unsigned char zero = 0x0; | 228 | unsigned char zero = 0x0; |
229 | __u8 i[4] = {0, 0, 0, 1}; | 229 | __u8 i[4] = {0, 0, 0, 1}; |
@@ -233,7 +233,7 @@ generate_smb3signingkey(struct cifs_ses *ses) | |||
233 | unsigned char *hashptr = prfhash; | 233 | unsigned char *hashptr = prfhash; |
234 | 234 | ||
235 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); | 235 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); |
236 | memset(ses->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); | 236 | memset(key, 0x0, key_size); |
237 | 237 | ||
238 | rc = smb3_crypto_shash_allocate(ses->server); | 238 | rc = smb3_crypto_shash_allocate(ses->server); |
239 | if (rc) { | 239 | if (rc) { |
@@ -262,7 +262,7 @@ generate_smb3signingkey(struct cifs_ses *ses) | |||
262 | } | 262 | } |
263 | 263 | ||
264 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 264 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
265 | "SMB2AESCMAC", 12); | 265 | label.iov_base, label.iov_len); |
266 | if (rc) { | 266 | if (rc) { |
267 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); | 267 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); |
268 | goto smb3signkey_ret; | 268 | goto smb3signkey_ret; |
@@ -276,7 +276,7 @@ generate_smb3signingkey(struct cifs_ses *ses) | |||
276 | } | 276 | } |
277 | 277 | ||
278 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 278 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, |
279 | "SmbSign", 8); | 279 | context.iov_base, context.iov_len); |
280 | if (rc) { | 280 | if (rc) { |
281 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); | 281 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); |
282 | goto smb3signkey_ret; | 282 | goto smb3signkey_ret; |
@@ -296,12 +296,102 @@ generate_smb3signingkey(struct cifs_ses *ses) | |||
296 | goto smb3signkey_ret; | 296 | goto smb3signkey_ret; |
297 | } | 297 | } |
298 | 298 | ||
299 | memcpy(ses->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE); | 299 | memcpy(key, hashptr, key_size); |
300 | 300 | ||
301 | smb3signkey_ret: | 301 | smb3signkey_ret: |
302 | return rc; | 302 | return rc; |
303 | } | 303 | } |
304 | 304 | ||
305 | struct derivation { | ||
306 | struct kvec label; | ||
307 | struct kvec context; | ||
308 | }; | ||
309 | |||
310 | struct derivation_triplet { | ||
311 | struct derivation signing; | ||
312 | struct derivation encryption; | ||
313 | struct derivation decryption; | ||
314 | }; | ||
315 | |||
316 | static int | ||
317 | generate_smb3signingkey(struct cifs_ses *ses, | ||
318 | const struct derivation_triplet *ptriplet) | ||
319 | { | ||
320 | int rc; | ||
321 | |||
322 | rc = generate_key(ses, ptriplet->signing.label, | ||
323 | ptriplet->signing.context, ses->smb3signingkey, | ||
324 | SMB3_SIGN_KEY_SIZE); | ||
325 | if (rc) | ||
326 | return rc; | ||
327 | |||
328 | rc = generate_key(ses, ptriplet->encryption.label, | ||
329 | ptriplet->encryption.context, ses->smb3encryptionkey, | ||
330 | SMB3_SIGN_KEY_SIZE); | ||
331 | if (rc) | ||
332 | return rc; | ||
333 | |||
334 | return generate_key(ses, ptriplet->decryption.label, | ||
335 | ptriplet->decryption.context, | ||
336 | ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE); | ||
337 | } | ||
338 | |||
339 | int | ||
340 | generate_smb30signingkey(struct cifs_ses *ses) | ||
341 | |||
342 | { | ||
343 | struct derivation_triplet triplet; | ||
344 | struct derivation *d; | ||
345 | |||
346 | d = &triplet.signing; | ||
347 | d->label.iov_base = "SMB2AESCMAC"; | ||
348 | d->label.iov_len = 12; | ||
349 | d->context.iov_base = "SmbSign"; | ||
350 | d->context.iov_len = 8; | ||
351 | |||
352 | d = &triplet.encryption; | ||
353 | d->label.iov_base = "SMB2AESCCM"; | ||
354 | d->label.iov_len = 11; | ||
355 | d->context.iov_base = "ServerIn "; | ||
356 | d->context.iov_len = 10; | ||
357 | |||
358 | d = &triplet.decryption; | ||
359 | d->label.iov_base = "SMB2AESCCM"; | ||
360 | d->label.iov_len = 11; | ||
361 | d->context.iov_base = "ServerOut"; | ||
362 | d->context.iov_len = 10; | ||
363 | |||
364 | return generate_smb3signingkey(ses, &triplet); | ||
365 | } | ||
366 | |||
367 | int | ||
368 | generate_smb311signingkey(struct cifs_ses *ses) | ||
369 | |||
370 | { | ||
371 | struct derivation_triplet triplet; | ||
372 | struct derivation *d; | ||
373 | |||
374 | d = &triplet.signing; | ||
375 | d->label.iov_base = "SMB2AESCMAC"; | ||
376 | d->label.iov_len = 12; | ||
377 | d->context.iov_base = "SmbSign"; | ||
378 | d->context.iov_len = 8; | ||
379 | |||
380 | d = &triplet.encryption; | ||
381 | d->label.iov_base = "SMB2AESCCM"; | ||
382 | d->label.iov_len = 11; | ||
383 | d->context.iov_base = "ServerIn "; | ||
384 | d->context.iov_len = 10; | ||
385 | |||
386 | d = &triplet.decryption; | ||
387 | d->label.iov_base = "SMB2AESCCM"; | ||
388 | d->label.iov_len = 11; | ||
389 | d->context.iov_base = "ServerOut"; | ||
390 | d->context.iov_len = 10; | ||
391 | |||
392 | return generate_smb3signingkey(ses, &triplet); | ||
393 | } | ||
394 | |||
305 | int | 395 | int |
306 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 396 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
307 | { | 397 | { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 2a24c524fb9a..87abe8ed074c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -576,14 +576,16 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, | |||
576 | cifs_in_send_dec(server); | 576 | cifs_in_send_dec(server); |
577 | cifs_save_when_sent(mid); | 577 | cifs_save_when_sent(mid); |
578 | 578 | ||
579 | if (rc < 0) | 579 | if (rc < 0) { |
580 | server->sequence_number -= 2; | 580 | server->sequence_number -= 2; |
581 | cifs_delete_mid(mid); | ||
582 | } | ||
583 | |||
581 | mutex_unlock(&server->srv_mutex); | 584 | mutex_unlock(&server->srv_mutex); |
582 | 585 | ||
583 | if (rc == 0) | 586 | if (rc == 0) |
584 | return 0; | 587 | return 0; |
585 | 588 | ||
586 | cifs_delete_mid(mid); | ||
587 | add_credits_and_wake_if(server, credits, optype); | 589 | add_credits_and_wake_if(server, credits, optype); |
588 | return rc; | 590 | return rc; |
589 | } | 591 | } |