Skip to content

Commit bd8e963

Browse files
committed
Merge tag '6.1-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: - memory leak fixes - fixes for directory leases, including an important one which fixes a problem noticed by git functional tests - fixes relating to missing free_xid calls (helpful for tracing/debugging of entry/exit into cifs.ko) - a multichannel fix - a small cleanup fix (use of list_move instead of list_del/list_add) * tag '6.1-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module number cifs: fix memory leaks in session setup cifs: drop the lease for cached directories on rmdir or rename smb3: interface count displayed incorrectly cifs: Fix memory leak when build ntlmssp negotiate blob failed cifs: set rc to -ENOENT if we can not get a dentry for the cached dir cifs: use LIST_HEAD() and list_move() to simplify code cifs: Fix xid leak in cifs_get_file_info_unix() cifs: Fix xid leak in cifs_ses_add_channel() cifs: Fix xid leak in cifs_flock() cifs: Fix xid leak in cifs_copy_file_range() cifs: Fix xid leak in cifs_create()
2 parents 022c028 + 73b1b8d commit bd8e963

File tree

11 files changed

+68
-32
lines changed

11 files changed

+68
-32
lines changed

fs/cifs/cached_dir.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
253253
dentry = dget(cifs_sb->root);
254254
else {
255255
dentry = path_to_dentry(cifs_sb, path);
256-
if (IS_ERR(dentry))
256+
if (IS_ERR(dentry)) {
257+
rc = -ENOENT;
257258
goto oshr_free;
259+
}
258260
}
259261
cfid->dentry = dentry;
260262
cfid->tcon = tcon;
@@ -338,6 +340,27 @@ smb2_close_cached_fid(struct kref *ref)
338340
free_cached_dir(cfid);
339341
}
340342

343+
void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
344+
const char *name, struct cifs_sb_info *cifs_sb)
345+
{
346+
struct cached_fid *cfid = NULL;
347+
int rc;
348+
349+
rc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid);
350+
if (rc) {
351+
cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name);
352+
return;
353+
}
354+
spin_lock(&cfid->cfids->cfid_list_lock);
355+
if (cfid->has_lease) {
356+
cfid->has_lease = false;
357+
kref_put(&cfid->refcount, smb2_close_cached_fid);
358+
}
359+
spin_unlock(&cfid->cfids->cfid_list_lock);
360+
close_cached_dir(cfid);
361+
}
362+
363+
341364
void close_cached_dir(struct cached_fid *cfid)
342365
{
343366
kref_put(&cfid->refcount, smb2_close_cached_fid);
@@ -378,22 +401,20 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
378401
{
379402
struct cached_fids *cfids = tcon->cfids;
380403
struct cached_fid *cfid, *q;
381-
struct list_head entry;
404+
LIST_HEAD(entry);
382405

383-
INIT_LIST_HEAD(&entry);
384406
spin_lock(&cfids->cfid_list_lock);
385407
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
386-
list_del(&cfid->entry);
387-
list_add(&cfid->entry, &entry);
408+
list_move(&cfid->entry, &entry);
388409
cfids->num_entries--;
389410
cfid->is_open = false;
411+
cfid->on_list = false;
390412
/* To prevent race with smb2_cached_lease_break() */
391413
kref_get(&cfid->refcount);
392414
}
393415
spin_unlock(&cfids->cfid_list_lock);
394416

395417
list_for_each_entry_safe(cfid, q, &entry, entry) {
396-
cfid->on_list = false;
397418
list_del(&cfid->entry);
398419
cancel_work_sync(&cfid->lease_break);
399420
if (cfid->has_lease) {
@@ -518,15 +539,13 @@ struct cached_fids *init_cached_dirs(void)
518539
void free_cached_dirs(struct cached_fids *cfids)
519540
{
520541
struct cached_fid *cfid, *q;
521-
struct list_head entry;
542+
LIST_HEAD(entry);
522543

523-
INIT_LIST_HEAD(&entry);
524544
spin_lock(&cfids->cfid_list_lock);
525545
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
526546
cfid->on_list = false;
527547
cfid->is_open = false;
528-
list_del(&cfid->entry);
529-
list_add(&cfid->entry, &entry);
548+
list_move(&cfid->entry, &entry);
530549
}
531550
spin_unlock(&cfids->cfid_list_lock);
532551

fs/cifs/cached_dir.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
6969
struct dentry *dentry,
7070
struct cached_fid **cfid);
7171
extern void close_cached_dir(struct cached_fid *cfid);
72+
extern void drop_cached_dir_by_name(const unsigned int xid,
73+
struct cifs_tcon *tcon,
74+
const char *name,
75+
struct cifs_sb_info *cifs_sb);
7276
extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
7377
extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
7478
extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);

fs/cifs/cifsfs.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,8 +1302,11 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
13021302
ssize_t rc;
13031303
struct cifsFileInfo *cfile = dst_file->private_data;
13041304

1305-
if (cfile->swapfile)
1306-
return -EOPNOTSUPP;
1305+
if (cfile->swapfile) {
1306+
rc = -EOPNOTSUPP;
1307+
free_xid(xid);
1308+
return rc;
1309+
}
13071310

13081311
rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
13091312
len, flags);

fs/cifs/cifsfs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,6 @@ extern const struct export_operations cifs_export_ops;
153153
#endif /* CONFIG_CIFS_NFSD_EXPORT */
154154

155155
/* when changing internal version - update following two lines at same time */
156-
#define SMB3_PRODUCT_BUILD 39
157-
#define CIFS_VERSION "2.39"
156+
#define SMB3_PRODUCT_BUILD 40
157+
#define CIFS_VERSION "2.40"
158158
#endif /* _CIFSFS_H */

fs/cifs/dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,8 +543,10 @@ int cifs_create(struct user_namespace *mnt_userns, struct inode *inode,
543543
cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
544544
inode, direntry, direntry);
545545

546-
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
547-
return -EIO;
546+
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb)))) {
547+
rc = -EIO;
548+
goto out_free_xid;
549+
}
548550

549551
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
550552
rc = PTR_ERR(tlink);

fs/cifs/file.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,11 +1885,13 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
18851885
struct cifsFileInfo *cfile;
18861886
__u32 type;
18871887

1888-
rc = -EACCES;
18891888
xid = get_xid();
18901889

1891-
if (!(fl->fl_flags & FL_FLOCK))
1892-
return -ENOLCK;
1890+
if (!(fl->fl_flags & FL_FLOCK)) {
1891+
rc = -ENOLCK;
1892+
free_xid(xid);
1893+
return rc;
1894+
}
18931895

18941896
cfile = (struct cifsFileInfo *)file->private_data;
18951897
tcon = tlink_tcon(cfile->tlink);
@@ -1908,8 +1910,9 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
19081910
* if no lock or unlock then nothing to do since we do not
19091911
* know what it is
19101912
*/
1913+
rc = -EOPNOTSUPP;
19111914
free_xid(xid);
1912-
return -EOPNOTSUPP;
1915+
return rc;
19131916
}
19141917

19151918
rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock,

fs/cifs/inode.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,10 @@ cifs_get_file_info_unix(struct file *filp)
368368

369369
if (cfile->symlink_target) {
370370
fattr.cf_symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
371-
if (!fattr.cf_symlink_target)
372-
return -ENOMEM;
371+
if (!fattr.cf_symlink_target) {
372+
rc = -ENOMEM;
373+
goto cifs_gfiunix_out;
374+
}
373375
}
374376

375377
rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);

fs/cifs/sess.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
496496
cifs_put_tcp_session(chan->server, 0);
497497
}
498498

499+
free_xid(xid);
499500
return rc;
500501
}
501502

fs/cifs/smb2inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ int
655655
smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
656656
struct cifs_sb_info *cifs_sb)
657657
{
658+
drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
658659
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
659660
CREATE_NOT_FILE, ACL_NO_MODE,
660661
NULL, SMB2_OP_RMDIR, NULL, NULL, NULL);
@@ -698,6 +699,7 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
698699
{
699700
struct cifsFileInfo *cfile;
700701

702+
drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
701703
cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
702704

703705
return smb2_set_path_attr(xid, tcon, from_name, to_name,

fs/cifs/smb2ops.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
530530
p = buf;
531531

532532
spin_lock(&ses->iface_lock);
533+
ses->iface_count = 0;
533534
/*
534535
* Go through iface_list and do kref_put to remove
535536
* any unused ifaces. ifaces in use will be removed
@@ -651,9 +652,9 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
651652
kref_put(&iface->refcount, release_iface);
652653
} else
653654
list_add_tail(&info->iface_head, &ses->iface_list);
654-
spin_unlock(&ses->iface_lock);
655655

656656
ses->iface_count++;
657+
spin_unlock(&ses->iface_lock);
657658
ses->iface_last_update = jiffies;
658659
next_iface:
659660
nb_iface++;

0 commit comments

Comments
 (0)