Skip to content

Commit b08cd74

Browse files
committed
Merge tag '6.1-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
Pull more cifs updates from Steve French: - fix a regression in guest mounts to old servers - improvements to directory leasing (caching directory entries safely beyond the root directory) - symlink improvement (reducing roundtrips needed to process symlinks) - an lseek fix (to problem where some dir entries could be skipped) - improved ioctl for returning more detailed information on directory change notifications - clarify multichannel interface query warning - cleanup fix (for better aligning buffers using ALIGN and round_up) - a compounding fix - fix some uninitialized variable bugs found by Coverity and the kernel test robot * tag '6.1-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: smb3: improve SMB3 change notification support cifs: lease key is uninitialized in two additional functions when smb1 cifs: lease key is uninitialized in smb1 paths smb3: must initialize two ACL struct fields to zero cifs: fix double-fault crash during ntlmssp cifs: fix static checker warning cifs: use ALIGN() and round_up() macros cifs: find and use the dentry for cached non-root directories also cifs: enable caching of directories for which a lease is held cifs: prevent copying past input buffer boundaries cifs: fix uninitialised var in smb2_compound_op() cifs: improve symlink handling for smb2+ smb3: clarify multichannel warning cifs: fix regression in very old smb1 mounts cifs: fix skipping to incorrect offset in emit_cached_dirents
2 parents 8049387 + e3e9463 commit b08cd74

23 files changed

+922
-726
lines changed

fs/cifs/cached_dir.c

Lines changed: 284 additions & 185 deletions
Large diffs are not rendered by default.

fs/cifs/cached_dir.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,32 @@ struct cached_dirents {
3131
};
3232

3333
struct cached_fid {
34+
struct list_head entry;
35+
struct cached_fids *cfids;
3436
const char *path;
35-
bool is_valid:1; /* Do we have a useable root fid */
36-
bool file_all_info_is_valid:1;
3737
bool has_lease:1;
38+
bool is_open:1;
39+
bool on_list:1;
40+
bool file_all_info_is_valid:1;
3841
unsigned long time; /* jiffies of when lease was taken */
3942
struct kref refcount;
4043
struct cifs_fid fid;
41-
struct mutex fid_mutex;
44+
spinlock_t fid_lock;
4245
struct cifs_tcon *tcon;
4346
struct dentry *dentry;
4447
struct work_struct lease_break;
4548
struct smb2_file_all_info file_all_info;
4649
struct cached_dirents dirents;
4750
};
4851

52+
#define MAX_CACHED_FIDS 16
4953
struct cached_fids {
50-
struct mutex cfid_list_mutex;
51-
struct cached_fid *cfid;
54+
/* Must be held when:
55+
* - accessing the cfids->entries list
56+
*/
57+
spinlock_t cfid_list_lock;
58+
int num_entries;
59+
struct list_head entries;
5260
};
5361

5462
extern struct cached_fids *init_cached_dirs(void);
@@ -61,8 +69,6 @@ extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
6169
struct dentry *dentry,
6270
struct cached_fid **cfid);
6371
extern void close_cached_dir(struct cached_fid *cfid);
64-
extern void close_cached_dir_lease(struct cached_fid *cfid);
65-
extern void close_cached_dir_lease_locked(struct cached_fid *cfid);
6672
extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
6773
extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
6874
extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);

fs/cifs/cifs_ioctl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ struct smb3_notify {
9191
bool watch_tree;
9292
} __packed;
9393

94+
struct smb3_notify_info {
95+
__u32 completion_filter;
96+
bool watch_tree;
97+
__u32 data_len; /* size of notify data below */
98+
__u8 notify_data[];
99+
} __packed;
100+
94101
#define CIFS_IOCTL_MAGIC 0xCF
95102
#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
96103
#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
@@ -100,6 +107,7 @@ struct smb3_notify {
100107
#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
101108
#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
102109
#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
110+
#define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info)
103111
#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)
104112

105113
/*

fs/cifs/cifsfs.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ cifs_alloc_inode(struct super_block *sb)
396396
cifs_inode->epoch = 0;
397397
spin_lock_init(&cifs_inode->open_file_lock);
398398
generate_random_uuid(cifs_inode->lease_key);
399+
cifs_inode->symlink_target = NULL;
399400

400401
/*
401402
* Can not set i_flags here - they get immediately overwritten to zero
@@ -412,7 +413,11 @@ cifs_alloc_inode(struct super_block *sb)
412413
static void
413414
cifs_free_inode(struct inode *inode)
414415
{
415-
kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
416+
struct cifsInodeInfo *cinode = CIFS_I(inode);
417+
418+
if (S_ISLNK(inode->i_mode))
419+
kfree(cinode->symlink_target);
420+
kmem_cache_free(cifs_inode_cachep, cinode);
416421
}
417422

418423
static void
@@ -1139,7 +1144,7 @@ const struct inode_operations cifs_file_inode_ops = {
11391144
};
11401145

11411146
const struct inode_operations cifs_symlink_inode_ops = {
1142-
.get_link = cifs_get_link,
1147+
.get_link = simple_get_link,
11431148
.permission = cifs_permission,
11441149
.listxattr = cifs_listxattr,
11451150
};

fs/cifs/cifsglob.h

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ struct cifs_cred {
185185
struct cifs_ace *aces;
186186
};
187187

188+
struct cifs_open_info_data {
189+
char *symlink_target;
190+
union {
191+
struct smb2_file_all_info fi;
192+
struct smb311_posix_qinfo posix_fi;
193+
};
194+
};
195+
196+
static inline void cifs_free_open_info(struct cifs_open_info_data *data)
197+
{
198+
kfree(data->symlink_target);
199+
}
200+
188201
/*
189202
*****************************************************************
190203
* Except the CIFS PDUs themselves all the
@@ -307,20 +320,20 @@ struct smb_version_operations {
307320
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
308321
struct cifs_sb_info *, const char *);
309322
/* query path data from the server */
310-
int (*query_path_info)(const unsigned int, struct cifs_tcon *,
311-
struct cifs_sb_info *, const char *,
312-
FILE_ALL_INFO *, bool *, bool *);
323+
int (*query_path_info)(const unsigned int xid, struct cifs_tcon *tcon,
324+
struct cifs_sb_info *cifs_sb, const char *full_path,
325+
struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
313326
/* query file data from the server */
314-
int (*query_file_info)(const unsigned int, struct cifs_tcon *,
315-
struct cifs_fid *, FILE_ALL_INFO *);
327+
int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon,
328+
struct cifsFileInfo *cfile, struct cifs_open_info_data *data);
316329
/* query reparse tag from srv to determine which type of special file */
317330
int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon,
318331
struct cifs_sb_info *cifs_sb, const char *path,
319332
__u32 *reparse_tag);
320333
/* get server index number */
321-
int (*get_srv_inum)(const unsigned int, struct cifs_tcon *,
322-
struct cifs_sb_info *, const char *,
323-
u64 *uniqueid, FILE_ALL_INFO *);
334+
int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon,
335+
struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid,
336+
struct cifs_open_info_data *data);
324337
/* set size by path */
325338
int (*set_path_size)(const unsigned int, struct cifs_tcon *,
326339
const char *, __u64, struct cifs_sb_info *, bool);
@@ -369,8 +382,8 @@ struct smb_version_operations {
369382
struct cifs_sb_info *, const char *,
370383
char **, bool);
371384
/* open a file for non-posix mounts */
372-
int (*open)(const unsigned int, struct cifs_open_parms *,
373-
__u32 *, FILE_ALL_INFO *);
385+
int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
386+
void *buf);
374387
/* set fid protocol-specific info */
375388
void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
376389
/* close a file */
@@ -441,7 +454,7 @@ struct smb_version_operations {
441454
int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
442455
struct cifsFileInfo *src_file, void __user *);
443456
int (*notify)(const unsigned int xid, struct file *pfile,
444-
void __user *pbuf);
457+
void __user *pbuf, bool return_changes);
445458
int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
446459
struct cifs_sb_info *, const unsigned char *,
447460
char *, unsigned int *);
@@ -1123,6 +1136,7 @@ struct cifs_fattr {
11231136
struct timespec64 cf_mtime;
11241137
struct timespec64 cf_ctime;
11251138
u32 cf_cifstag;
1139+
char *cf_symlink_target;
11261140
};
11271141

11281142
/*
@@ -1385,6 +1399,7 @@ struct cifsFileInfo {
13851399
struct work_struct put; /* work for the final part of _put */
13861400
struct delayed_work deferred;
13871401
bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
1402+
char *symlink_target;
13881403
};
13891404

13901405
struct cifs_io_parms {
@@ -1543,6 +1558,7 @@ struct cifsInodeInfo {
15431558
struct list_head deferred_closes; /* list of deferred closes */
15441559
spinlock_t deferred_lock; /* protection on deferred list */
15451560
bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
1561+
char *symlink_target;
15461562
};
15471563

15481564
static inline struct cifsInodeInfo *
@@ -2111,4 +2127,14 @@ static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses)
21112127
return sizeof(ses->workstation_name);
21122128
}
21132129

2130+
static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const FILE_ALL_INFO *src)
2131+
{
2132+
memcpy(dst, src, (size_t)((u8 *)&src->AccessFlags - (u8 *)src));
2133+
dst->AccessFlags = src->AccessFlags;
2134+
dst->CurrentByteOffset = src->CurrentByteOffset;
2135+
dst->Mode = src->Mode;
2136+
dst->AlignmentRequirement = src->AlignmentRequirement;
2137+
dst->FileNameLength = src->FileNameLength;
2138+
}
2139+
21142140
#endif /* _CIFS_GLOB_H */

fs/cifs/cifsproto.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,9 @@ extern int cifs_unlock_range(struct cifsFileInfo *cfile,
182182
extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
183183

184184
extern void cifs_down_write(struct rw_semaphore *sem);
185-
extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid,
186-
struct file *file,
187-
struct tcon_link *tlink,
188-
__u32 oplock);
185+
struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
186+
struct tcon_link *tlink, __u32 oplock,
187+
const char *symlink_target);
189188
extern int cifs_posix_open(const char *full_path, struct inode **inode,
190189
struct super_block *sb, int mode,
191190
unsigned int f_flags, __u32 *oplock, __u16 *netfid,
@@ -200,9 +199,9 @@ extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
200199
extern struct inode *cifs_iget(struct super_block *sb,
201200
struct cifs_fattr *fattr);
202201

203-
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
204-
FILE_ALL_INFO *data, struct super_block *sb,
205-
int xid, const struct cifs_fid *fid);
202+
int cifs_get_inode_info(struct inode **inode, const char *full_path,
203+
struct cifs_open_info_data *data, struct super_block *sb, int xid,
204+
const struct cifs_fid *fid);
206205
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
207206
struct super_block *sb, unsigned int xid);
208207
extern int cifs_get_inode_info_unix(struct inode **pinode,

fs/cifs/cifssmb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2305,7 +2305,7 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
23052305
remap);
23062306
}
23072307
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2308-
count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2308+
count = sizeof(struct set_file_rename) + (2 * len_of_str);
23092309
byte_count += count;
23102310
pSMB->DataCount = cpu_to_le16(count);
23112311
pSMB->TotalDataCount = pSMB->DataCount;

fs/cifs/connect.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,9 +2832,12 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
28322832
* sessinit is sent but no second negprot
28332833
*/
28342834
struct rfc1002_session_packet *ses_init_buf;
2835+
unsigned int req_noscope_len;
28352836
struct smb_hdr *smb_buf;
2837+
28362838
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
28372839
GFP_KERNEL);
2840+
28382841
if (ses_init_buf) {
28392842
ses_init_buf->trailer.session_req.called_len = 32;
28402843

@@ -2870,8 +2873,12 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
28702873
ses_init_buf->trailer.session_req.scope2 = 0;
28712874
smb_buf = (struct smb_hdr *)ses_init_buf;
28722875

2873-
/* sizeof RFC1002_SESSION_REQUEST with no scope */
2874-
smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
2876+
/* sizeof RFC1002_SESSION_REQUEST with no scopes */
2877+
req_noscope_len = sizeof(struct rfc1002_session_packet) - 2;
2878+
2879+
/* == cpu_to_be32(0x81000044) */
2880+
smb_buf->smb_buf_length =
2881+
cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | req_noscope_len);
28752882
rc = smb_send(server, smb_buf, 0x44);
28762883
kfree(ses_init_buf);
28772884
/*
@@ -3922,12 +3929,11 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
39223929
pSMB->AndXCommand = 0xFF;
39233930
pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
39243931
bcc_ptr = &pSMB->Password[0];
3925-
if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
3926-
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3927-
*bcc_ptr = 0; /* password is null byte */
3928-
bcc_ptr++; /* skip password */
3929-
/* already aligned so no need to do it below */
3930-
}
3932+
3933+
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3934+
*bcc_ptr = 0; /* password is null byte */
3935+
bcc_ptr++; /* skip password */
3936+
/* already aligned so no need to do it below */
39313937

39323938
if (ses->server->sign)
39333939
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

0 commit comments

Comments
 (0)