aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_debug.c1
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_ioctl.h8
-rw-r--r--fs/cifs/cifsacl.c123
-rw-r--r--fs/cifs/cifsfs.c11
-rw-r--r--fs/cifs/cifsglob.h50
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/connect.c43
-rw-r--r--fs/cifs/file.c105
-rw-r--r--fs/cifs/ioctl.c16
-rw-r--r--fs/cifs/misc.c15
-rw-r--r--fs/cifs/readdir.c6
-rw-r--r--fs/cifs/smb2inode.c6
-rw-r--r--fs/cifs/smb2misc.c16
-rw-r--r--fs/cifs/smb2ops.c62
-rw-r--r--fs/cifs/smb2pdu.c587
-rw-r--r--fs/cifs/smb2pdu.h2
-rw-r--r--fs/cifs/xattr.c62
19 files changed, 824 insertions, 296 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 6c58e13fed2f..3d03e48a9213 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -152,6 +152,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
152 list_for_each(tmp1, &cifs_tcp_ses_list) { 152 list_for_each(tmp1, &cifs_tcp_ses_list) {
153 server = list_entry(tmp1, struct TCP_Server_Info, 153 server = list_entry(tmp1, struct TCP_Server_Info,
154 tcp_ses_list); 154 tcp_ses_list);
155 seq_printf(m, "\nNumber of credits: %d", server->credits);
155 i++; 156 i++;
156 list_for_each(tmp2, &server->smb_ses_list) { 157 list_for_each(tmp2, &server->smb_ses_list) {
157 ses = list_entry(tmp2, struct cifs_ses, 158 ses = list_entry(tmp2, struct cifs_ses,
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 1418daa03d95..07ed81cf1552 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -49,6 +49,7 @@
49#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible 49#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
50 * root mountable 50 * root mountable
51 */ 51 */
52#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
52 53
53struct cifs_sb_info { 54struct cifs_sb_info {
54 struct rb_root tlink_tree; 55 struct rb_root tlink_tree;
diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 0065256881d8..57ff0756e30c 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -36,7 +36,15 @@ struct smb_mnt_fs_info {
36 __u64 cifs_posix_caps; 36 __u64 cifs_posix_caps;
37} __packed; 37} __packed;
38 38
39struct smb_snapshot_array {
40 __u32 number_of_snapshots;
41 __u32 number_of_snapshots_returned;
42 __u32 snapshot_array_size;
43 /* snapshots[]; */
44} __packed;
45
39#define CIFS_IOCTL_MAGIC 0xCF 46#define CIFS_IOCTL_MAGIC 0xCF
40#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) 47#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
41#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4) 48#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
42#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info) 49#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
50#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 71e8a56e9479..15bac390dff9 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -42,6 +42,35 @@ static const struct cifs_sid sid_authusers = {
42/* group users */ 42/* group users */
43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; 43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44 44
45/* S-1-22-1 Unmapped Unix users */
46static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
47 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
48
49/* S-1-22-2 Unmapped Unix groups */
50static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
51 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
52
53/*
54 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
55 */
56
57/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
58
59/* S-1-5-88-1 Unix uid */
60static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
61 {cpu_to_le32(88),
62 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
63
64/* S-1-5-88-2 Unix gid */
65static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
66 {cpu_to_le32(88),
67 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
68
69/* S-1-5-88-3 Unix mode */
70static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
71 {cpu_to_le32(88),
72 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
73
45static const struct cred *root_cred; 74static const struct cred *root_cred;
46 75
47static int 76static int
@@ -183,6 +212,62 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
183 return 0; /* sids compare/match */ 212 return 0; /* sids compare/match */
184} 213}
185 214
215static bool
216is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
217{
218 int i;
219 int num_subauth;
220 const struct cifs_sid *pwell_known_sid;
221
222 if (!psid || (puid == NULL))
223 return false;
224
225 num_subauth = psid->num_subauth;
226
227 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
228 if (num_subauth == 2) {
229 if (is_group)
230 pwell_known_sid = &sid_unix_groups;
231 else
232 pwell_known_sid = &sid_unix_users;
233 } else if (num_subauth == 3) {
234 if (is_group)
235 pwell_known_sid = &sid_unix_NFS_groups;
236 else
237 pwell_known_sid = &sid_unix_NFS_users;
238 } else
239 return false;
240
241 /* compare the revision */
242 if (psid->revision != pwell_known_sid->revision)
243 return false;
244
245 /* compare all of the six auth values */
246 for (i = 0; i < NUM_AUTHS; ++i) {
247 if (psid->authority[i] != pwell_known_sid->authority[i]) {
248 cifs_dbg(FYI, "auth %d did not match\n", i);
249 return false;
250 }
251 }
252
253 if (num_subauth == 2) {
254 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
255 return false;
256
257 *puid = le32_to_cpu(psid->sub_auth[1]);
258 } else /* 3 subauths, ie Windows/Mac style */ {
259 *puid = le32_to_cpu(psid->sub_auth[0]);
260 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
261 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
262 return false;
263
264 *puid = le32_to_cpu(psid->sub_auth[2]);
265 }
266
267 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
268 return true; /* well known sid found, uid returned */
269}
270
186static void 271static void
187cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) 272cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
188{ 273{
@@ -276,6 +361,43 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
276 return -EIO; 361 return -EIO;
277 } 362 }
278 363
364 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
365 uint32_t unix_id;
366 bool is_group;
367
368 if (sidtype != SIDOWNER)
369 is_group = true;
370 else
371 is_group = false;
372
373 if (is_well_known_sid(psid, &unix_id, is_group) == false)
374 goto try_upcall_to_get_id;
375
376 if (is_group) {
377 kgid_t gid;
378 gid_t id;
379
380 id = (gid_t)unix_id;
381 gid = make_kgid(&init_user_ns, id);
382 if (gid_valid(gid)) {
383 fgid = gid;
384 goto got_valid_id;
385 }
386 } else {
387 kuid_t uid;
388 uid_t id;
389
390 id = (uid_t)unix_id;
391 uid = make_kuid(&init_user_ns, id);
392 if (uid_valid(uid)) {
393 fuid = uid;
394 goto got_valid_id;
395 }
396 }
397 /* If unable to find uid/gid easily from SID try via upcall */
398 }
399
400try_upcall_to_get_id:
279 sidstr = sid_to_key_str(psid, sidtype); 401 sidstr = sid_to_key_str(psid, sidtype);
280 if (!sidstr) 402 if (!sidstr)
281 return -ENOMEM; 403 return -ENOMEM;
@@ -329,6 +451,7 @@ out_revert_creds:
329 * Note that we return 0 here unconditionally. If the mapping 451 * Note that we return 0 here unconditionally. If the mapping
330 * fails then we just fall back to using the mnt_uid/mnt_gid. 452 * fails then we just fall back to using the mnt_uid/mnt_gid.
331 */ 453 */
454got_valid_id:
332 if (sidtype == SIDOWNER) 455 if (sidtype == SIDOWNER)
333 fattr->cf_uid = fuid; 456 fattr->cf_uid = fuid;
334 else 457 else
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index cca04e710421..15261ba464c5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,15 +64,15 @@ unsigned int global_secflags = CIFSSEC_DEF;
64unsigned int sign_CIFS_PDUs = 1; 64unsigned int sign_CIFS_PDUs = 1;
65static const struct super_operations cifs_super_ops; 65static const struct super_operations cifs_super_ops;
66unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 66unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
67module_param(CIFSMaxBufSize, uint, 0); 67module_param(CIFSMaxBufSize, uint, 0444);
68MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). " 68MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
69 "Default: 16384 Range: 8192 to 130048"); 69 "Default: 16384 Range: 8192 to 130048");
70unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; 70unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
71module_param(cifs_min_rcv, uint, 0); 71module_param(cifs_min_rcv, uint, 0444);
72MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: " 72MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
73 "1 to 64"); 73 "1 to 64");
74unsigned int cifs_min_small = 30; 74unsigned int cifs_min_small = 30;
75module_param(cifs_min_small, uint, 0); 75module_param(cifs_min_small, uint, 0444);
76MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " 76MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
77 "Range: 2 to 256"); 77 "Range: 2 to 256");
78unsigned int cifs_max_pending = CIFS_MAX_REQ; 78unsigned int cifs_max_pending = CIFS_MAX_REQ;
@@ -271,7 +271,7 @@ cifs_alloc_inode(struct super_block *sb)
271 cifs_inode->createtime = 0; 271 cifs_inode->createtime = 0;
272 cifs_inode->epoch = 0; 272 cifs_inode->epoch = 0;
273#ifdef CONFIG_CIFS_SMB2 273#ifdef CONFIG_CIFS_SMB2
274 get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE); 274 generate_random_uuid(cifs_inode->lease_key);
275#endif 275#endif
276 /* 276 /*
277 * Can not set i_flags here - they get immediately overwritten to zero 277 * Can not set i_flags here - they get immediately overwritten to zero
@@ -469,6 +469,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
469 seq_puts(s, ",posixpaths"); 469 seq_puts(s, ",posixpaths");
470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
471 seq_puts(s, ",setuids"); 471 seq_puts(s, ",setuids");
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
473 seq_puts(s, ",idsfromsid");
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 474 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
473 seq_puts(s, ",serverino"); 475 seq_puts(s, ",serverino");
474 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 476 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
@@ -1262,7 +1264,6 @@ init_cifs(void)
1262 GlobalTotalActiveXid = 0; 1264 GlobalTotalActiveXid = 0;
1263 GlobalMaxActiveXid = 0; 1265 GlobalMaxActiveXid = 0;
1264 spin_lock_init(&cifs_tcp_ses_lock); 1266 spin_lock_init(&cifs_tcp_ses_lock);
1265 spin_lock_init(&cifs_file_list_lock);
1266 spin_lock_init(&GlobalMid_Lock); 1267 spin_lock_init(&GlobalMid_Lock);
1267 1268
1268 get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret)); 1269 get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret));
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 8f1d8c1e72be..1f17f6bd7a60 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -75,6 +75,18 @@
75#define SMB_ECHO_INTERVAL_MAX 600 75#define SMB_ECHO_INTERVAL_MAX 600
76#define SMB_ECHO_INTERVAL_DEFAULT 60 76#define SMB_ECHO_INTERVAL_DEFAULT 60
77 77
78/*
79 * Default number of credits to keep available for SMB3.
80 * This value is chosen somewhat arbitrarily. The Windows client
81 * defaults to 128 credits, the Windows server allows clients up to
82 * 512 credits (or 8K for later versions), and the NetApp server
83 * does not limit clients at all. Choose a high enough default value
84 * such that the client shouldn't limit performance, but allow mount
85 * to override (until you approach 64K, where we limit credits to 65000
86 * to reduce possibility of seeing more server credit overflow bugs.
87 */
88#define SMB2_MAX_CREDITS_AVAILABLE 32000
89
78#include "cifspdu.h" 90#include "cifspdu.h"
79 91
80#ifndef XATTR_DOS_ATTRIB 92#ifndef XATTR_DOS_ATTRIB
@@ -376,6 +388,8 @@ struct smb_version_operations {
376 int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); 388 int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
377 int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, 389 int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
378 struct cifsFileInfo *src_file); 390 struct cifsFileInfo *src_file);
391 int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
392 struct cifsFileInfo *src_file, void __user *);
379 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, 393 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
380 struct cifs_sb_info *, const unsigned char *, 394 struct cifs_sb_info *, const unsigned char *,
381 char *, unsigned int *); 395 char *, unsigned int *);
@@ -464,6 +478,7 @@ struct smb_vol {
464 bool retry:1; 478 bool retry:1;
465 bool intr:1; 479 bool intr:1;
466 bool setuids:1; 480 bool setuids:1;
481 bool setuidfromacl:1;
467 bool override_uid:1; 482 bool override_uid:1;
468 bool override_gid:1; 483 bool override_gid:1;
469 bool dynperm:1; 484 bool dynperm:1;
@@ -510,6 +525,7 @@ struct smb_vol {
510 struct sockaddr_storage srcaddr; /* allow binding to a local IP */ 525 struct sockaddr_storage srcaddr; /* allow binding to a local IP */
511 struct nls_table *local_nls; 526 struct nls_table *local_nls;
512 unsigned int echo_interval; /* echo interval in secs */ 527 unsigned int echo_interval; /* echo interval in secs */
528 unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
513}; 529};
514 530
515#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ 531#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \
@@ -567,7 +583,8 @@ struct TCP_Server_Info {
567 bool noblocksnd; /* use blocking sendmsg */ 583 bool noblocksnd; /* use blocking sendmsg */
568 bool noautotune; /* do not autotune send buf sizes */ 584 bool noautotune; /* do not autotune send buf sizes */
569 bool tcp_nodelay; 585 bool tcp_nodelay;
570 int credits; /* send no more requests at once */ 586 unsigned int credits; /* send no more requests at once */
587 unsigned int max_credits; /* can override large 32000 default at mnt */
571 unsigned int in_flight; /* number of requests on the wire to server */ 588 unsigned int in_flight; /* number of requests on the wire to server */
572 spinlock_t req_lock; /* protect the two values above */ 589 spinlock_t req_lock; /* protect the two values above */
573 struct mutex srv_mutex; 590 struct mutex srv_mutex;
@@ -833,6 +850,7 @@ struct cifs_tcon {
833 struct list_head tcon_list; 850 struct list_head tcon_list;
834 int tc_count; 851 int tc_count;
835 struct list_head openFileList; 852 struct list_head openFileList;
853 spinlock_t open_file_lock; /* protects list above */
836 struct cifs_ses *ses; /* pointer to session associated with */ 854 struct cifs_ses *ses; /* pointer to session associated with */
837 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ 855 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
838 char *nativeFileSystem; 856 char *nativeFileSystem;
@@ -889,7 +907,7 @@ struct cifs_tcon {
889#endif /* CONFIG_CIFS_STATS2 */ 907#endif /* CONFIG_CIFS_STATS2 */
890 __u64 bytes_read; 908 __u64 bytes_read;
891 __u64 bytes_written; 909 __u64 bytes_written;
892 spinlock_t stat_lock; 910 spinlock_t stat_lock; /* protects the two fields above */
893#endif /* CONFIG_CIFS_STATS */ 911#endif /* CONFIG_CIFS_STATS */
894 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 912 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
895 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ 913 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
@@ -1040,20 +1058,24 @@ struct cifs_fid_locks {
1040}; 1058};
1041 1059
1042struct cifsFileInfo { 1060struct cifsFileInfo {
1061 /* following two lists are protected by tcon->open_file_lock */
1043 struct list_head tlist; /* pointer to next fid owned by tcon */ 1062 struct list_head tlist; /* pointer to next fid owned by tcon */
1044 struct list_head flist; /* next fid (file instance) for this inode */ 1063 struct list_head flist; /* next fid (file instance) for this inode */
1064 /* lock list below protected by cifsi->lock_sem */
1045 struct cifs_fid_locks *llist; /* brlocks held by this fid */ 1065 struct cifs_fid_locks *llist; /* brlocks held by this fid */
1046 kuid_t uid; /* allows finding which FileInfo structure */ 1066 kuid_t uid; /* allows finding which FileInfo structure */
1047 __u32 pid; /* process id who opened file */ 1067 __u32 pid; /* process id who opened file */
1048 struct cifs_fid fid; /* file id from remote */ 1068 struct cifs_fid fid; /* file id from remote */
1069 struct list_head rlist; /* reconnect list */
1049 /* BB add lock scope info here if needed */ ; 1070 /* BB add lock scope info here if needed */ ;
1050 /* lock scope id (0 if none) */ 1071 /* lock scope id (0 if none) */
1051 struct dentry *dentry; 1072 struct dentry *dentry;
1052 unsigned int f_flags;
1053 struct tcon_link *tlink; 1073 struct tcon_link *tlink;
1074 unsigned int f_flags;
1054 bool invalidHandle:1; /* file closed via session abend */ 1075 bool invalidHandle:1; /* file closed via session abend */
1055 bool oplock_break_cancelled:1; 1076 bool oplock_break_cancelled:1;
1056 int count; /* refcount protected by cifs_file_list_lock */ 1077 int count;
1078 spinlock_t file_info_lock; /* protects four flag/count fields above */
1057 struct mutex fh_mutex; /* prevents reopen race after dead ses*/ 1079 struct mutex fh_mutex; /* prevents reopen race after dead ses*/
1058 struct cifs_search_info srch_inf; 1080 struct cifs_search_info srch_inf;
1059 struct work_struct oplock_break; /* work for oplock breaks */ 1081 struct work_struct oplock_break; /* work for oplock breaks */
@@ -1120,7 +1142,7 @@ struct cifs_writedata {
1120 1142
1121/* 1143/*
1122 * Take a reference on the file private data. Must be called with 1144 * Take a reference on the file private data. Must be called with
1123 * cifs_file_list_lock held. 1145 * cfile->file_info_lock held.
1124 */ 1146 */
1125static inline void 1147static inline void
1126cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file) 1148cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
@@ -1514,8 +1536,10 @@ require use of the stronger protocol */
1514 * GlobalMid_Lock protects: 1536 * GlobalMid_Lock protects:
1515 * list operations on pending_mid_q and oplockQ 1537 * list operations on pending_mid_q and oplockQ
1516 * updates to XID counters, multiplex id and SMB sequence numbers 1538 * updates to XID counters, multiplex id and SMB sequence numbers
1517 * cifs_file_list_lock protects: 1539 * tcp_ses_lock protects:
1518 * list operations on tcp and SMB session lists and tCon lists 1540 * list operations on tcp and SMB session lists
1541 * tcon->open_file_lock protects the list of open files hanging off the tcon
1542 * cfile->file_info_lock protects counters and fields in cifs file struct
1519 * f_owner.lock protects certain per file struct operations 1543 * f_owner.lock protects certain per file struct operations
1520 * mapping->page_lock protects certain per page operations 1544 * mapping->page_lock protects certain per page operations
1521 * 1545 *
@@ -1547,18 +1571,12 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
1547 * tcp session, and the list of tcon's per smb session. It also protects 1571 * tcp session, and the list of tcon's per smb session. It also protects
1548 * the reference counters for the server, smb session, and tcon. Finally, 1572 * the reference counters for the server, smb session, and tcon. Finally,
1549 * changes to the tcon->tidStatus should be done while holding this lock. 1573 * changes to the tcon->tidStatus should be done while holding this lock.
1574 * generally the locks should be taken in order tcp_ses_lock before
1575 * tcon->open_file_lock and that before file->file_info_lock since the
1576 * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
1550 */ 1577 */
1551GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock; 1578GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock;
1552 1579
1553/*
1554 * This lock protects the cifs_file->llist and cifs_file->flist
1555 * list operations, and updates to some flags (cifs_file->invalidHandle)
1556 * It will be moved to either use the tcon->stat_lock or equivalent later.
1557 * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
1558 * the cifs_tcp_ses_lock must be grabbed first and released last.
1559 */
1560GLOBAL_EXTERN spinlock_t cifs_file_list_lock;
1561
1562#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ 1580#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
1563/* Outstanding dir notify requests */ 1581/* Outstanding dir notify requests */
1564GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; 1582GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 4ead72a001f9..ced0e42ce460 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -193,6 +193,8 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data,
193extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); 193extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
194extern void cifs_umount(struct cifs_sb_info *); 194extern void cifs_umount(struct cifs_sb_info *);
195extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon); 195extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
196extern void cifs_reopen_persistent_handles(struct cifs_tcon *tcon);
197
196extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, 198extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
197 __u64 length, __u8 type, 199 __u64 length, __u8 type,
198 struct cifsLockInfo **conf_lock, 200 struct cifsLockInfo **conf_lock,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f82d2823622f..3f3185febc58 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -98,13 +98,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
98 struct list_head *tmp1; 98 struct list_head *tmp1;
99 99
100 /* list all files open on tree connection and mark them invalid */ 100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&cifs_file_list_lock); 101 spin_lock(&tcon->open_file_lock);
102 list_for_each_safe(tmp, tmp1, &tcon->openFileList) { 102 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist); 103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true; 104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true; 105 open_file->oplock_break_cancelled = true;
106 } 106 }
107 spin_unlock(&cifs_file_list_lock); 107 spin_unlock(&tcon->open_file_lock);
108 /* 108 /*
109 * BB Add call to invalidate_inodes(sb) for all superblocks mounted 109 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
110 * to this tcon. 110 * to this tcon.
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2e4f4bad8b1e..aab5227979e2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -63,7 +63,6 @@ extern mempool_t *cifs_req_poolp;
63#define TLINK_IDLE_EXPIRE (600 * HZ) 63#define TLINK_IDLE_EXPIRE (600 * HZ)
64 64
65enum { 65enum {
66
67 /* Mount options that take no arguments */ 66 /* Mount options that take no arguments */
68 Opt_user_xattr, Opt_nouser_xattr, 67 Opt_user_xattr, Opt_nouser_xattr,
69 Opt_forceuid, Opt_noforceuid, 68 Opt_forceuid, Opt_noforceuid,
@@ -76,7 +75,7 @@ enum {
76 Opt_noposixpaths, Opt_nounix, 75 Opt_noposixpaths, Opt_nounix,
77 Opt_nocase, 76 Opt_nocase,
78 Opt_brl, Opt_nobrl, 77 Opt_brl, Opt_nobrl,
79 Opt_forcemandatorylock, Opt_setuids, 78 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
80 Opt_nosetuids, Opt_dynperm, Opt_nodynperm, 79 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
81 Opt_nohard, Opt_nosoft, 80 Opt_nohard, Opt_nosoft,
82 Opt_nointr, Opt_intr, 81 Opt_nointr, Opt_intr,
@@ -95,7 +94,7 @@ enum {
95 Opt_cruid, Opt_gid, Opt_file_mode, 94 Opt_cruid, Opt_gid, Opt_file_mode,
96 Opt_dirmode, Opt_port, 95 Opt_dirmode, Opt_port,
97 Opt_rsize, Opt_wsize, Opt_actimeo, 96 Opt_rsize, Opt_wsize, Opt_actimeo,
98 Opt_echo_interval, 97 Opt_echo_interval, Opt_max_credits,
99 98
100 /* Mount options which take string value */ 99 /* Mount options which take string value */
101 Opt_user, Opt_pass, Opt_ip, 100 Opt_user, Opt_pass, Opt_ip,
@@ -148,6 +147,7 @@ static const match_table_t cifs_mount_option_tokens = {
148 { Opt_forcemandatorylock, "forcemand" }, 147 { Opt_forcemandatorylock, "forcemand" },
149 { Opt_setuids, "setuids" }, 148 { Opt_setuids, "setuids" },
150 { Opt_nosetuids, "nosetuids" }, 149 { Opt_nosetuids, "nosetuids" },
150 { Opt_setuidfromacl, "idsfromsid" },
151 { Opt_dynperm, "dynperm" }, 151 { Opt_dynperm, "dynperm" },
152 { Opt_nodynperm, "nodynperm" }, 152 { Opt_nodynperm, "nodynperm" },
153 { Opt_nohard, "nohard" }, 153 { Opt_nohard, "nohard" },
@@ -190,6 +190,7 @@ static const match_table_t cifs_mount_option_tokens = {
190 { Opt_wsize, "wsize=%s" }, 190 { Opt_wsize, "wsize=%s" },
191 { Opt_actimeo, "actimeo=%s" }, 191 { Opt_actimeo, "actimeo=%s" },
192 { Opt_echo_interval, "echo_interval=%s" }, 192 { Opt_echo_interval, "echo_interval=%s" },
193 { Opt_max_credits, "max_credits=%s" },
193 194
194 { Opt_blank_user, "user=" }, 195 { Opt_blank_user, "user=" },
195 { Opt_blank_user, "username=" }, 196 { Opt_blank_user, "username=" },
@@ -1376,6 +1377,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1376 case Opt_nosetuids: 1377 case Opt_nosetuids:
1377 vol->setuids = 0; 1378 vol->setuids = 0;
1378 break; 1379 break;
1380 case Opt_setuidfromacl:
1381 vol->setuidfromacl = 1;
1382 break;
1379 case Opt_dynperm: 1383 case Opt_dynperm:
1380 vol->dynperm = true; 1384 vol->dynperm = true;
1381 break; 1385 break;
@@ -1586,6 +1590,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1586 } 1590 }
1587 vol->echo_interval = option; 1591 vol->echo_interval = option;
1588 break; 1592 break;
1593 case Opt_max_credits:
1594 if (get_option_ul(args, &option) || (option < 20) ||
1595 (option > 60000)) {
1596 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1597 __func__);
1598 goto cifs_parse_mount_err;
1599 }
1600 vol->max_credits = option;
1601 break;
1589 1602
1590 /* String Arguments */ 1603 /* String Arguments */
1591 1604
@@ -2163,7 +2176,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
2163 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, 2176 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2164 sizeof(tcp_ses->dstaddr)); 2177 sizeof(tcp_ses->dstaddr));
2165#ifdef CONFIG_CIFS_SMB2 2178#ifdef CONFIG_CIFS_SMB2
2166 get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE); 2179 generate_random_uuid(tcp_ses->client_guid);
2167#endif 2180#endif
2168 /* 2181 /*
2169 * at this point we are the only ones with the pointer 2182 * at this point we are the only ones with the pointer
@@ -3270,6 +3283,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3270 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; 3283 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3271 if (pvolume_info->setuids) 3284 if (pvolume_info->setuids)
3272 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; 3285 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3286 if (pvolume_info->setuidfromacl)
3287 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
3273 if (pvolume_info->server_ino) 3288 if (pvolume_info->server_ino)
3274 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; 3289 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3275 if (pvolume_info->remap) 3290 if (pvolume_info->remap)
@@ -3598,7 +3613,11 @@ try_mount_again:
3598 bdi_destroy(&cifs_sb->bdi); 3613 bdi_destroy(&cifs_sb->bdi);
3599 goto out; 3614 goto out;
3600 } 3615 }
3601 3616 if ((volume_info->max_credits < 20) ||
3617 (volume_info->max_credits > 60000))
3618 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3619 else
3620 server->max_credits = volume_info->max_credits;
3602 /* get a reference to a SMB session */ 3621 /* get a reference to a SMB session */
3603 ses = cifs_get_smb_ses(server, volume_info); 3622 ses = cifs_get_smb_ses(server, volume_info);
3604 if (IS_ERR(ses)) { 3623 if (IS_ERR(ses)) {
@@ -3688,14 +3707,16 @@ remote_path_check:
3688 goto mount_fail_check; 3707 goto mount_fail_check;
3689 } 3708 }
3690 3709
3691 rc = cifs_are_all_path_components_accessible(server, 3710 if (rc != -EREMOTE) {
3711 rc = cifs_are_all_path_components_accessible(server,
3692 xid, tcon, cifs_sb, 3712 xid, tcon, cifs_sb,
3693 full_path); 3713 full_path);
3694 if (rc != 0) { 3714 if (rc != 0) {
3695 cifs_dbg(VFS, "cannot query dirs between root and final path, " 3715 cifs_dbg(VFS, "cannot query dirs between root and final path, "
3696 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); 3716 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
3697 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 3717 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
3698 rc = 0; 3718 rc = 0;
3719 }
3699 } 3720 }
3700 kfree(full_path); 3721 kfree(full_path);
3701 } 3722 }
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a95fe8b1afe9..7f5f6176c6f1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -305,6 +305,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
305 cfile->tlink = cifs_get_tlink(tlink); 305 cfile->tlink = cifs_get_tlink(tlink);
306 INIT_WORK(&cfile->oplock_break, cifs_oplock_break); 306 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
307 mutex_init(&cfile->fh_mutex); 307 mutex_init(&cfile->fh_mutex);
308 spin_lock_init(&cfile->file_info_lock);
308 309
309 cifs_sb_active(inode->i_sb); 310 cifs_sb_active(inode->i_sb);
310 311
@@ -317,7 +318,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
317 oplock = 0; 318 oplock = 0;
318 } 319 }
319 320
320 spin_lock(&cifs_file_list_lock); 321 spin_lock(&tcon->open_file_lock);
321 if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock) 322 if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
322 oplock = fid->pending_open->oplock; 323 oplock = fid->pending_open->oplock;
323 list_del(&fid->pending_open->olist); 324 list_del(&fid->pending_open->olist);
@@ -326,12 +327,13 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
326 server->ops->set_fid(cfile, fid, oplock); 327 server->ops->set_fid(cfile, fid, oplock);
327 328
328 list_add(&cfile->tlist, &tcon->openFileList); 329 list_add(&cfile->tlist, &tcon->openFileList);
330
329 /* if readable file instance put first in list*/ 331 /* if readable file instance put first in list*/
330 if (file->f_mode & FMODE_READ) 332 if (file->f_mode & FMODE_READ)
331 list_add(&cfile->flist, &cinode->openFileList); 333 list_add(&cfile->flist, &cinode->openFileList);
332 else 334 else
333 list_add_tail(&cfile->flist, &cinode->openFileList); 335 list_add_tail(&cfile->flist, &cinode->openFileList);
334 spin_unlock(&cifs_file_list_lock); 336 spin_unlock(&tcon->open_file_lock);
335 337
336 if (fid->purge_cache) 338 if (fid->purge_cache)
337 cifs_zap_mapping(inode); 339 cifs_zap_mapping(inode);
@@ -343,16 +345,16 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
343struct cifsFileInfo * 345struct cifsFileInfo *
344cifsFileInfo_get(struct cifsFileInfo *cifs_file) 346cifsFileInfo_get(struct cifsFileInfo *cifs_file)
345{ 347{
346 spin_lock(&cifs_file_list_lock); 348 spin_lock(&cifs_file->file_info_lock);
347 cifsFileInfo_get_locked(cifs_file); 349 cifsFileInfo_get_locked(cifs_file);
348 spin_unlock(&cifs_file_list_lock); 350 spin_unlock(&cifs_file->file_info_lock);
349 return cifs_file; 351 return cifs_file;
350} 352}
351 353
352/* 354/*
353 * Release a reference on the file private data. This may involve closing 355 * Release a reference on the file private data. This may involve closing
354 * the filehandle out on the server. Must be called without holding 356 * the filehandle out on the server. Must be called without holding
355 * cifs_file_list_lock. 357 * tcon->open_file_lock and cifs_file->file_info_lock.
356 */ 358 */
357void cifsFileInfo_put(struct cifsFileInfo *cifs_file) 359void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
358{ 360{
@@ -367,11 +369,15 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
367 struct cifs_pending_open open; 369 struct cifs_pending_open open;
368 bool oplock_break_cancelled; 370 bool oplock_break_cancelled;
369 371
370 spin_lock(&cifs_file_list_lock); 372 spin_lock(&tcon->open_file_lock);
373
374 spin_lock(&cifs_file->file_info_lock);
371 if (--cifs_file->count > 0) { 375 if (--cifs_file->count > 0) {
372 spin_unlock(&cifs_file_list_lock); 376 spin_unlock(&cifs_file->file_info_lock);
377 spin_unlock(&tcon->open_file_lock);
373 return; 378 return;
374 } 379 }
380 spin_unlock(&cifs_file->file_info_lock);
375 381
376 if (server->ops->get_lease_key) 382 if (server->ops->get_lease_key)
377 server->ops->get_lease_key(inode, &fid); 383 server->ops->get_lease_key(inode, &fid);
@@ -395,7 +401,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
395 set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags); 401 set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
396 cifs_set_oplock_level(cifsi, 0); 402 cifs_set_oplock_level(cifsi, 0);
397 } 403 }
398 spin_unlock(&cifs_file_list_lock); 404
405 spin_unlock(&tcon->open_file_lock);
399 406
400 oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break); 407 oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break);
401 408
@@ -732,6 +739,15 @@ reopen_success:
732 * to the server to get the new inode info. 739 * to the server to get the new inode info.
733 */ 740 */
734 741
742 /*
743 * If the server returned a read oplock and we have mandatory brlocks,
744 * set oplock level to None.
745 */
746 if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
747 cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
748 oplock = 0;
749 }
750
735 server->ops->set_fid(cfile, &cfile->fid, oplock); 751 server->ops->set_fid(cfile, &cfile->fid, oplock);
736 if (oparms.reconnect) 752 if (oparms.reconnect)
737 cifs_relock_file(cfile); 753 cifs_relock_file(cfile);
@@ -753,6 +769,36 @@ int cifs_close(struct inode *inode, struct file *file)
753 return 0; 769 return 0;
754} 770}
755 771
772void
773cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
774{
775 struct cifsFileInfo *open_file;
776 struct list_head *tmp;
777 struct list_head *tmp1;
778 struct list_head tmp_list;
779
780 cifs_dbg(FYI, "Reopen persistent handles");
781 INIT_LIST_HEAD(&tmp_list);
782
783 /* list all files open on tree connection, reopen resilient handles */
784 spin_lock(&tcon->open_file_lock);
785 list_for_each(tmp, &tcon->openFileList) {
786 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
787 if (!open_file->invalidHandle)
788 continue;
789 cifsFileInfo_get(open_file);
790 list_add_tail(&open_file->rlist, &tmp_list);
791 }
792 spin_unlock(&tcon->open_file_lock);
793
794 list_for_each_safe(tmp, tmp1, &tmp_list) {
795 open_file = list_entry(tmp, struct cifsFileInfo, rlist);
796 cifs_reopen_file(open_file, false /* do not flush */);
797 list_del_init(&open_file->rlist);
798 cifsFileInfo_put(open_file);
799 }
800}
801
756int cifs_closedir(struct inode *inode, struct file *file) 802int cifs_closedir(struct inode *inode, struct file *file)
757{ 803{
758 int rc = 0; 804 int rc = 0;
@@ -772,10 +818,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
772 server = tcon->ses->server; 818 server = tcon->ses->server;
773 819
774 cifs_dbg(FYI, "Freeing private data in close dir\n"); 820 cifs_dbg(FYI, "Freeing private data in close dir\n");
775 spin_lock(&cifs_file_list_lock); 821 spin_lock(&cfile->file_info_lock);
776 if (server->ops->dir_needs_close(cfile)) { 822 if (server->ops->dir_needs_close(cfile)) {
777 cfile->invalidHandle = true; 823 cfile->invalidHandle = true;
778 spin_unlock(&cifs_file_list_lock); 824 spin_unlock(&cfile->file_info_lock);
779 if (server->ops->close_dir) 825 if (server->ops->close_dir)
780 rc = server->ops->close_dir(xid, tcon, &cfile->fid); 826 rc = server->ops->close_dir(xid, tcon, &cfile->fid);
781 else 827 else
@@ -784,7 +830,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
784 /* not much we can do if it fails anyway, ignore rc */ 830 /* not much we can do if it fails anyway, ignore rc */
785 rc = 0; 831 rc = 0;
786 } else 832 } else
787 spin_unlock(&cifs_file_list_lock); 833 spin_unlock(&cfile->file_info_lock);
788 834
789 buf = cfile->srch_inf.ntwrk_buf_start; 835 buf = cfile->srch_inf.ntwrk_buf_start;
790 if (buf) { 836 if (buf) {
@@ -1728,12 +1774,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1728{ 1774{
1729 struct cifsFileInfo *open_file = NULL; 1775 struct cifsFileInfo *open_file = NULL;
1730 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); 1776 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1777 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
1731 1778
1732 /* only filter by fsuid on multiuser mounts */ 1779 /* only filter by fsuid on multiuser mounts */
1733 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 1780 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1734 fsuid_only = false; 1781 fsuid_only = false;
1735 1782
1736 spin_lock(&cifs_file_list_lock); 1783 spin_lock(&tcon->open_file_lock);
1737 /* we could simply get the first_list_entry since write-only entries 1784 /* we could simply get the first_list_entry since write-only entries
1738 are always at the end of the list but since the first entry might 1785 are always at the end of the list but since the first entry might
1739 have a close pending, we go through the whole list */ 1786 have a close pending, we go through the whole list */
@@ -1744,8 +1791,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1744 if (!open_file->invalidHandle) { 1791 if (!open_file->invalidHandle) {
1745 /* found a good file */ 1792 /* found a good file */
1746 /* lock it so it will not be closed on us */ 1793 /* lock it so it will not be closed on us */
1747 cifsFileInfo_get_locked(open_file); 1794 cifsFileInfo_get(open_file);
1748 spin_unlock(&cifs_file_list_lock); 1795 spin_unlock(&tcon->open_file_lock);
1749 return open_file; 1796 return open_file;
1750 } /* else might as well continue, and look for 1797 } /* else might as well continue, and look for
1751 another, or simply have the caller reopen it 1798 another, or simply have the caller reopen it
@@ -1753,7 +1800,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1753 } else /* write only file */ 1800 } else /* write only file */
1754 break; /* write only files are last so must be done */ 1801 break; /* write only files are last so must be done */
1755 } 1802 }
1756 spin_unlock(&cifs_file_list_lock); 1803 spin_unlock(&tcon->open_file_lock);
1757 return NULL; 1804 return NULL;
1758} 1805}
1759 1806
@@ -1762,6 +1809,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1762{ 1809{
1763 struct cifsFileInfo *open_file, *inv_file = NULL; 1810 struct cifsFileInfo *open_file, *inv_file = NULL;
1764 struct cifs_sb_info *cifs_sb; 1811 struct cifs_sb_info *cifs_sb;
1812 struct cifs_tcon *tcon;
1765 bool any_available = false; 1813 bool any_available = false;
1766 int rc; 1814 int rc;
1767 unsigned int refind = 0; 1815 unsigned int refind = 0;
@@ -1777,15 +1825,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1777 } 1825 }
1778 1826
1779 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); 1827 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1828 tcon = cifs_sb_master_tcon(cifs_sb);
1780 1829
1781 /* only filter by fsuid on multiuser mounts */ 1830 /* only filter by fsuid on multiuser mounts */
1782 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 1831 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1783 fsuid_only = false; 1832 fsuid_only = false;
1784 1833
1785 spin_lock(&cifs_file_list_lock); 1834 spin_lock(&tcon->open_file_lock);
1786refind_writable: 1835refind_writable:
1787 if (refind > MAX_REOPEN_ATT) { 1836 if (refind > MAX_REOPEN_ATT) {
1788 spin_unlock(&cifs_file_list_lock); 1837 spin_unlock(&tcon->open_file_lock);
1789 return NULL; 1838 return NULL;
1790 } 1839 }
1791 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1840 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
@@ -1796,8 +1845,8 @@ refind_writable:
1796 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 1845 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
1797 if (!open_file->invalidHandle) { 1846 if (!open_file->invalidHandle) {
1798 /* found a good writable file */ 1847 /* found a good writable file */
1799 cifsFileInfo_get_locked(open_file); 1848 cifsFileInfo_get(open_file);
1800 spin_unlock(&cifs_file_list_lock); 1849 spin_unlock(&tcon->open_file_lock);
1801 return open_file; 1850 return open_file;
1802 } else { 1851 } else {
1803 if (!inv_file) 1852 if (!inv_file)
@@ -1813,24 +1862,24 @@ refind_writable:
1813 1862
1814 if (inv_file) { 1863 if (inv_file) {
1815 any_available = false; 1864 any_available = false;
1816 cifsFileInfo_get_locked(inv_file); 1865 cifsFileInfo_get(inv_file);
1817 } 1866 }
1818 1867
1819 spin_unlock(&cifs_file_list_lock); 1868 spin_unlock(&tcon->open_file_lock);
1820 1869
1821 if (inv_file) { 1870 if (inv_file) {
1822 rc = cifs_reopen_file(inv_file, false); 1871 rc = cifs_reopen_file(inv_file, false);
1823 if (!rc) 1872 if (!rc)
1824 return inv_file; 1873 return inv_file;
1825 else { 1874 else {
1826 spin_lock(&cifs_file_list_lock); 1875 spin_lock(&tcon->open_file_lock);
1827 list_move_tail(&inv_file->flist, 1876 list_move_tail(&inv_file->flist,
1828 &cifs_inode->openFileList); 1877 &cifs_inode->openFileList);
1829 spin_unlock(&cifs_file_list_lock); 1878 spin_unlock(&tcon->open_file_lock);
1830 cifsFileInfo_put(inv_file); 1879 cifsFileInfo_put(inv_file);
1831 spin_lock(&cifs_file_list_lock);
1832 ++refind; 1880 ++refind;
1833 inv_file = NULL; 1881 inv_file = NULL;
1882 spin_lock(&tcon->open_file_lock);
1834 goto refind_writable; 1883 goto refind_writable;
1835 } 1884 }
1836 } 1885 }
@@ -3612,15 +3661,17 @@ static int cifs_readpage(struct file *file, struct page *page)
3612static int is_inode_writable(struct cifsInodeInfo *cifs_inode) 3661static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3613{ 3662{
3614 struct cifsFileInfo *open_file; 3663 struct cifsFileInfo *open_file;
3664 struct cifs_tcon *tcon =
3665 cifs_sb_master_tcon(CIFS_SB(cifs_inode->vfs_inode.i_sb));
3615 3666
3616 spin_lock(&cifs_file_list_lock); 3667 spin_lock(&tcon->open_file_lock);
3617 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 3668 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
3618 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 3669 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
3619 spin_unlock(&cifs_file_list_lock); 3670 spin_unlock(&tcon->open_file_lock);
3620 return 1; 3671 return 1;
3621 } 3672 }
3622 } 3673 }
3623 spin_unlock(&cifs_file_list_lock); 3674 spin_unlock(&tcon->open_file_lock);
3624 return 0; 3675 return 0;
3625} 3676}
3626 3677
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 7a3b84e300f8..9f51b81119f2 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
189 xid = get_xid(); 189 xid = get_xid();
190 190
191 cifs_sb = CIFS_SB(inode->i_sb); 191 cifs_sb = CIFS_SB(inode->i_sb);
192 192 cifs_dbg(VFS, "cifs ioctl 0x%x\n", command);
193 switch (command) { 193 switch (command) {
194 case FS_IOC_GETFLAGS: 194 case FS_IOC_GETFLAGS:
195 if (pSMBFile == NULL) 195 if (pSMBFile == NULL)
@@ -267,11 +267,23 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
267 tcon = tlink_tcon(pSMBFile->tlink); 267 tcon = tlink_tcon(pSMBFile->tlink);
268 rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); 268 rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
269 break; 269 break;
270 case CIFS_ENUMERATE_SNAPSHOTS:
271 if (arg == 0) {
272 rc = -EINVAL;
273 goto cifs_ioc_exit;
274 }
275 tcon = tlink_tcon(pSMBFile->tlink);
276 if (tcon->ses->server->ops->enum_snapshots)
277 rc = tcon->ses->server->ops->enum_snapshots(xid, tcon,
278 pSMBFile, (void __user *)arg);
279 else
280 rc = -EOPNOTSUPP;
281 break;
270 default: 282 default:
271 cifs_dbg(FYI, "unsupported ioctl\n"); 283 cifs_dbg(FYI, "unsupported ioctl\n");
272 break; 284 break;
273 } 285 }
274 286cifs_ioc_exit:
275 free_xid(xid); 287 free_xid(xid);
276 return rc; 288 return rc;
277} 289}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 813fe13c2ae1..c6729156f9a0 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -120,6 +120,7 @@ tconInfoAlloc(void)
120 ++ret_buf->tc_count; 120 ++ret_buf->tc_count;
121 INIT_LIST_HEAD(&ret_buf->openFileList); 121 INIT_LIST_HEAD(&ret_buf->openFileList);
122 INIT_LIST_HEAD(&ret_buf->tcon_list); 122 INIT_LIST_HEAD(&ret_buf->tcon_list);
123 spin_lock_init(&ret_buf->open_file_lock);
123#ifdef CONFIG_CIFS_STATS 124#ifdef CONFIG_CIFS_STATS
124 spin_lock_init(&ret_buf->stat_lock); 125 spin_lock_init(&ret_buf->stat_lock);
125#endif 126#endif
@@ -465,7 +466,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
465 continue; 466 continue;
466 467
467 cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); 468 cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
468 spin_lock(&cifs_file_list_lock); 469 spin_lock(&tcon->open_file_lock);
469 list_for_each(tmp2, &tcon->openFileList) { 470 list_for_each(tmp2, &tcon->openFileList) {
470 netfile = list_entry(tmp2, struct cifsFileInfo, 471 netfile = list_entry(tmp2, struct cifsFileInfo,
471 tlist); 472 tlist);
@@ -495,11 +496,11 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
495 &netfile->oplock_break); 496 &netfile->oplock_break);
496 netfile->oplock_break_cancelled = false; 497 netfile->oplock_break_cancelled = false;
497 498
498 spin_unlock(&cifs_file_list_lock); 499 spin_unlock(&tcon->open_file_lock);
499 spin_unlock(&cifs_tcp_ses_lock); 500 spin_unlock(&cifs_tcp_ses_lock);
500 return true; 501 return true;
501 } 502 }
502 spin_unlock(&cifs_file_list_lock); 503 spin_unlock(&tcon->open_file_lock);
503 spin_unlock(&cifs_tcp_ses_lock); 504 spin_unlock(&cifs_tcp_ses_lock);
504 cifs_dbg(FYI, "No matching file for oplock break\n"); 505 cifs_dbg(FYI, "No matching file for oplock break\n");
505 return true; 506 return true;
@@ -613,9 +614,9 @@ backup_cred(struct cifs_sb_info *cifs_sb)
613void 614void
614cifs_del_pending_open(struct cifs_pending_open *open) 615cifs_del_pending_open(struct cifs_pending_open *open)
615{ 616{
616 spin_lock(&cifs_file_list_lock); 617 spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
617 list_del(&open->olist); 618 list_del(&open->olist);
618 spin_unlock(&cifs_file_list_lock); 619 spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
619} 620}
620 621
621void 622void
@@ -635,7 +636,7 @@ void
635cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink, 636cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
636 struct cifs_pending_open *open) 637 struct cifs_pending_open *open)
637{ 638{
638 spin_lock(&cifs_file_list_lock); 639 spin_lock(&tlink_tcon(tlink)->open_file_lock);
639 cifs_add_pending_open_locked(fid, tlink, open); 640 cifs_add_pending_open_locked(fid, tlink, open);
640 spin_unlock(&cifs_file_list_lock); 641 spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
641} 642}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 65cf85dcda09..8f6a2a5863b9 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -597,14 +597,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
597 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { 597 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
598 /* close and restart search */ 598 /* close and restart search */
599 cifs_dbg(FYI, "search backing up - close and restart search\n"); 599 cifs_dbg(FYI, "search backing up - close and restart search\n");
600 spin_lock(&cifs_file_list_lock); 600 spin_lock(&cfile->file_info_lock);
601 if (server->ops->dir_needs_close(cfile)) { 601 if (server->ops->dir_needs_close(cfile)) {
602 cfile->invalidHandle = true; 602 cfile->invalidHandle = true;
603 spin_unlock(&cifs_file_list_lock); 603 spin_unlock(&cfile->file_info_lock);
604 if (server->ops->close_dir) 604 if (server->ops->close_dir)
605 server->ops->close_dir(xid, tcon, &cfile->fid); 605 server->ops->close_dir(xid, tcon, &cfile->fid);
606 } else 606 } else
607 spin_unlock(&cifs_file_list_lock); 607 spin_unlock(&cfile->file_info_lock);
608 if (cfile->srch_inf.ntwrk_buf_start) { 608 if (cfile->srch_inf.ntwrk_buf_start) {
609 cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n"); 609 cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
610 if (cfile->srch_inf.smallBuf) 610 if (cfile->srch_inf.smallBuf)
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 4f0231e685a9..1238cd3552f9 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -266,9 +266,15 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
266 struct tcon_link *tlink; 266 struct tcon_link *tlink;
267 int rc; 267 int rc;
268 268
269 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
270 (buf->LastWriteTime == 0) && (buf->ChangeTime) &&
271 (buf->Attributes == 0))
272 return 0; /* would be a no op, no sense sending this */
273
269 tlink = cifs_sb_tlink(cifs_sb); 274 tlink = cifs_sb_tlink(cifs_sb);
270 if (IS_ERR(tlink)) 275 if (IS_ERR(tlink))
271 return PTR_ERR(tlink); 276 return PTR_ERR(tlink);
277
272 rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path, 278 rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
273 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, 279 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
274 SMB2_OP_SET_INFO); 280 SMB2_OP_SET_INFO);
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 389fb9f8c84e..3d383489b9cf 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -549,19 +549,19 @@ smb2_is_valid_lease_break(char *buffer)
549 list_for_each(tmp1, &server->smb_ses_list) { 549 list_for_each(tmp1, &server->smb_ses_list) {
550 ses = list_entry(tmp1, struct cifs_ses, smb_ses_list); 550 ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
551 551
552 spin_lock(&cifs_file_list_lock);
553 list_for_each(tmp2, &ses->tcon_list) { 552 list_for_each(tmp2, &ses->tcon_list) {
554 tcon = list_entry(tmp2, struct cifs_tcon, 553 tcon = list_entry(tmp2, struct cifs_tcon,
555 tcon_list); 554 tcon_list);
555 spin_lock(&tcon->open_file_lock);
556 cifs_stats_inc( 556 cifs_stats_inc(
557 &tcon->stats.cifs_stats.num_oplock_brks); 557 &tcon->stats.cifs_stats.num_oplock_brks);
558 if (smb2_tcon_has_lease(tcon, rsp, lw)) { 558 if (smb2_tcon_has_lease(tcon, rsp, lw)) {
559 spin_unlock(&cifs_file_list_lock); 559 spin_unlock(&tcon->open_file_lock);
560 spin_unlock(&cifs_tcp_ses_lock); 560 spin_unlock(&cifs_tcp_ses_lock);
561 return true; 561 return true;
562 } 562 }
563 spin_unlock(&tcon->open_file_lock);
563 } 564 }
564 spin_unlock(&cifs_file_list_lock);
565 } 565 }
566 } 566 }
567 spin_unlock(&cifs_tcp_ses_lock); 567 spin_unlock(&cifs_tcp_ses_lock);
@@ -603,7 +603,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
603 tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); 603 tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
604 604
605 cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); 605 cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
606 spin_lock(&cifs_file_list_lock); 606 spin_lock(&tcon->open_file_lock);
607 list_for_each(tmp2, &tcon->openFileList) { 607 list_for_each(tmp2, &tcon->openFileList) {
608 cfile = list_entry(tmp2, struct cifsFileInfo, 608 cfile = list_entry(tmp2, struct cifsFileInfo,
609 tlist); 609 tlist);
@@ -615,7 +615,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
615 615
616 cifs_dbg(FYI, "file id match, oplock break\n"); 616 cifs_dbg(FYI, "file id match, oplock break\n");
617 cinode = CIFS_I(d_inode(cfile->dentry)); 617 cinode = CIFS_I(d_inode(cfile->dentry));
618 618 spin_lock(&cfile->file_info_lock);
619 if (!CIFS_CACHE_WRITE(cinode) && 619 if (!CIFS_CACHE_WRITE(cinode) &&
620 rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE) 620 rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
621 cfile->oplock_break_cancelled = true; 621 cfile->oplock_break_cancelled = true;
@@ -637,14 +637,14 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
637 clear_bit( 637 clear_bit(
638 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 638 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
639 &cinode->flags); 639 &cinode->flags);
640 640 spin_unlock(&cfile->file_info_lock);
641 queue_work(cifsiod_wq, &cfile->oplock_break); 641 queue_work(cifsiod_wq, &cfile->oplock_break);
642 642
643 spin_unlock(&cifs_file_list_lock); 643 spin_unlock(&tcon->open_file_lock);
644 spin_unlock(&cifs_tcp_ses_lock); 644 spin_unlock(&cifs_tcp_ses_lock);
645 return true; 645 return true;
646 } 646 }
647 spin_unlock(&cifs_file_list_lock); 647 spin_unlock(&tcon->open_file_lock);
648 spin_unlock(&cifs_tcp_ses_lock); 648 spin_unlock(&cifs_tcp_ses_lock);
649 cifs_dbg(FYI, "No matching file for oplock break\n"); 649 cifs_dbg(FYI, "No matching file for oplock break\n");
650 return true; 650 return true;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index d203c0329626..5d456ebb3813 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -28,6 +28,7 @@
28#include "cifs_unicode.h" 28#include "cifs_unicode.h"
29#include "smb2status.h" 29#include "smb2status.h"
30#include "smb2glob.h" 30#include "smb2glob.h"
31#include "cifs_ioctl.h"
31 32
32static int 33static int
33change_conf(struct TCP_Server_Info *server) 34change_conf(struct TCP_Server_Info *server)
@@ -70,6 +71,10 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
70 spin_lock(&server->req_lock); 71 spin_lock(&server->req_lock);
71 val = server->ops->get_credits_field(server, optype); 72 val = server->ops->get_credits_field(server, optype);
72 *val += add; 73 *val += add;
74 if (*val > 65000) {
75 *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
76 printk_once(KERN_WARNING "server overflowed SMB3 credits\n");
77 }
73 server->in_flight--; 78 server->in_flight--;
74 if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP) 79 if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
75 rc = change_conf(server); 80 rc = change_conf(server);
@@ -287,7 +292,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
287 cifs_dbg(FYI, "Link Speed %lld\n", 292 cifs_dbg(FYI, "Link Speed %lld\n",
288 le64_to_cpu(out_buf->LinkSpeed)); 293 le64_to_cpu(out_buf->LinkSpeed));
289 } 294 }
290 295 kfree(out_buf);
291 return rc; 296 return rc;
292} 297}
293#endif /* STATS2 */ 298#endif /* STATS2 */
@@ -541,6 +546,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
541 server->ops->set_oplock_level(cinode, oplock, fid->epoch, 546 server->ops->set_oplock_level(cinode, oplock, fid->epoch,
542 &fid->purge_cache); 547 &fid->purge_cache);
543 cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); 548 cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
549 memcpy(cfile->fid.create_guid, fid->create_guid, 16);
544} 550}
545 551
546static void 552static void
@@ -699,6 +705,7 @@ smb2_clone_range(const unsigned int xid,
699 705
700cchunk_out: 706cchunk_out:
701 kfree(pcchunk); 707 kfree(pcchunk);
708 kfree(retbuf);
702 return rc; 709 return rc;
703} 710}
704 711
@@ -823,7 +830,6 @@ smb2_duplicate_extents(const unsigned int xid,
823{ 830{
824 int rc; 831 int rc;
825 unsigned int ret_data_len; 832 unsigned int ret_data_len;
826 char *retbuf = NULL;
827 struct duplicate_extents_to_file dup_ext_buf; 833 struct duplicate_extents_to_file dup_ext_buf;
828 struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink); 834 struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
829 835
@@ -849,7 +855,7 @@ smb2_duplicate_extents(const unsigned int xid,
849 FSCTL_DUPLICATE_EXTENTS_TO_FILE, 855 FSCTL_DUPLICATE_EXTENTS_TO_FILE,
850 true /* is_fsctl */, (char *)&dup_ext_buf, 856 true /* is_fsctl */, (char *)&dup_ext_buf,
851 sizeof(struct duplicate_extents_to_file), 857 sizeof(struct duplicate_extents_to_file),
852 (char **)&retbuf, 858 NULL,
853 &ret_data_len); 859 &ret_data_len);
854 860
855 if (ret_data_len > 0) 861 if (ret_data_len > 0)
@@ -872,7 +878,6 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
872 struct cifsFileInfo *cfile) 878 struct cifsFileInfo *cfile)
873{ 879{
874 struct fsctl_set_integrity_information_req integr_info; 880 struct fsctl_set_integrity_information_req integr_info;
875 char *retbuf = NULL;
876 unsigned int ret_data_len; 881 unsigned int ret_data_len;
877 882
878 integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED); 883 integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
@@ -884,9 +889,53 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
884 FSCTL_SET_INTEGRITY_INFORMATION, 889 FSCTL_SET_INTEGRITY_INFORMATION,
885 true /* is_fsctl */, (char *)&integr_info, 890 true /* is_fsctl */, (char *)&integr_info,
886 sizeof(struct fsctl_set_integrity_information_req), 891 sizeof(struct fsctl_set_integrity_information_req),
892 NULL,
893 &ret_data_len);
894
895}
896
897static int
898smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
899 struct cifsFileInfo *cfile, void __user *ioc_buf)
900{
901 char *retbuf = NULL;
902 unsigned int ret_data_len = 0;
903 int rc;
904 struct smb_snapshot_array snapshot_in;
905
906 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
907 cfile->fid.volatile_fid,
908 FSCTL_SRV_ENUMERATE_SNAPSHOTS,
909 true /* is_fsctl */, NULL, 0 /* no input data */,
887 (char **)&retbuf, 910 (char **)&retbuf,
888 &ret_data_len); 911 &ret_data_len);
912 cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
913 rc, ret_data_len);
914 if (rc)
915 return rc;
889 916
917 if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
918 /* Fixup buffer */
919 if (copy_from_user(&snapshot_in, ioc_buf,
920 sizeof(struct smb_snapshot_array))) {
921 rc = -EFAULT;
922 kfree(retbuf);
923 return rc;
924 }
925 if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
926 rc = -ERANGE;
927 return rc;
928 }
929
930 if (ret_data_len > snapshot_in.snapshot_array_size)
931 ret_data_len = snapshot_in.snapshot_array_size;
932
933 if (copy_to_user(ioc_buf, retbuf, ret_data_len))
934 rc = -EFAULT;
935 }
936
937 kfree(retbuf);
938 return rc;
890} 939}
891 940
892static int 941static int
@@ -1041,7 +1090,7 @@ smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
1041static void 1090static void
1042smb2_new_lease_key(struct cifs_fid *fid) 1091smb2_new_lease_key(struct cifs_fid *fid)
1043{ 1092{
1044 get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE); 1093 generate_random_uuid(fid->lease_key);
1045} 1094}
1046 1095
1047#define SMB2_SYMLINK_STRUCT_SIZE \ 1096#define SMB2_SYMLINK_STRUCT_SIZE \
@@ -1654,6 +1703,7 @@ struct smb_version_operations smb21_operations = {
1654 .clone_range = smb2_clone_range, 1703 .clone_range = smb2_clone_range,
1655 .wp_retry_size = smb2_wp_retry_size, 1704 .wp_retry_size = smb2_wp_retry_size,
1656 .dir_needs_close = smb2_dir_needs_close, 1705 .dir_needs_close = smb2_dir_needs_close,
1706 .enum_snapshots = smb3_enum_snapshots,
1657}; 1707};
1658 1708
1659struct smb_version_operations smb30_operations = { 1709struct smb_version_operations smb30_operations = {
@@ -1740,6 +1790,7 @@ struct smb_version_operations smb30_operations = {
1740 .wp_retry_size = smb2_wp_retry_size, 1790 .wp_retry_size = smb2_wp_retry_size,
1741 .dir_needs_close = smb2_dir_needs_close, 1791 .dir_needs_close = smb2_dir_needs_close,
1742 .fallocate = smb3_fallocate, 1792 .fallocate = smb3_fallocate,
1793 .enum_snapshots = smb3_enum_snapshots,
1743}; 1794};
1744 1795
1745#ifdef CONFIG_CIFS_SMB311 1796#ifdef CONFIG_CIFS_SMB311
@@ -1827,6 +1878,7 @@ struct smb_version_operations smb311_operations = {
1827 .wp_retry_size = smb2_wp_retry_size, 1878 .wp_retry_size = smb2_wp_retry_size,
1828 .dir_needs_close = smb2_dir_needs_close, 1879 .dir_needs_close = smb2_dir_needs_close,
1829 .fallocate = smb3_fallocate, 1880 .fallocate = smb3_fallocate,
1881 .enum_snapshots = smb3_enum_snapshots,
1830}; 1882};
1831#endif /* CIFS_SMB311 */ 1883#endif /* CIFS_SMB311 */
1832 1884
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 29e06db5f187..5ca5ea4668a1 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -100,7 +100,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
100 hdr->ProtocolId = SMB2_PROTO_NUMBER; 100 hdr->ProtocolId = SMB2_PROTO_NUMBER;
101 hdr->StructureSize = cpu_to_le16(64); 101 hdr->StructureSize = cpu_to_le16(64);
102 hdr->Command = smb2_cmd; 102 hdr->Command = smb2_cmd;
103 hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */ 103 if (tcon && tcon->ses && tcon->ses->server) {
104 struct TCP_Server_Info *server = tcon->ses->server;
105
106 spin_lock(&server->req_lock);
107 /* Request up to 2 credits but don't go over the limit. */
108 if (server->credits >= server->max_credits)
109 hdr->CreditRequest = cpu_to_le16(0);
110 else
111 hdr->CreditRequest = cpu_to_le16(
112 min_t(int, server->max_credits -
113 server->credits, 2));
114 spin_unlock(&server->req_lock);
115 } else {
116 hdr->CreditRequest = cpu_to_le16(2);
117 }
104 hdr->ProcessId = cpu_to_le32((__u16)current->tgid); 118 hdr->ProcessId = cpu_to_le32((__u16)current->tgid);
105 119
106 if (!tcon) 120 if (!tcon)
@@ -236,8 +250,13 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
236 } 250 }
237 251
238 cifs_mark_open_files_invalid(tcon); 252 cifs_mark_open_files_invalid(tcon);
253
239 rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage); 254 rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
240 mutex_unlock(&tcon->ses->session_mutex); 255 mutex_unlock(&tcon->ses->session_mutex);
256
257 if (tcon->use_persistent)
258 cifs_reopen_persistent_handles(tcon);
259
241 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 260 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
242 if (rc) 261 if (rc)
243 goto out; 262 goto out;
@@ -574,59 +593,42 @@ vneg_out:
574 return -EIO; 593 return -EIO;
575} 594}
576 595
577int 596struct SMB2_sess_data {
578SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, 597 unsigned int xid;
579 const struct nls_table *nls_cp) 598 struct cifs_ses *ses;
599 struct nls_table *nls_cp;
600 void (*func)(struct SMB2_sess_data *);
601 int result;
602 u64 previous_session;
603
604 /* we will send the SMB in three pieces:
605 * a fixed length beginning part, an optional
606 * SPNEGO blob (which can be zero length), and a
607 * last part which will include the strings
608 * and rest of bcc area. This allows us to avoid
609 * a large buffer 17K allocation
610 */
611 int buf0_type;
612 struct kvec iov[2];
613};
614
615static int
616SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
580{ 617{
618 int rc;
619 struct cifs_ses *ses = sess_data->ses;
581 struct smb2_sess_setup_req *req; 620 struct smb2_sess_setup_req *req;
582 struct smb2_sess_setup_rsp *rsp = NULL;
583 struct kvec iov[2];
584 int rc = 0;
585 int resp_buftype = CIFS_NO_BUFFER;
586 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
587 struct TCP_Server_Info *server = ses->server; 621 struct TCP_Server_Info *server = ses->server;
588 u16 blob_length = 0;
589 struct key *spnego_key = NULL;
590 char *security_blob = NULL;
591 unsigned char *ntlmssp_blob = NULL;
592 bool use_spnego = false; /* else use raw ntlmssp */
593
594 cifs_dbg(FYI, "Session Setup\n");
595
596 if (!server) {
597 WARN(1, "%s: server is NULL!\n", __func__);
598 return -EIO;
599 }
600
601 /*
602 * If we are here due to reconnect, free per-smb session key
603 * in case signing was required.
604 */
605 kfree(ses->auth_key.response);
606 ses->auth_key.response = NULL;
607
608 /*
609 * If memory allocation is successful, caller of this function
610 * frees it.
611 */
612 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
613 if (!ses->ntlmssp)
614 return -ENOMEM;
615 ses->ntlmssp->sesskey_per_smbsess = true;
616
617 /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */
618 if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP)
619 ses->sectype = RawNTLMSSP;
620
621ssetup_ntlmssp_authenticate:
622 if (phase == NtLmChallenge)
623 phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
624 622
625 rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **) &req); 623 rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **) &req);
626 if (rc) 624 if (rc)
627 return rc; 625 return rc;
628 626
629 req->hdr.SessionId = 0; /* First session, not a reauthenticate */ 627 req->hdr.SessionId = 0; /* First session, not a reauthenticate */
628
629 /* if reconnect, we need to send previous sess id, otherwise it is 0 */
630 req->PreviousSessionId = sess_data->previous_session;
631
630 req->Flags = 0; /* MBZ */ 632 req->Flags = 0; /* MBZ */
631 /* to enable echos and oplocks */ 633 /* to enable echos and oplocks */
632 req->hdr.CreditRequest = cpu_to_le16(3); 634 req->hdr.CreditRequest = cpu_to_le16(3);
@@ -642,199 +644,368 @@ ssetup_ntlmssp_authenticate:
642 req->Capabilities = 0; 644 req->Capabilities = 0;
643 req->Channel = 0; /* MBZ */ 645 req->Channel = 0; /* MBZ */
644 646
645 iov[0].iov_base = (char *)req; 647 sess_data->iov[0].iov_base = (char *)req;
646 /* 4 for rfc1002 length field and 1 for pad */ 648 /* 4 for rfc1002 length field and 1 for pad */
647 iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; 649 sess_data->iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
650 /*
651 * This variable will be used to clear the buffer
652 * allocated above in case of any error in the calling function.
653 */
654 sess_data->buf0_type = CIFS_SMALL_BUFFER;
648 655
649 if (ses->sectype == Kerberos) { 656 return 0;
650#ifdef CONFIG_CIFS_UPCALL 657}
651 struct cifs_spnego_msg *msg;
652 658
653 spnego_key = cifs_get_spnego_key(ses); 659static void
654 if (IS_ERR(spnego_key)) { 660SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
655 rc = PTR_ERR(spnego_key); 661{
656 spnego_key = NULL; 662 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
657 goto ssetup_exit; 663 sess_data->buf0_type = CIFS_NO_BUFFER;
658 } 664}
659 665
660 msg = spnego_key->payload.data[0]; 666static int
661 /* 667SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
662 * check version field to make sure that cifs.upcall is 668{
663 * sending us a response in an expected form 669 int rc;
664 */ 670 struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
665 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
666 cifs_dbg(VFS,
667 "bad cifs.upcall version. Expected %d got %d",
668 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
669 rc = -EKEYREJECTED;
670 goto ssetup_exit;
671 }
672 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
673 GFP_KERNEL);
674 if (!ses->auth_key.response) {
675 cifs_dbg(VFS,
676 "Kerberos can't allocate (%u bytes) memory",
677 msg->sesskey_len);
678 rc = -ENOMEM;
679 goto ssetup_exit;
680 }
681 ses->auth_key.len = msg->sesskey_len;
682 blob_length = msg->secblob_len;
683 iov[1].iov_base = msg->data + msg->sesskey_len;
684 iov[1].iov_len = blob_length;
685#else
686 rc = -EOPNOTSUPP;
687 goto ssetup_exit;
688#endif /* CONFIG_CIFS_UPCALL */
689 } else if (phase == NtLmNegotiate) { /* if not krb5 must be ntlmssp */
690 ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
691 GFP_KERNEL);
692 if (ntlmssp_blob == NULL) {
693 rc = -ENOMEM;
694 goto ssetup_exit;
695 }
696 build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
697 if (use_spnego) {
698 /* blob_length = build_spnego_ntlmssp_blob(
699 &security_blob,
700 sizeof(struct _NEGOTIATE_MESSAGE),
701 ntlmssp_blob); */
702 /* BB eventually need to add this */
703 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
704 rc = -EOPNOTSUPP;
705 kfree(ntlmssp_blob);
706 goto ssetup_exit;
707 } else {
708 blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
709 /* with raw NTLMSSP we don't encapsulate in SPNEGO */
710 security_blob = ntlmssp_blob;
711 }
712 iov[1].iov_base = security_blob;
713 iov[1].iov_len = blob_length;
714 } else if (phase == NtLmAuthenticate) {
715 req->hdr.SessionId = ses->Suid;
716 rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
717 nls_cp);
718 if (rc) {
719 cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n",
720 rc);
721 goto ssetup_exit; /* BB double check error handling */
722 }
723 if (use_spnego) {
724 /* blob_length = build_spnego_ntlmssp_blob(
725 &security_blob,
726 blob_length,
727 ntlmssp_blob); */
728 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
729 rc = -EOPNOTSUPP;
730 kfree(ntlmssp_blob);
731 goto ssetup_exit;
732 } else {
733 security_blob = ntlmssp_blob;
734 }
735 iov[1].iov_base = security_blob;
736 iov[1].iov_len = blob_length;
737 } else {
738 cifs_dbg(VFS, "illegal ntlmssp phase\n");
739 rc = -EIO;
740 goto ssetup_exit;
741 }
742 671
743 /* Testing shows that buffer offset must be at location of Buffer[0] */ 672 /* Testing shows that buffer offset must be at location of Buffer[0] */
744 req->SecurityBufferOffset = 673 req->SecurityBufferOffset =
745 cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 674 cpu_to_le16(sizeof(struct smb2_sess_setup_req) -
746 1 /* pad */ - 4 /* rfc1001 len */); 675 1 /* pad */ - 4 /* rfc1001 len */);
747 req->SecurityBufferLength = cpu_to_le16(blob_length); 676 req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
748 677
749 inc_rfc1001_len(req, blob_length - 1 /* pad */); 678 inc_rfc1001_len(req, sess_data->iov[1].iov_len - 1 /* pad */);
750 679
751 /* BB add code to build os and lm fields */ 680 /* BB add code to build os and lm fields */
752 681
753 rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 682 rc = SendReceive2(sess_data->xid, sess_data->ses,
754 CIFS_LOG_ERROR | CIFS_NEG_OP); 683 sess_data->iov, 2,
684 &sess_data->buf0_type,
685 CIFS_LOG_ERROR | CIFS_NEG_OP);
755 686
756 kfree(security_blob); 687 return rc;
757 rsp = (struct smb2_sess_setup_rsp *)iov[0].iov_base; 688}
758 ses->Suid = rsp->hdr.SessionId; 689
759 if (resp_buftype != CIFS_NO_BUFFER && 690static int
760 rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) { 691SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
761 if (phase != NtLmNegotiate) { 692{
762 cifs_dbg(VFS, "Unexpected more processing error\n"); 693 int rc = 0;
763 goto ssetup_exit; 694 struct cifs_ses *ses = sess_data->ses;
764 } 695
765 if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 != 696 mutex_lock(&ses->server->srv_mutex);
766 le16_to_cpu(rsp->SecurityBufferOffset)) { 697 if (ses->server->sign && ses->server->ops->generate_signingkey) {
767 cifs_dbg(VFS, "Invalid security buffer offset %d\n", 698 rc = ses->server->ops->generate_signingkey(ses);
768 le16_to_cpu(rsp->SecurityBufferOffset)); 699 kfree(ses->auth_key.response);
769 rc = -EIO; 700 ses->auth_key.response = NULL;
770 goto ssetup_exit; 701 if (rc) {
702 cifs_dbg(FYI,
703 "SMB3 session key generation failed\n");
704 mutex_unlock(&ses->server->srv_mutex);
705 goto keygen_exit;
771 } 706 }
707 }
708 if (!ses->server->session_estab) {
709 ses->server->sequence_number = 0x2;
710 ses->server->session_estab = true;
711 }
712 mutex_unlock(&ses->server->srv_mutex);
713
714 cifs_dbg(FYI, "SMB2/3 session established successfully\n");
715 spin_lock(&GlobalMid_Lock);
716 ses->status = CifsGood;
717 ses->need_reconnect = false;
718 spin_unlock(&GlobalMid_Lock);
772 719
773 /* NTLMSSP Negotiate sent now processing challenge (response) */ 720keygen_exit:
774 phase = NtLmChallenge; /* process ntlmssp challenge */ 721 if (!ses->server->sign) {
775 rc = 0; /* MORE_PROCESSING is not an error here but expected */ 722 kfree(ses->auth_key.response);
776 rc = decode_ntlmssp_challenge(rsp->Buffer, 723 ses->auth_key.response = NULL;
777 le16_to_cpu(rsp->SecurityBufferLength), ses); 724 }
725 return rc;
726}
727
728#ifdef CONFIG_CIFS_UPCALL
729static void
730SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
731{
732 int rc;
733 struct cifs_ses *ses = sess_data->ses;
734 struct cifs_spnego_msg *msg;
735 struct key *spnego_key = NULL;
736 struct smb2_sess_setup_rsp *rsp = NULL;
737
738 rc = SMB2_sess_alloc_buffer(sess_data);
739 if (rc)
740 goto out;
741
742 spnego_key = cifs_get_spnego_key(ses);
743 if (IS_ERR(spnego_key)) {
744 rc = PTR_ERR(spnego_key);
745 spnego_key = NULL;
746 goto out;
778 } 747 }
779 748
749 msg = spnego_key->payload.data[0];
780 /* 750 /*
781 * BB eventually add code for SPNEGO decoding of NtlmChallenge blob, 751 * check version field to make sure that cifs.upcall is
782 * but at least the raw NTLMSSP case works. 752 * sending us a response in an expected form
783 */ 753 */
754 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
755 cifs_dbg(VFS,
756 "bad cifs.upcall version. Expected %d got %d",
757 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
758 rc = -EKEYREJECTED;
759 goto out_put_spnego_key;
760 }
761
762 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
763 GFP_KERNEL);
764 if (!ses->auth_key.response) {
765 cifs_dbg(VFS,
766 "Kerberos can't allocate (%u bytes) memory",
767 msg->sesskey_len);
768 rc = -ENOMEM;
769 goto out_put_spnego_key;
770 }
771 ses->auth_key.len = msg->sesskey_len;
772
773 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
774 sess_data->iov[1].iov_len = msg->secblob_len;
775
776 rc = SMB2_sess_sendreceive(sess_data);
777 if (rc)
778 goto out_put_spnego_key;
779
780 rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
781 ses->Suid = rsp->hdr.SessionId;
782
783 ses->session_flags = le16_to_cpu(rsp->SessionFlags);
784 if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
785 cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
786
787 rc = SMB2_sess_establish_session(sess_data);
788out_put_spnego_key:
789 key_invalidate(spnego_key);
790 key_put(spnego_key);
791out:
792 sess_data->result = rc;
793 sess_data->func = NULL;
794 SMB2_sess_free_buffer(sess_data);
795}
796#else
797static void
798SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
799{
800 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
801 sess_data->result = -EOPNOTSUPP;
802 sess_data->func = NULL;
803}
804#endif
805
806static void
807SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
808
809static void
810SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
811{
812 int rc;
813 struct cifs_ses *ses = sess_data->ses;
814 struct smb2_sess_setup_rsp *rsp = NULL;
815 char *ntlmssp_blob = NULL;
816 bool use_spnego = false; /* else use raw ntlmssp */
817 u16 blob_length = 0;
818
784 /* 819 /*
785 * No tcon so can't do 820 * If memory allocation is successful, caller of this function
786 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); 821 * frees it.
787 */ 822 */
788 if (rc != 0) 823 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
789 goto ssetup_exit; 824 if (!ses->ntlmssp) {
825 rc = -ENOMEM;
826 goto out_err;
827 }
828 ses->ntlmssp->sesskey_per_smbsess = true;
829
830 rc = SMB2_sess_alloc_buffer(sess_data);
831 if (rc)
832 goto out_err;
833
834 ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
835 GFP_KERNEL);
836 if (ntlmssp_blob == NULL) {
837 rc = -ENOMEM;
838 goto out;
839 }
840
841 build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
842 if (use_spnego) {
843 /* BB eventually need to add this */
844 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
845 rc = -EOPNOTSUPP;
846 goto out;
847 } else {
848 blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
849 /* with raw NTLMSSP we don't encapsulate in SPNEGO */
850 }
851 sess_data->iov[1].iov_base = ntlmssp_blob;
852 sess_data->iov[1].iov_len = blob_length;
853
854 rc = SMB2_sess_sendreceive(sess_data);
855 rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
856
857 /* If true, rc here is expected and not an error */
858 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
859 rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
860 rc = 0;
861
862 if (rc)
863 goto out;
864
865 if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
866 le16_to_cpu(rsp->SecurityBufferOffset)) {
867 cifs_dbg(VFS, "Invalid security buffer offset %d\n",
868 le16_to_cpu(rsp->SecurityBufferOffset));
869 rc = -EIO;
870 goto out;
871 }
872 rc = decode_ntlmssp_challenge(rsp->Buffer,
873 le16_to_cpu(rsp->SecurityBufferLength), ses);
874 if (rc)
875 goto out;
876
877 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
878
790 879
880 ses->Suid = rsp->hdr.SessionId;
791 ses->session_flags = le16_to_cpu(rsp->SessionFlags); 881 ses->session_flags = le16_to_cpu(rsp->SessionFlags);
792 if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) 882 if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
793 cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); 883 cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
794ssetup_exit:
795 free_rsp_buf(resp_buftype, rsp);
796
797 /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
798 if ((phase == NtLmChallenge) && (rc == 0))
799 goto ssetup_ntlmssp_authenticate;
800 884
885out:
886 kfree(ntlmssp_blob);
887 SMB2_sess_free_buffer(sess_data);
801 if (!rc) { 888 if (!rc) {
802 mutex_lock(&server->srv_mutex); 889 sess_data->result = 0;
803 if (server->sign && server->ops->generate_signingkey) { 890 sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
804 rc = server->ops->generate_signingkey(ses); 891 return;
805 kfree(ses->auth_key.response);
806 ses->auth_key.response = NULL;
807 if (rc) {
808 cifs_dbg(FYI,
809 "SMB3 session key generation failed\n");
810 mutex_unlock(&server->srv_mutex);
811 goto keygen_exit;
812 }
813 }
814 if (!server->session_estab) {
815 server->sequence_number = 0x2;
816 server->session_estab = true;
817 }
818 mutex_unlock(&server->srv_mutex);
819
820 cifs_dbg(FYI, "SMB2/3 session established successfully\n");
821 spin_lock(&GlobalMid_Lock);
822 ses->status = CifsGood;
823 ses->need_reconnect = false;
824 spin_unlock(&GlobalMid_Lock);
825 } 892 }
893out_err:
894 kfree(ses->ntlmssp);
895 ses->ntlmssp = NULL;
896 sess_data->result = rc;
897 sess_data->func = NULL;
898}
826 899
827keygen_exit: 900static void
828 if (!server->sign) { 901SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
829 kfree(ses->auth_key.response); 902{
830 ses->auth_key.response = NULL; 903 int rc;
904 struct cifs_ses *ses = sess_data->ses;
905 struct smb2_sess_setup_req *req;
906 struct smb2_sess_setup_rsp *rsp = NULL;
907 unsigned char *ntlmssp_blob = NULL;
908 bool use_spnego = false; /* else use raw ntlmssp */
909 u16 blob_length = 0;
910
911 rc = SMB2_sess_alloc_buffer(sess_data);
912 if (rc)
913 goto out;
914
915 req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
916 req->hdr.SessionId = ses->Suid;
917
918 rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
919 sess_data->nls_cp);
920 if (rc) {
921 cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc);
922 goto out;
831 } 923 }
832 if (spnego_key) { 924
833 key_invalidate(spnego_key); 925 if (use_spnego) {
834 key_put(spnego_key); 926 /* BB eventually need to add this */
927 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
928 rc = -EOPNOTSUPP;
929 goto out;
835 } 930 }
931 sess_data->iov[1].iov_base = ntlmssp_blob;
932 sess_data->iov[1].iov_len = blob_length;
933
934 rc = SMB2_sess_sendreceive(sess_data);
935 if (rc)
936 goto out;
937
938 rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
939
940 ses->Suid = rsp->hdr.SessionId;
941 ses->session_flags = le16_to_cpu(rsp->SessionFlags);
942 if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
943 cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
944
945 rc = SMB2_sess_establish_session(sess_data);
946out:
947 kfree(ntlmssp_blob);
948 SMB2_sess_free_buffer(sess_data);
836 kfree(ses->ntlmssp); 949 kfree(ses->ntlmssp);
950 ses->ntlmssp = NULL;
951 sess_data->result = rc;
952 sess_data->func = NULL;
953}
837 954
955static int
956SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
957{
958 if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP)
959 ses->sectype = RawNTLMSSP;
960
961 switch (ses->sectype) {
962 case Kerberos:
963 sess_data->func = SMB2_auth_kerberos;
964 break;
965 case RawNTLMSSP:
966 sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
967 break;
968 default:
969 cifs_dbg(VFS, "secType %d not supported!\n", ses->sectype);
970 return -EOPNOTSUPP;
971 }
972
973 return 0;
974}
975
976int
977SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
978 const struct nls_table *nls_cp)
979{
980 int rc = 0;
981 struct TCP_Server_Info *server = ses->server;
982 struct SMB2_sess_data *sess_data;
983
984 cifs_dbg(FYI, "Session Setup\n");
985
986 if (!server) {
987 WARN(1, "%s: server is NULL!\n", __func__);
988 return -EIO;
989 }
990
991 sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL);
992 if (!sess_data)
993 return -ENOMEM;
994
995 rc = SMB2_select_sec(ses, sess_data);
996 if (rc)
997 goto out;
998 sess_data->xid = xid;
999 sess_data->ses = ses;
1000 sess_data->buf0_type = CIFS_NO_BUFFER;
1001 sess_data->nls_cp = (struct nls_table *) nls_cp;
1002
1003 while (sess_data->func)
1004 sess_data->func(sess_data);
1005
1006 rc = sess_data->result;
1007out:
1008 kfree(sess_data);
838 return rc; 1009 return rc;
839} 1010}
840 1011
@@ -1164,7 +1335,7 @@ create_durable_v2_buf(struct cifs_fid *pfid)
1164 1335
1165 buf->dcontext.Timeout = 0; /* Should this be configurable by workload */ 1336 buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
1166 buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); 1337 buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
1167 get_random_bytes(buf->dcontext.CreateGuid, 16); 1338 generate_random_uuid(buf->dcontext.CreateGuid);
1168 memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); 1339 memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
1169 1340
1170 /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */ 1341 /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
@@ -2057,6 +2228,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
2057 if (rdata->credits) { 2228 if (rdata->credits) {
2058 buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, 2229 buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
2059 SMB2_MAX_BUFFER_SIZE)); 2230 SMB2_MAX_BUFFER_SIZE));
2231 buf->CreditRequest = buf->CreditCharge;
2060 spin_lock(&server->req_lock); 2232 spin_lock(&server->req_lock);
2061 server->credits += rdata->credits - 2233 server->credits += rdata->credits -
2062 le16_to_cpu(buf->CreditCharge); 2234 le16_to_cpu(buf->CreditCharge);
@@ -2243,6 +2415,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
2243 if (wdata->credits) { 2415 if (wdata->credits) {
2244 req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, 2416 req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
2245 SMB2_MAX_BUFFER_SIZE)); 2417 SMB2_MAX_BUFFER_SIZE));
2418 req->hdr.CreditRequest = req->hdr.CreditCharge;
2246 spin_lock(&server->req_lock); 2419 spin_lock(&server->req_lock);
2247 server->credits += wdata->credits - 2420 server->credits += wdata->credits -
2248 le16_to_cpu(req->hdr.CreditCharge); 2421 le16_to_cpu(req->hdr.CreditCharge);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index ff88d9feb01e..fd3709e8de33 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -276,7 +276,7 @@ struct smb2_sess_setup_req {
276 __le32 Channel; 276 __le32 Channel;
277 __le16 SecurityBufferOffset; 277 __le16 SecurityBufferOffset;
278 __le16 SecurityBufferLength; 278 __le16 SecurityBufferLength;
279 __le64 PreviousSessionId; 279 __u64 PreviousSessionId;
280 __u8 Buffer[1]; /* variable length GSS security buffer */ 280 __u8 Buffer[1]; /* variable length GSS security buffer */
281} __packed; 281} __packed;
282 282
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 5e23f64c0804..20af5187ba63 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -33,7 +33,8 @@
33 33
34#define MAX_EA_VALUE_SIZE 65535 34#define MAX_EA_VALUE_SIZE 65535
35#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" 35#define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
36 36#define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
37#define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
37/* BB need to add server (Samba e.g) support for security and trusted prefix */ 38/* BB need to add server (Samba e.g) support for security and trusted prefix */
38 39
39enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT }; 40enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT };
@@ -144,6 +145,54 @@ out:
144 return rc; 145 return rc;
145} 146}
146 147
148static int cifs_attrib_get(struct dentry *dentry,
149 struct inode *inode, void *value,
150 size_t size)
151{
152 ssize_t rc;
153 __u32 *pattribute;
154
155 rc = cifs_revalidate_dentry_attr(dentry);
156
157 if (rc)
158 return rc;
159
160 if ((value == NULL) || (size == 0))
161 return sizeof(__u32);
162 else if (size < sizeof(__u32))
163 return -ERANGE;
164
165 /* return dos attributes as pseudo xattr */
166 pattribute = (__u32 *)value;
167 *pattribute = CIFS_I(inode)->cifsAttrs;
168
169 return sizeof(__u32);
170}
171
172static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
173 void *value, size_t size)
174{
175 ssize_t rc;
176 __u64 * pcreatetime;
177
178 rc = cifs_revalidate_dentry_attr(dentry);
179 if (rc)
180 return rc;
181
182 if ((value == NULL) || (size == 0))
183 return sizeof(__u64);
184 else if (size < sizeof(__u64))
185 return -ERANGE;
186
187 /* return dos attributes as pseudo xattr */
188 pcreatetime = (__u64 *)value;
189 *pcreatetime = CIFS_I(inode)->createtime;
190 return sizeof(__u64);
191
192 return rc;
193}
194
195
147static int cifs_xattr_get(const struct xattr_handler *handler, 196static int cifs_xattr_get(const struct xattr_handler *handler,
148 struct dentry *dentry, struct inode *inode, 197 struct dentry *dentry, struct inode *inode,
149 const char *name, void *value, size_t size) 198 const char *name, void *value, size_t size)
@@ -168,10 +217,19 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
168 rc = -ENOMEM; 217 rc = -ENOMEM;
169 goto out; 218 goto out;
170 } 219 }
171 /* return dos attributes as pseudo xattr */ 220
172 /* return alt name if available as pseudo attr */ 221 /* return alt name if available as pseudo attr */
173 switch (handler->flags) { 222 switch (handler->flags) {
174 case XATTR_USER: 223 case XATTR_USER:
224 cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
225 if (strcmp(name, CIFS_XATTR_ATTRIB) == 0) {
226 rc = cifs_attrib_get(dentry, inode, value, size);
227 break;
228 } else if (strcmp(name, CIFS_XATTR_CREATETIME) == 0) {
229 rc = cifs_creation_time_get(dentry, inode, value, size);
230 break;
231 }
232
175 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 233 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
176 goto out; 234 goto out;
177 235