Merge tag '5.6-rc4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Mar 2020 23:31:19 +0000 (17:31 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Mar 2020 23:31:19 +0000 (17:31 -0600)
Pull cifs fixes from Steve French:
 "Five small cifs/smb3 fixes, two for stable (one for a reconnect
  problem and the other fixes a use case when renaming an open file)"

* tag '5.6-rc4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Use #define in cifs_dbg
  cifs: fix rename() by ensuring source handle opened with DELETE bit
  cifs: add missing mount option to /proc/mounts
  cifs: fix potential mismatch of UNC paths
  cifs: don't leak -EAGAIN for stat() during reconnect

fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c

index 606f26d..cc3ada1 100644 (file)
@@ -324,6 +324,8 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
        if (full_path == NULL)
                goto cdda_exit;
 
+       convert_delimiter(full_path, '\\');
+
        cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
 
        if (!cifs_sb_master_tlink(cifs_sb)) {
index 46ebaf3..fa77fe5 100644 (file)
@@ -530,6 +530,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
 
        if (tcon->seal)
                seq_puts(s, ",seal");
+       else if (tcon->ses->server->ignore_signature)
+               seq_puts(s, ",signloosely");
        if (tcon->nocase)
                seq_puts(s, ",nocase");
        if (tcon->local_lease)
index de82cfa..0d95636 100644 (file)
@@ -1281,6 +1281,7 @@ struct cifs_fid {
        __u64 volatile_fid;     /* volatile file id for smb2 */
        __u8 lease_key[SMB2_LEASE_KEY_SIZE];    /* lease key for smb2 */
        __u8 create_guid[16];
+       __u32 access;
        struct cifs_pending_open *pending_open;
        unsigned int epoch;
 #ifdef CONFIG_CIFS_DEBUG2
@@ -1741,6 +1742,12 @@ static inline bool is_retryable_error(int error)
        return false;
 }
 
+
+/* cifs_get_writable_file() flags */
+#define FIND_WR_ANY         0
+#define FIND_WR_FSUID_ONLY  1
+#define FIND_WR_WITH_DELETE 2
+
 #define   MID_FREE 0
 #define   MID_REQUEST_ALLOCATED 1
 #define   MID_REQUEST_SUBMITTED 2
index 89eaaf4..e5cb681 100644 (file)
@@ -134,11 +134,12 @@ extern bool backup_cred(struct cifs_sb_info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
                            unsigned int bytes_written);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
 extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
-                                 bool fsuid_only,
+                                 int flags,
                                  struct cifsFileInfo **ret_file);
 extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                                 int flags,
                                  struct cifsFileInfo **ret_file);
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
 extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
index 3c89569..6f6fb36 100644 (file)
@@ -1492,6 +1492,7 @@ openRetry:
        *oplock = rsp->OplockLevel;
        /* cifs fid stays in le */
        oparms->fid->netfid = rsp->Fid;
+       oparms->fid->access = desired_access;
 
        /* Let caller know file was created so we can set the mode. */
        /* Do we care about the CreateAction in any other cases? */
@@ -2115,7 +2116,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
                wdata2->tailsz = tailsz;
                wdata2->bytes = cur_len;
 
-               rc = cifs_get_writable_file(CIFS_I(inode), false,
+               rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
                                            &wdata2->cfile);
                if (!wdata2->cfile) {
                        cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
index bc9516a..3b942ec 100644 (file)
@@ -1958,7 +1958,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
 
 /* Return -EBADF if no handle is found and general rc otherwise */
 int
-cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
+cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
                       struct cifsFileInfo **ret_file)
 {
        struct cifsFileInfo *open_file, *inv_file = NULL;
@@ -1966,7 +1966,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
        bool any_available = false;
        int rc = -EBADF;
        unsigned int refind = 0;
-
+       bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
+       bool with_delete = flags & FIND_WR_WITH_DELETE;
        *ret_file = NULL;
 
        /*
@@ -1998,6 +1999,8 @@ refind_writable:
                        continue;
                if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
                        continue;
+               if (with_delete && !(open_file->fid.access & DELETE))
+                       continue;
                if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
                        if (!open_file->invalidHandle) {
                                /* found a good writable file */
@@ -2045,12 +2048,12 @@ refind_writable:
 }
 
 struct cifsFileInfo *
-find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only)
+find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)
 {
        struct cifsFileInfo *cfile;
        int rc;
 
-       rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile);
+       rc = cifs_get_writable_file(cifs_inode, flags, &cfile);
        if (rc)
                cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc);
 
@@ -2059,6 +2062,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only)
 
 int
 cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                      int flags,
                       struct cifsFileInfo **ret_file)
 {
        struct list_head *tmp;
@@ -2085,7 +2089,7 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
                kfree(full_path);
                cinode = CIFS_I(d_inode(cfile->dentry));
                spin_unlock(&tcon->open_file_lock);
-               return cifs_get_writable_file(cinode, 0, ret_file);
+               return cifs_get_writable_file(cinode, flags, ret_file);
        }
 
        spin_unlock(&tcon->open_file_lock);
@@ -2162,7 +2166,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
        if (mapping->host->i_size - offset < (loff_t)to)
                to = (unsigned)(mapping->host->i_size - offset);
 
-       rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file);
+       rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY,
+                                   &open_file);
        if (!rc) {
                bytes_written = cifs_write(open_file, open_file->pid,
                                           write_data, to - from, &offset);
@@ -2355,7 +2360,7 @@ retry:
                if (cfile)
                        cifsFileInfo_put(cfile);
 
-               rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile);
+               rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
 
                /* in case of an error store it to return later */
                if (rc)
index b5e6635..1e8a4b1 100644 (file)
@@ -653,8 +653,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
                 */
                if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
                    !info->DeletePending) {
-                       cifs_dbg(1, "bogus file nlink value %u\n",
-                               fattr->cf_nlink);
+                       cifs_dbg(VFS, "bogus file nlink value %u\n",
+                                fattr->cf_nlink);
                        fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
                }
        }
@@ -2073,6 +2073,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
        struct inode *inode = d_inode(dentry);
        struct super_block *sb = dentry->d_sb;
        char *full_path = NULL;
+       int count = 0;
 
        if (inode == NULL)
                return -ENOENT;
@@ -2094,15 +2095,18 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
                 full_path, inode, inode->i_count.counter,
                 dentry, cifs_get_time(dentry), jiffies);
 
+again:
        if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
                rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
        else
                rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
                                         xid, NULL);
-
+       if (rc == -EAGAIN && count++ < 10)
+               goto again;
 out:
        kfree(full_path);
        free_xid(xid);
+
        return rc;
 }
 
@@ -2278,7 +2282,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
         * writebehind data than the SMB timeout for the SetPathInfo
         * request would allow
         */
-       open_file = find_writable_file(cifsInode, true);
+       open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                tcon = tlink_tcon(open_file->tlink);
                server = tcon->ses->server;
@@ -2428,7 +2432,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
                args->ctime = NO_CHANGE_64;
 
        args->device = 0;
-       open_file = find_writable_file(cifsInode, true);
+       open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                u16 nfid = open_file->fid.netfid;
                u32 npid = open_file->pid;
@@ -2531,7 +2535,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        rc = 0;
 
        if (attrs->ia_valid & ATTR_MTIME) {
-               rc = cifs_get_writable_file(cifsInode, false, &wfile);
+               rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
                if (!rc) {
                        tcon = tlink_tcon(wfile->tlink);
                        rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
index eb994e3..b130efa 100644 (file)
@@ -766,7 +766,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        struct cifs_tcon *tcon;
 
        /* if the file is already open for write, just use that fileid */
-       open_file = find_writable_file(cinode, true);
+       open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                fid.netfid = open_file->fid.netfid;
                netpid = open_file->pid;
index 1cf2075..a8c301a 100644 (file)
@@ -521,7 +521,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
        cifs_i = CIFS_I(inode);
        dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
        data.Attributes = cpu_to_le32(dosattrs);
-       cifs_get_writable_path(tcon, name, &cfile);
+       cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
        tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
                                 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
                                 CREATE_NOT_FILE, ACL_NO_MODE,
@@ -577,7 +577,7 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
 {
        struct cifsFileInfo *cfile;
 
-       cifs_get_writable_path(tcon, from_name, &cfile);
+       cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
 
        return smb2_set_path_attr(xid, tcon, from_name, to_name,
                                  cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
index e47190c..c31e84e 100644 (file)
@@ -1364,6 +1364,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
 
        cfile->fid.persistent_fid = fid->persistent_fid;
        cfile->fid.volatile_fid = fid->volatile_fid;
+       cfile->fid.access = fid->access;
 #ifdef CONFIG_CIFS_DEBUG2
        cfile->fid.mid = fid->mid;
 #endif /* CIFS_DEBUG2 */
@@ -3327,7 +3328,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs
         * some servers (Windows2016) will not reflect recent writes in
         * QUERY_ALLOCATED_RANGES until SMB2_flush is called.
         */
-       wrcfile = find_writable_file(cifsi, false);
+       wrcfile = find_writable_file(cifsi, FIND_WR_ANY);
        if (wrcfile) {
                filemap_write_and_wait(inode->i_mapping);
                smb2_flush_file(xid, tcon, &wrcfile->fid);
index 1234f9c..28c0be5 100644 (file)
@@ -2771,6 +2771,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        atomic_inc(&tcon->num_remote_opens);
        oparms->fid->persistent_fid = rsp->PersistentFileId;
        oparms->fid->volatile_fid = rsp->VolatileFileId;
+       oparms->fid->access = oparms->desired_access;
 #ifdef CONFIG_CIFS_DEBUG2
        oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId);
 #endif /* CIFS_DEBUG2 */