Skip to content

Commit 0b2f2b1

Browse files
committed
Merge tag 'v7.1-rc1-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client updates from Steve French: - Fix integer underflow in encrypted read - Four debug patches, adding a few tracepoints - Minor update to MAINTAINERS file (preferred server URL for cifs) - Remove the BUG_ON() calls in d_mark_tmpfile_name * tag 'v7.1-rc1-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: MAINTAINERS: change git.samba.org to https smb: client: fix integer underflow in receive_encrypted_read() smb: client: add tracepoints for deferred handle caching smb: client: add oplock level to smb3_open_done tracepoint smb: client: add tracepoint for local lock conflicts smb: client: add tracepoints for lock operations vfs: get rid of BUG_ON() in d_mark_tmpfile_name()
2 parents 3cd8b19 + c09fb90 commit 0b2f2b1

9 files changed

Lines changed: 233 additions & 43 deletions

File tree

MAINTAINERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6386,7 +6386,7 @@ L: linux-cifs@vger.kernel.org
63866386
L: samba-technical@lists.samba.org (moderated for non-subscribers)
63876387
S: Supported
63886388
W: https://wiki.samba.org/index.php/LinuxCIFS
6389-
T: git git://git.samba.org/sfrench/cifs-2.6.git
6389+
T: git https://git.samba.org/sfrench/cifs-2.6.git
63906390
F: Documentation/admin-guide/cifs/
63916391
F: fs/smb/client/
63926392
F: fs/smb/common/
@@ -14007,7 +14007,7 @@ R: Sergey Senozhatsky <senozhatsky@chromium.org>
1400714007
R: Tom Talpey <tom@talpey.com>
1400814008
L: linux-cifs@vger.kernel.org
1400914009
S: Maintained
14010-
T: git git://git.samba.org/ksmbd.git
14010+
T: git https://git.samba.org/ksmbd.git
1401114011
F: Documentation/filesystems/smb/ksmbd.rst
1401214012
F: fs/smb/common/
1401314013
F: fs/smb/server/

fs/dcache.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,22 +3196,26 @@ void d_mark_tmpfile(struct file *file, struct inode *inode)
31963196
}
31973197
EXPORT_SYMBOL(d_mark_tmpfile);
31983198

3199-
void d_mark_tmpfile_name(struct file *file, const struct qstr *name)
3199+
int d_mark_tmpfile_name(struct file *file, const struct qstr *name)
32003200
{
32013201
struct dentry *dentry = file->f_path.dentry;
32023202
char *dname = dentry->d_shortname.string;
32033203

3204-
BUG_ON(dname_external(dentry));
3205-
BUG_ON(d_really_is_positive(dentry));
3206-
BUG_ON(!d_unlinked(dentry));
3207-
BUG_ON(name->len > DNAME_INLINE_LEN - 1);
3204+
if (unlikely(dname_external(dentry) ||
3205+
d_really_is_positive(dentry) ||
3206+
!d_unlinked(dentry)))
3207+
return -EINVAL;
3208+
if (unlikely(name->len > DNAME_INLINE_LEN - 1))
3209+
return -ENAMETOOLONG;
3210+
32083211
spin_lock(&dentry->d_parent->d_lock);
32093212
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
32103213
dentry->__d_name.len = name->len;
32113214
memcpy(dname, name->name, name->len);
32123215
dname[name->len] = '\0';
32133216
spin_unlock(&dentry->d_lock);
32143217
spin_unlock(&dentry->d_parent->d_lock);
3218+
return 0;
32153219
}
32163220
EXPORT_SYMBOL(d_mark_tmpfile_name);
32173221

fs/smb/client/cifsfs.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define _CIFSFS_H
1111

1212
#include <linux/hash.h>
13+
#include <linux/dcache.h>
1314

1415
#define ROOT_I 2
1516

@@ -149,17 +150,11 @@ struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, int flags,
149150

150151
char *cifs_silly_fullpath(struct dentry *dentry);
151152

152-
#define CIFS_TMPNAME_PREFIX ".__smbfile_tmp"
153-
#define CIFS_TMPNAME_PREFIX_LEN ((int)sizeof(CIFS_TMPNAME_PREFIX) - 1)
154-
#define CIFS_TMPNAME_COUNTER_LEN ((int)sizeof(cifs_tmpcounter) * 2)
155-
#define CIFS_TMPNAME_LEN \
156-
(CIFS_TMPNAME_PREFIX_LEN + CIFS_TMPNAME_COUNTER_LEN)
157-
158-
#define CIFS_SILLYNAME_PREFIX ".__smbfile_silly"
159-
#define CIFS_SILLYNAME_PREFIX_LEN ((int)sizeof(CIFS_SILLYNAME_PREFIX) - 1)
160-
#define CIFS_SILLYNAME_COUNTER_LEN ((int)sizeof(cifs_sillycounter) * 2)
161-
#define CIFS_SILLYNAME_LEN \
162-
(CIFS_SILLYNAME_PREFIX_LEN + CIFS_SILLYNAME_COUNTER_LEN)
153+
#define CIFS_TMPNAME_PREFIX ".__smbfile_tmp"
154+
#define CIFS_TMPNAME_LEN (DNAME_INLINE_LEN - 1)
155+
156+
#define CIFS_SILLYNAME_PREFIX ".__smbfile_silly"
157+
#define CIFS_SILLYNAME_LEN (DNAME_INLINE_LEN - 1)
163158

164159
#ifdef CONFIG_CIFS_NFSD_EXPORT
165160
extern const struct export_operations cifs_export_ops;

fs/smb/client/dir.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,9 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10561056
{
10571057
struct dentry *dentry = file->f_path.dentry;
10581058
struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
1059+
size_t namesize = CIFS_TMPNAME_LEN + 1;
10591060
char *path __free(kfree) = NULL, *name;
10601061
unsigned int oflags = file->f_flags;
1061-
size_t size = CIFS_TMPNAME_LEN + 1;
10621062
int retries = 0, max_retries = 16;
10631063
struct TCP_Server_Info *server;
10641064
struct cifs_pending_open open;
@@ -1070,6 +1070,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10701070
struct inode *inode;
10711071
unsigned int xid;
10721072
__u32 oplock;
1073+
int namelen;
10731074
int rc;
10741075

10751076
if (unlikely(cifs_forced_shutdown(cifs_sb)))
@@ -1093,7 +1094,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10931094
server->ops->new_lease_key(&fid);
10941095
cifs_add_pending_open(&fid, tlink, &open);
10951096

1096-
path = alloc_parent_path(dentry, size - 1);
1097+
path = alloc_parent_path(dentry, namesize - 1);
10971098
if (IS_ERR(path)) {
10981099
cifs_del_pending_open(&open);
10991100
rc = PTR_ERR(path);
@@ -1103,16 +1104,22 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
11031104

11041105
name = path + strlen(path);
11051106
do {
1106-
scnprintf(name, size,
1107-
CIFS_TMPNAME_PREFIX "%0*x",
1108-
CIFS_TMPNAME_COUNTER_LEN,
1109-
atomic_inc_return(&cifs_tmpcounter));
1107+
/* Append tmpfile name to @path */
1108+
namelen = scnprintf(name, namesize, CIFS_TMPNAME_PREFIX "%x",
1109+
atomic_inc_return(&cifs_tmpcounter));
11101110
rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
11111111
mode, &oplock, &fid, NULL, &inode);
11121112
if (!rc) {
1113+
rc = d_mark_tmpfile_name(file, &QSTR_LEN(name, namelen));
1114+
if (rc) {
1115+
cifs_dbg(VFS | ONCE, "%s: failed to set filename in dentry: %d\n",
1116+
__func__, rc);
1117+
rc = -EISDIR;
1118+
iput(inode);
1119+
goto err_open;
1120+
}
11131121
set_nlink(inode, 0);
11141122
mark_inode_dirty(inode);
1115-
d_mark_tmpfile_name(file, &QSTR_LEN(name, size - 1));
11161123
d_instantiate(dentry, inode);
11171124
break;
11181125
}
@@ -1168,9 +1175,7 @@ char *cifs_silly_fullpath(struct dentry *dentry)
11681175

11691176
do {
11701177
dput(sdentry);
1171-
scnprintf(name, namesize,
1172-
CIFS_SILLYNAME_PREFIX "%0*x",
1173-
CIFS_SILLYNAME_COUNTER_LEN,
1178+
scnprintf(name, namesize, CIFS_SILLYNAME_PREFIX "%x",
11741179
atomic_inc_return(&cifs_sillycounter));
11751180
sdentry = lookup_noperm(&QSTR(name), dentry->d_parent);
11761181
if (IS_ERR(sdentry))

fs/smb/client/file.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,9 @@ int cifs_open(struct inode *inode, struct file *file)
10821082
rc = cfile ? 0 : -ENOENT;
10831083
}
10841084
if (rc == 0) {
1085+
trace_smb3_open_cached(xid, tcon->tid, tcon->ses->Suid,
1086+
cfile->fid.persistent_fid,
1087+
file->f_flags, cfile->f_flags);
10851088
file->private_data = cfile;
10861089
spin_lock(&CIFS_I(inode)->deferred_lock);
10871090
cifs_del_deferred_close(cfile);
@@ -1441,6 +1444,7 @@ int cifs_close(struct inode *inode, struct file *file)
14411444
struct cifsInodeInfo *cinode = CIFS_I(inode);
14421445
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
14431446
struct cifs_deferred_close *dclose;
1447+
struct cifs_tcon *tcon;
14441448

14451449
cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE);
14461450

@@ -1467,6 +1471,10 @@ int cifs_close(struct inode *inode, struct file *file)
14671471
cifsFileInfo_get(cfile);
14681472
} else {
14691473
/* Deferred close for files */
1474+
tcon = tlink_tcon(cfile->tlink);
1475+
trace_smb3_close_cached(tcon->tid, tcon->ses->Suid,
1476+
cfile->fid.persistent_fid,
1477+
cifs_sb->ctx->closetimeo);
14701478
queue_delayed_work(deferredclose_wq,
14711479
&cfile->deferred, cifs_sb->ctx->closetimeo);
14721480
cfile->deferred_close_scheduled = true;
@@ -1630,6 +1638,9 @@ cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
16301638
continue;
16311639
if (conf_lock)
16321640
*conf_lock = li;
1641+
trace_smb3_lock_conflict(cfile->fid.persistent_fid,
1642+
offset, length, type,
1643+
li->offset, li->length, li->type, li->pid);
16331644
return true;
16341645
}
16351646
return false;
@@ -1711,7 +1722,7 @@ cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
17111722
*/
17121723
static int
17131724
cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
1714-
bool wait)
1725+
bool wait, unsigned int xid)
17151726
{
17161727
struct cifsLockInfo *conf_lock;
17171728
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
@@ -1726,7 +1737,13 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
17261737
lock->type, lock->flags, &conf_lock,
17271738
CIFS_LOCK_OP);
17281739
if (!exist && cinode->can_cache_brlcks) {
1740+
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1741+
17291742
list_add_tail(&lock->llist, &cfile->llist->locks);
1743+
trace_smb3_lock_cached(xid, cfile->fid.persistent_fid,
1744+
tcon->tid, tcon->ses->Suid,
1745+
lock->offset, lock->length,
1746+
lock->type, 1, 0);
17301747
up_write(&cinode->lock_sem);
17311748
return rc;
17321749
}
@@ -2341,7 +2358,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
23412358
if (!lock)
23422359
return -ENOMEM;
23432360

2344-
rc = cifs_lock_add_if(cfile, lock, wait_flag);
2361+
rc = cifs_lock_add_if(cfile, lock, wait_flag, xid);
23452362
if (rc < 0) {
23462363
kfree(lock);
23472364
return rc;

fs/smb/client/smb2ops.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4943,6 +4943,14 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
49434943
goto free_dw;
49444944
server->total_read += rc;
49454945

4946+
if (le32_to_cpu(tr_hdr->OriginalMessageSize) <
4947+
server->vals->read_rsp_size) {
4948+
cifs_server_dbg(VFS, "OriginalMessageSize %u too small for read response (%zu)\n",
4949+
le32_to_cpu(tr_hdr->OriginalMessageSize),
4950+
server->vals->read_rsp_size);
4951+
rc = -EINVAL;
4952+
goto discard_data;
4953+
}
49464954
len = le32_to_cpu(tr_hdr->OriginalMessageSize) -
49474955
server->vals->read_rsp_size;
49484956
dw->len = len;

fs/smb/client/smb2pdu.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3043,7 +3043,8 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
30433043
}
30443044

30453045
trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
3046-
CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES);
3046+
CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES,
3047+
rsp->OplockLevel);
30473048

30483049
SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
30493050

@@ -3320,9 +3321,6 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
33203321
goto creat_exit;
33213322
} else if (rsp == NULL) /* unlikely to happen, but safer to check */
33223323
goto creat_exit;
3323-
else
3324-
trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
3325-
oparms->create_options, oparms->desired_access);
33263324

33273325
atomic_inc(&tcon->num_remote_opens);
33283326
oparms->fid->persistent_fid = rsp->PersistentFileId;
@@ -3347,6 +3345,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
33473345

33483346
rc = smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch,
33493347
oparms->fid->lease_key, oplock, buf, posix);
3348+
3349+
trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
3350+
oparms->create_options, oparms->desired_access,
3351+
*oplock);
33503352
creat_exit:
33513353
SMB2_open_free(&rqst);
33523354
free_rsp_buf(resp_buftype, rsp);
@@ -6272,6 +6274,11 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
62726274
smb2_set_replay(server, &rqst);
62736275
}
62746276

6277+
trace_smb3_lock_enter(xid, persist_fid, tcon->tid, tcon->ses->Suid,
6278+
le64_to_cpu(buf[0].Offset),
6279+
le64_to_cpu(buf[0].Length),
6280+
le32_to_cpu(buf[0].Flags), num_lock, 0);
6281+
62756282
rc = cifs_send_recv(xid, tcon->ses, server,
62766283
&rqst, &resp_buf_type, flags,
62776284
&rsp_iov);
@@ -6280,7 +6287,15 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
62806287
cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
62816288
cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
62826289
trace_smb3_lock_err(xid, persist_fid, tcon->tid,
6283-
tcon->ses->Suid, rc);
6290+
tcon->ses->Suid,
6291+
le64_to_cpu(buf[0].Offset),
6292+
le64_to_cpu(buf[0].Length),
6293+
le32_to_cpu(buf[0].Flags), num_lock, rc);
6294+
} else {
6295+
trace_smb3_lock_done(xid, persist_fid, tcon->tid, tcon->ses->Suid,
6296+
le64_to_cpu(buf[0].Offset),
6297+
le64_to_cpu(buf[0].Length),
6298+
le32_to_cpu(buf[0].Flags), num_lock, 0);
62846299
}
62856300

62866301
if (is_replayable_error(rc) &&

0 commit comments

Comments
 (0)