Commit 0b2f2b1f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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()
parents 3cd8b194 c09fb907
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -6386,7 +6386,7 @@ L: linux-cifs@vger.kernel.org
L:	samba-technical@lists.samba.org (moderated for non-subscribers)
S:	Supported
W:	https://wiki.samba.org/index.php/LinuxCIFS
T:	git git://git.samba.org/sfrench/cifs-2.6.git
T:	git https://git.samba.org/sfrench/cifs-2.6.git
F:	Documentation/admin-guide/cifs/
F:	fs/smb/client/
F:	fs/smb/common/
@@ -14007,7 +14007,7 @@ R: Sergey Senozhatsky <senozhatsky@chromium.org>
R:	Tom Talpey <tom@talpey.com>
L:	linux-cifs@vger.kernel.org
S:	Maintained
T:	git git://git.samba.org/ksmbd.git
T:	git https://git.samba.org/ksmbd.git
F:	Documentation/filesystems/smb/ksmbd.rst
F:	fs/smb/common/
F:	fs/smb/server/
+9 −5
Original line number Diff line number Diff line
@@ -3196,15 +3196,18 @@ void d_mark_tmpfile(struct file *file, struct inode *inode)
}
EXPORT_SYMBOL(d_mark_tmpfile);

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

	BUG_ON(dname_external(dentry));
	BUG_ON(d_really_is_positive(dentry));
	BUG_ON(!d_unlinked(dentry));
	BUG_ON(name->len > DNAME_INLINE_LEN - 1);
	if (unlikely(dname_external(dentry) ||
		     d_really_is_positive(dentry) ||
		     !d_unlinked(dentry)))
		return -EINVAL;
	if (unlikely(name->len > DNAME_INLINE_LEN - 1))
		return -ENAMETOOLONG;

	spin_lock(&dentry->d_parent->d_lock);
	spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
	dentry->__d_name.len = name->len;
@@ -3212,6 +3215,7 @@ void d_mark_tmpfile_name(struct file *file, const struct qstr *name)
	dname[name->len] = '\0';
	spin_unlock(&dentry->d_lock);
	spin_unlock(&dentry->d_parent->d_lock);
	return 0;
}
EXPORT_SYMBOL(d_mark_tmpfile_name);

+6 −11
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#define _CIFSFS_H

#include <linux/hash.h>
#include <linux/dcache.h>

#define ROOT_I 2

@@ -150,16 +151,10 @@ struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, int flags,
char *cifs_silly_fullpath(struct dentry *dentry);

#define CIFS_TMPNAME_PREFIX	".__smbfile_tmp"
#define CIFS_TMPNAME_PREFIX_LEN    ((int)sizeof(CIFS_TMPNAME_PREFIX) - 1)
#define CIFS_TMPNAME_COUNTER_LEN   ((int)sizeof(cifs_tmpcounter) * 2)
#define CIFS_TMPNAME_LEN \
	(CIFS_TMPNAME_PREFIX_LEN + CIFS_TMPNAME_COUNTER_LEN)
#define CIFS_TMPNAME_LEN	(DNAME_INLINE_LEN - 1)

#define CIFS_SILLYNAME_PREFIX	".__smbfile_silly"
#define CIFS_SILLYNAME_PREFIX_LEN  ((int)sizeof(CIFS_SILLYNAME_PREFIX) - 1)
#define CIFS_SILLYNAME_COUNTER_LEN ((int)sizeof(cifs_sillycounter) * 2)
#define CIFS_SILLYNAME_LEN \
	(CIFS_SILLYNAME_PREFIX_LEN + CIFS_SILLYNAME_COUNTER_LEN)
#define CIFS_SILLYNAME_LEN	(DNAME_INLINE_LEN - 1)

#ifdef CONFIG_CIFS_NFSD_EXPORT
extern const struct export_operations cifs_export_ops;
+15 −10
Original line number Diff line number Diff line
@@ -1056,9 +1056,9 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
{
	struct dentry *dentry = file->f_path.dentry;
	struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
	size_t namesize = CIFS_TMPNAME_LEN + 1;
	char *path __free(kfree) = NULL, *name;
	unsigned int oflags = file->f_flags;
	size_t size = CIFS_TMPNAME_LEN + 1;
	int retries = 0, max_retries = 16;
	struct TCP_Server_Info *server;
	struct cifs_pending_open open;
@@ -1070,6 +1070,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
	struct inode *inode;
	unsigned int xid;
	__u32 oplock;
	int namelen;
	int rc;

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

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

	name = path + strlen(path);
	do {
		scnprintf(name, size,
			  CIFS_TMPNAME_PREFIX "%0*x",
			  CIFS_TMPNAME_COUNTER_LEN,
		/* Append tmpfile name to @path */
		namelen = scnprintf(name, namesize, CIFS_TMPNAME_PREFIX "%x",
				    atomic_inc_return(&cifs_tmpcounter));
		rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
				      mode, &oplock, &fid, NULL, &inode);
		if (!rc) {
			rc = d_mark_tmpfile_name(file, &QSTR_LEN(name, namelen));
			if (rc) {
				cifs_dbg(VFS | ONCE, "%s: failed to set filename in dentry: %d\n",
					 __func__, rc);
				rc = -EISDIR;
				iput(inode);
				goto err_open;
			}
			set_nlink(inode, 0);
			mark_inode_dirty(inode);
			d_mark_tmpfile_name(file, &QSTR_LEN(name, size - 1));
			d_instantiate(dentry, inode);
			break;
		}
@@ -1168,9 +1175,7 @@ char *cifs_silly_fullpath(struct dentry *dentry)

	do {
		dput(sdentry);
		scnprintf(name, namesize,
			  CIFS_SILLYNAME_PREFIX "%0*x",
			  CIFS_SILLYNAME_COUNTER_LEN,
		scnprintf(name, namesize, CIFS_SILLYNAME_PREFIX "%x",
			  atomic_inc_return(&cifs_sillycounter));
		sdentry = lookup_noperm(&QSTR(name), dentry->d_parent);
		if (IS_ERR(sdentry))
+19 −2
Original line number Diff line number Diff line
@@ -1082,6 +1082,9 @@ int cifs_open(struct inode *inode, struct file *file)
		rc = cfile ? 0 : -ENOENT;
	}
	if (rc == 0) {
		trace_smb3_open_cached(xid, tcon->tid, tcon->ses->Suid,
				       cfile->fid.persistent_fid,
				       file->f_flags, cfile->f_flags);
		file->private_data = cfile;
		spin_lock(&CIFS_I(inode)->deferred_lock);
		cifs_del_deferred_close(cfile);
@@ -1441,6 +1444,7 @@ int cifs_close(struct inode *inode, struct file *file)
	struct cifsInodeInfo *cinode = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifs_deferred_close *dclose;
	struct cifs_tcon *tcon;

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

@@ -1467,6 +1471,10 @@ int cifs_close(struct inode *inode, struct file *file)
					cifsFileInfo_get(cfile);
			} else {
				/* Deferred close for files */
				tcon = tlink_tcon(cfile->tlink);
				trace_smb3_close_cached(tcon->tid, tcon->ses->Suid,
						cfile->fid.persistent_fid,
						cifs_sb->ctx->closetimeo);
				queue_delayed_work(deferredclose_wq,
						&cfile->deferred, cifs_sb->ctx->closetimeo);
				cfile->deferred_close_scheduled = true;
@@ -1630,6 +1638,9 @@ cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
			continue;
		if (conf_lock)
			*conf_lock = li;
		trace_smb3_lock_conflict(cfile->fid.persistent_fid,
					 offset, length, type,
					 li->offset, li->length, li->type, li->pid);
		return true;
	}
	return false;
@@ -1711,7 +1722,7 @@ cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
 */
static int
cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
		 bool wait)
		 bool wait, unsigned int xid)
{
	struct cifsLockInfo *conf_lock;
	struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
@@ -1726,7 +1737,13 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
					lock->type, lock->flags, &conf_lock,
					CIFS_LOCK_OP);
	if (!exist && cinode->can_cache_brlcks) {
		struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);

		list_add_tail(&lock->llist, &cfile->llist->locks);
		trace_smb3_lock_cached(xid, cfile->fid.persistent_fid,
				       tcon->tid, tcon->ses->Suid,
				       lock->offset, lock->length,
				       lock->type, 1, 0);
		up_write(&cinode->lock_sem);
		return rc;
	}
@@ -2341,7 +2358,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
		if (!lock)
			return -ENOMEM;

		rc = cifs_lock_add_if(cfile, lock, wait_flag);
		rc = cifs_lock_add_if(cfile, lock, wait_flag, xid);
		if (rc < 0) {
			kfree(lock);
			return rc;
Loading