Merge tag '5.1-rc1-cifs-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Mar 2019 16:58:08 +0000 (09:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Mar 2019 16:58:08 +0000 (09:58 -0700)
Pull smb3 fixes from Steve French:

 - two fixes for stable for guest mount problems with smb3.1.1

 - two fixes for crediting (SMB3 flow control) on resent requests

 - a byte range lock leak fix

 - two fixes for incorrect rc mappings

* tag '5.1-rc1-cifs-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module version number
  SMB3: Fix SMB3.1.1 guest mounts to Samba
  cifs: Fix slab-out-of-bounds when tracing SMB tcon
  cifs: allow guest mounts to work for smb3.11
  fix incorrect error code mapping for OBJECTID_NOT_FOUND
  cifs: fix that return -EINVAL when do dedupe operation
  CIFS: Fix an issue with re-sending rdata when transport returning -EAGAIN
  CIFS: Fix an issue with re-sending wdata when transport returning -EAGAIN

fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/file.c
fs/cifs/smb2maperror.c
fs/cifs/smb2pdu.c
fs/cifs/trace.h

index 217276b8b942f59d96fa74edc9d119402d3c7031..f9b71c12cc9f6d46267eaf73a801dd00715a9cf2 100644 (file)
@@ -1008,7 +1008,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
        unsigned int xid;
        int rc;
 
-       if (remap_flags & ~REMAP_FILE_ADVISORY)
+       if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
                return -EINVAL;
 
        cifs_dbg(FYI, "clone range\n");
index 142164ef1f05fe7befc2ad5df61409336b422fb7..5c0298b9998fc326795c435f6050c3563bdf09f4 100644 (file)
@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.18"
+#define CIFS_VERSION   "2.19"
 #endif                         /* _CIFSFS_H */
index 2a6d20c0ce0288d37ad2405424200be3fefaa9f4..89006e044973ec2d97ad784236f66cb447431693 100644 (file)
@@ -2632,43 +2632,56 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
        struct TCP_Server_Info *server =
                tlink_tcon(wdata->cfile->tlink)->ses->server;
 
-       /*
-        * Wait for credits to resend this wdata.
-        * Note: we are attempting to resend the whole wdata not in segments
-        */
        do {
-               rc = server->ops->wait_mtu_credits(server, wdata->bytes, &wsize,
-                                                  &credits);
+               if (wdata->cfile->invalidHandle) {
+                       rc = cifs_reopen_file(wdata->cfile, false);
+                       if (rc == -EAGAIN)
+                               continue;
+                       else if (rc)
+                               break;
+               }
 
-               if (rc)
-                       goto out;
 
-               if (wsize < wdata->bytes) {
-                       add_credits_and_wake_if(server, &credits, 0);
-                       msleep(1000);
-               }
-       } while (wsize < wdata->bytes);
+               /*
+                * Wait for credits to resend this wdata.
+                * Note: we are attempting to resend the whole wdata not in
+                * segments
+                */
+               do {
+                       rc = server->ops->wait_mtu_credits(server, wdata->bytes,
+                                               &wsize, &credits);
+                       if (rc)
+                               goto fail;
+
+                       if (wsize < wdata->bytes) {
+                               add_credits_and_wake_if(server, &credits, 0);
+                               msleep(1000);
+                       }
+               } while (wsize < wdata->bytes);
+               wdata->credits = credits;
 
-       wdata->credits = credits;
-       rc = -EAGAIN;
-       while (rc == -EAGAIN) {
-               rc = 0;
-               if (wdata->cfile->invalidHandle)
-                       rc = cifs_reopen_file(wdata->cfile, false);
-               if (!rc)
-                       rc = server->ops->async_writev(wdata,
+               rc = adjust_credits(server, &wdata->credits, wdata->bytes);
+
+               if (!rc) {
+                       if (wdata->cfile->invalidHandle)
+                               rc = -EAGAIN;
+                       else
+                               rc = server->ops->async_writev(wdata,
                                        cifs_uncached_writedata_release);
-       }
+               }
 
-       if (!rc) {
-               list_add_tail(&wdata->list, wdata_list);
-               return 0;
-       }
+               /* If the write was successfully sent, we are done */
+               if (!rc) {
+                       list_add_tail(&wdata->list, wdata_list);
+                       return 0;
+               }
 
-       add_credits_and_wake_if(server, &wdata->credits, 0);
-out:
-       kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+               /* Roll back credits and retry if needed */
+               add_credits_and_wake_if(server, &wdata->credits, 0);
+       } while (rc == -EAGAIN);
 
+fail:
+       kref_put(&wdata->refcount, cifs_uncached_writedata_release);
        return rc;
 }
 
@@ -2896,12 +2909,12 @@ restart_loop:
                                                wdata->bytes, &tmp_from,
                                                ctx->cfile, cifs_sb, &tmp_list,
                                                ctx);
+
+                                       kref_put(&wdata->refcount,
+                                               cifs_uncached_writedata_release);
                                }
 
                                list_splice(&tmp_list, &ctx->list);
-
-                               kref_put(&wdata->refcount,
-                                        cifs_uncached_writedata_release);
                                goto restart_loop;
                        }
                }
@@ -3348,44 +3361,55 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
        struct TCP_Server_Info *server =
                tlink_tcon(rdata->cfile->tlink)->ses->server;
 
-       /*
-        * Wait for credits to resend this rdata.
-        * Note: we are attempting to resend the whole rdata not in segments
-        */
        do {
-               rc = server->ops->wait_mtu_credits(server, rdata->bytes,
+               if (rdata->cfile->invalidHandle) {
+                       rc = cifs_reopen_file(rdata->cfile, true);
+                       if (rc == -EAGAIN)
+                               continue;
+                       else if (rc)
+                               break;
+               }
+
+               /*
+                * Wait for credits to resend this rdata.
+                * Note: we are attempting to resend the whole rdata not in
+                * segments
+                */
+               do {
+                       rc = server->ops->wait_mtu_credits(server, rdata->bytes,
                                                &rsize, &credits);
 
-               if (rc)
-                       goto out;
+                       if (rc)
+                               goto fail;
 
-               if (rsize < rdata->bytes) {
-                       add_credits_and_wake_if(server, &credits, 0);
-                       msleep(1000);
-               }
-       } while (rsize < rdata->bytes);
+                       if (rsize < rdata->bytes) {
+                               add_credits_and_wake_if(server, &credits, 0);
+                               msleep(1000);
+                       }
+               } while (rsize < rdata->bytes);
+               rdata->credits = credits;
 
-       rdata->credits = credits;
-       rc = -EAGAIN;
-       while (rc == -EAGAIN) {
-               rc = 0;
-               if (rdata->cfile->invalidHandle)
-                       rc = cifs_reopen_file(rdata->cfile, true);
-               if (!rc)
-                       rc = server->ops->async_readv(rdata);
-       }
+               rc = adjust_credits(server, &rdata->credits, rdata->bytes);
+               if (!rc) {
+                       if (rdata->cfile->invalidHandle)
+                               rc = -EAGAIN;
+                       else
+                               rc = server->ops->async_readv(rdata);
+               }
 
-       if (!rc) {
-               /* Add to aio pending list */
-               list_add_tail(&rdata->list, rdata_list);
-               return 0;
-       }
+               /* If the read was successfully sent, we are done */
+               if (!rc) {
+                       /* Add to aio pending list */
+                       list_add_tail(&rdata->list, rdata_list);
+                       return 0;
+               }
 
-       add_credits_and_wake_if(server, &rdata->credits, 0);
-out:
-       kref_put(&rdata->refcount,
-               cifs_uncached_readdata_release);
+               /* Roll back credits and retry if needed */
+               add_credits_and_wake_if(server, &rdata->credits, 0);
+       } while (rc == -EAGAIN);
 
+fail:
+       kref_put(&rdata->refcount, cifs_uncached_readdata_release);
        return rc;
 }
 
index 924269cec1352f75a592ba81e9865bbb030caafe..e32c264e3adbb847653911499ef635c586032c8a 100644 (file)
@@ -1036,7 +1036,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
        {STATUS_UNFINISHED_CONTEXT_DELETED, -EIO,
        "STATUS_UNFINISHED_CONTEXT_DELETED"},
        {STATUS_NO_TGT_REPLY, -EIO, "STATUS_NO_TGT_REPLY"},
-       {STATUS_OBJECTID_NOT_FOUND, -EIO, "STATUS_OBJECTID_NOT_FOUND"},
+       /* Note that ENOATTTR and ENODATA are the same errno */
+       {STATUS_OBJECTID_NOT_FOUND, -ENODATA, "STATUS_OBJECTID_NOT_FOUND"},
        {STATUS_NO_IP_ADDRESSES, -EIO, "STATUS_NO_IP_ADDRESSES"},
        {STATUS_WRONG_CREDENTIAL_HANDLE, -EIO,
        "STATUS_WRONG_CREDENTIAL_HANDLE"},
index c399e09b76e62a7c733857075ff348b039e49a58..21ac19ff19cb2c3257f524f4aef90f0de2e8d342 100644 (file)
@@ -1628,9 +1628,16 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        iov[1].iov_base = unc_path;
        iov[1].iov_len = unc_path_len;
 
-       /* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */
+       /*
+        * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
+        * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
+        * (Samba servers don't always set the flag so also check if null user)
+        */
        if ((ses->server->dialect == SMB311_PROT_ID) &&
-           !smb3_encryption_required(tcon))
+           !smb3_encryption_required(tcon) &&
+           !(ses->session_flags &
+                   (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
+           ((ses->user_name != NULL) || (ses->sectype == Kerberos)))
                req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
 
        memset(&rqst, 0, sizeof(struct smb_rqst));
index fa226de48ef38c0c0696aca767c69cc2ac8dbdd8..99c4d799c24b63c1f16efba4cf5ab1341c9ae90b 100644 (file)
@@ -549,19 +549,19 @@ DECLARE_EVENT_CLASS(smb3_tcon_class,
                __field(unsigned int, xid)
                __field(__u32, tid)
                __field(__u64, sesid)
-               __field(const char *,  unc_name)
+               __string(name, unc_name)
                __field(int, rc)
        ),
        TP_fast_assign(
                __entry->xid = xid;
                __entry->tid = tid;
                __entry->sesid = sesid;
-               __entry->unc_name = unc_name;
+               __assign_str(name, unc_name);
                __entry->rc = rc;
        ),
        TP_printk("xid=%u sid=0x%llx tid=0x%x unc_name=%s rc=%d",
                __entry->xid, __entry->sesid, __entry->tid,
-               __entry->unc_name, __entry->rc)
+               __get_str(name), __entry->rc)
 )
 
 #define DEFINE_SMB3_TCON_EVENT(name)          \