From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 10:58:36 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v6.2.3~103 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ad78a5a21dcbb489210026c2f28c88f16db16507;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: cifs-check-the-lease-context-if-we-actually-got-a-lease.patch cifs-don-t-try-to-use-rdma-offload-on-encrypted-connections.patch cifs-fix-mount-on-old-smb-servers.patch cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch cifs-fix-uninitialized-memory-reads-for-oparms.mode.patch cifs-introduce-cifs_io_parms-in-smb2_async_writev.patch cifs-return-a-single-use-cfid-if-we-did-not-get-a-lease.patch cifs-split-out-smb3_use_rdma_offload-helper.patch kvm-s390-disable-migration-mode-when-dirty-tracking-is-disabled.patch s390-discard-.interp-section.patch s390-extmem-return-correct-segment-type-in-__segment_load.patch s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch scsi-mpi3mr-fix-issues-in-mpi3mr_get_all_tgt_info.patch scsi-mpi3mr-fix-missing-mrioc-evtack_cmds-initialization.patch scsi-mpi3mr-remove-unnecessary-memcpy-to-alltgt_info-dmi.patch --- diff --git a/queue-6.1/cifs-check-the-lease-context-if-we-actually-got-a-lease.patch b/queue-6.1/cifs-check-the-lease-context-if-we-actually-got-a-lease.patch new file mode 100644 index 00000000000..ca2acca2169 --- /dev/null +++ b/queue-6.1/cifs-check-the-lease-context-if-we-actually-got-a-lease.patch @@ -0,0 +1,74 @@ +From 66d45ca1350a3bb8d5f4db8879ccad3ed492337a Mon Sep 17 00:00:00 2001 +From: Ronnie Sahlberg +Date: Fri, 17 Feb 2023 13:35:00 +1000 +Subject: cifs: Check the lease context if we actually got a lease + +From: Ronnie Sahlberg + +commit 66d45ca1350a3bb8d5f4db8879ccad3ed492337a upstream. + +Some servers may return that we got a lease in rsp->OplockLevel +but then in the lease context contradict this and say we got no lease +at all. Thus we need to check the context if we have a lease. +Additionally, If we do not get a lease we need to make sure we close +the handle before we return an error to the caller. + +Signed-off-by: Ronnie Sahlberg +Cc: stable@vger.kernel.org +Reviewed-by: Bharath SM +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cached_dir.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/fs/cifs/cached_dir.c ++++ b/fs/cifs/cached_dir.c +@@ -221,8 +221,7 @@ int open_cached_dir(unsigned int xid, st + } + goto oshr_free; + } +- +- atomic_inc(&tcon->num_remote_opens); ++ cfid->is_open = true; + + o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; + oparms.fid->persistent_fid = o_rsp->PersistentFileId; +@@ -239,7 +238,8 @@ int open_cached_dir(unsigned int xid, st + &oparms.fid->epoch, + oparms.fid->lease_key, &oplock, + NULL, NULL); +- ++ if (!(oplock & SMB2_LEASE_READ_CACHING_HE)) ++ goto oshr_free; + qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; + if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info)) + goto oshr_free; +@@ -262,7 +262,6 @@ int open_cached_dir(unsigned int xid, st + cfid->dentry = dentry; + cfid->tcon = tcon; + cfid->time = jiffies; +- cfid->is_open = true; + cfid->has_lease = true; + + oshr_free: +@@ -282,12 +281,17 @@ oshr_free: + } + spin_unlock(&cfids->cfid_list_lock); + if (rc) { ++ if (cfid->is_open) ++ SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, ++ cfid->fid.volatile_fid); + free_cached_dir(cfid); + cfid = NULL; + } + +- if (rc == 0) ++ if (rc == 0) { + *ret_cfid = cfid; ++ atomic_inc(&tcon->num_remote_opens); ++ } + + return rc; + } diff --git a/queue-6.1/cifs-don-t-try-to-use-rdma-offload-on-encrypted-connections.patch b/queue-6.1/cifs-don-t-try-to-use-rdma-offload-on-encrypted-connections.patch new file mode 100644 index 00000000000..a208ad16d84 --- /dev/null +++ b/queue-6.1/cifs-don-t-try-to-use-rdma-offload-on-encrypted-connections.patch @@ -0,0 +1,48 @@ +From 3891f6c7655a39065e44980f51ba46bb32be3133 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 1 Feb 2023 16:21:41 +0100 +Subject: cifs: don't try to use rdma offload on encrypted connections + +From: Stefan Metzmacher + +commit 3891f6c7655a39065e44980f51ba46bb32be3133 upstream. + +The aim of using encryption on a connection is to keep +the data confidential, so we must not use plaintext rdma offload +for that data! + +It seems that current windows servers and ksmbd would allow +this, but that's no reason to expose the users data in plaintext! +And servers hopefully reject this in future. + +Note modern windows servers support signed or encrypted offload, +see MS-SMB2 2.2.3.1.6 SMB2_RDMA_TRANSFORM_CAPABILITIES, but we don't +support that yet. + +Signed-off-by: Stefan Metzmacher +Cc: Steve French +Cc: Tom Talpey +Cc: Long Li +Cc: Namjae Jeon +Cc: David Howells +Cc: linux-cifs@vger.kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2pdu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4081,6 +4081,10 @@ static inline bool smb3_use_rdma_offload + if (server->sign) + return false; + ++ /* we don't support encrypted offload yet */ ++ if (smb3_encryption_required(tcon)) ++ return false; ++ + /* offload also has its overhead, so only do it if desired */ + if (io_parms->length < server->smbd_conn->rdma_readwrite_threshold) + return false; diff --git a/queue-6.1/cifs-fix-mount-on-old-smb-servers.patch b/queue-6.1/cifs-fix-mount-on-old-smb-servers.patch new file mode 100644 index 00000000000..e1d5184fc15 --- /dev/null +++ b/queue-6.1/cifs-fix-mount-on-old-smb-servers.patch @@ -0,0 +1,140 @@ +From d99e86ebde2d7b3a04190f8d14de5bf6814bf10f Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Thu, 16 Feb 2023 15:33:22 -0300 +Subject: cifs: fix mount on old smb servers + +From: Paulo Alcantara + +commit d99e86ebde2d7b3a04190f8d14de5bf6814bf10f upstream. + +The client was sending rfc1002 session request packet with a wrong +length field set, therefore failing to mount shares against old SMB +servers over port 139. + +Fix this by calculating the correct length as specified in rfc1002. + +Fixes: d7173623bf0b ("cifs: use ALIGN() and round_up() macros") +Cc: stable@vger.kernel.org +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Ronnie Sahlberg +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/connect.c | 94 ++++++++++++++++++----------------------------- + 1 file changed, 35 insertions(+), 59 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index b2a04b4e89a5..af49ae53aaf4 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -2843,72 +2843,48 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + * negprot - BB check reconnection in case where second + * sessinit is sent but no second negprot + */ +- struct rfc1002_session_packet *ses_init_buf; +- unsigned int req_noscope_len; +- struct smb_hdr *smb_buf; ++ struct rfc1002_session_packet req = {}; ++ struct smb_hdr *smb_buf = (struct smb_hdr *)&req; ++ unsigned int len; + +- ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), +- GFP_KERNEL); ++ req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name); + +- if (ses_init_buf) { +- ses_init_buf->trailer.session_req.called_len = 32; ++ if (server->server_RFC1001_name[0] != 0) ++ rfc1002mangle(req.trailer.session_req.called_name, ++ server->server_RFC1001_name, ++ RFC1001_NAME_LEN_WITH_NULL); ++ else ++ rfc1002mangle(req.trailer.session_req.called_name, ++ DEFAULT_CIFS_CALLED_NAME, ++ RFC1001_NAME_LEN_WITH_NULL); + +- if (server->server_RFC1001_name[0] != 0) +- rfc1002mangle(ses_init_buf->trailer. +- session_req.called_name, +- server->server_RFC1001_name, +- RFC1001_NAME_LEN_WITH_NULL); +- else +- rfc1002mangle(ses_init_buf->trailer. +- session_req.called_name, +- DEFAULT_CIFS_CALLED_NAME, +- RFC1001_NAME_LEN_WITH_NULL); ++ req.trailer.session_req.calling_len = sizeof(req.trailer.session_req.calling_name); + +- ses_init_buf->trailer.session_req.calling_len = 32; ++ /* calling name ends in null (byte 16) from old smb convention */ ++ if (server->workstation_RFC1001_name[0] != 0) ++ rfc1002mangle(req.trailer.session_req.calling_name, ++ server->workstation_RFC1001_name, ++ RFC1001_NAME_LEN_WITH_NULL); ++ else ++ rfc1002mangle(req.trailer.session_req.calling_name, ++ "LINUX_CIFS_CLNT", ++ RFC1001_NAME_LEN_WITH_NULL); + +- /* +- * calling name ends in null (byte 16) from old smb +- * convention. +- */ +- if (server->workstation_RFC1001_name[0] != 0) +- rfc1002mangle(ses_init_buf->trailer. +- session_req.calling_name, +- server->workstation_RFC1001_name, +- RFC1001_NAME_LEN_WITH_NULL); +- else +- rfc1002mangle(ses_init_buf->trailer. +- session_req.calling_name, +- "LINUX_CIFS_CLNT", +- RFC1001_NAME_LEN_WITH_NULL); +- +- ses_init_buf->trailer.session_req.scope1 = 0; +- ses_init_buf->trailer.session_req.scope2 = 0; +- smb_buf = (struct smb_hdr *)ses_init_buf; +- +- /* sizeof RFC1002_SESSION_REQUEST with no scopes */ +- req_noscope_len = sizeof(struct rfc1002_session_packet) - 2; +- +- /* == cpu_to_be32(0x81000044) */ +- smb_buf->smb_buf_length = +- cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | req_noscope_len); +- rc = smb_send(server, smb_buf, 0x44); +- kfree(ses_init_buf); +- /* +- * RFC1001 layer in at least one server +- * requires very short break before negprot +- * presumably because not expecting negprot +- * to follow so fast. This is a simple +- * solution that works without +- * complicating the code and causes no +- * significant slowing down on mount +- * for everyone else +- */ +- usleep_range(1000, 2000); +- } + /* +- * else the negprot may still work without this +- * even though malloc failed ++ * As per rfc1002, @len must be the number of bytes that follows the ++ * length field of a rfc1002 session request payload. ++ */ ++ len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req); ++ ++ smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len); ++ rc = smb_send(server, smb_buf, len); ++ /* ++ * RFC1001 layer in at least one server requires very short break before ++ * negprot presumably because not expecting negprot to follow so fast. ++ * This is a simple solution that works without complicating the code ++ * and causes no significant slowing down on mount for everyone else + */ ++ usleep_range(1000, 2000); + + return rc; + } +-- +2.39.2 + diff --git a/queue-6.1/cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch b/queue-6.1/cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch new file mode 100644 index 00000000000..ecd0983d165 --- /dev/null +++ b/queue-6.1/cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch @@ -0,0 +1,42 @@ +From d447e794a37288ec7a080aa1b044a8d9deebbab7 Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Wed, 11 Jan 2023 12:37:58 +0100 +Subject: cifs: Fix uninitialized memory read in smb3_qfs_tcon() + +From: Volker Lendecke + +commit d447e794a37288ec7a080aa1b044a8d9deebbab7 upstream. + +oparms was not fully initialized + +Signed-off-by: Volker Lendecke +Reviewed-by: Paulo Alcantara (SUSE) +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2ops.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -729,12 +729,13 @@ smb3_qfs_tcon(const unsigned int xid, st + struct cifs_fid fid; + struct cached_fid *cfid = NULL; + +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = open_cached_dir(xid, tcon, "", cifs_sb, false, &cfid); + if (rc == 0) diff --git a/queue-6.1/cifs-fix-uninitialized-memory-reads-for-oparms.mode.patch b/queue-6.1/cifs-fix-uninitialized-memory-reads-for-oparms.mode.patch new file mode 100644 index 00000000000..ebfb2518d1c --- /dev/null +++ b/queue-6.1/cifs-fix-uninitialized-memory-reads-for-oparms.mode.patch @@ -0,0 +1,789 @@ +From de036dcaca65cf94bf7ff09c571c077f02bc92b4 Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Wed, 11 Jan 2023 12:37:58 +0100 +Subject: cifs: Fix uninitialized memory reads for oparms.mode + +From: Volker Lendecke + +commit de036dcaca65cf94bf7ff09c571c077f02bc92b4 upstream. + +Use a struct assignment with implicit member initialization + +Signed-off-by: Volker Lendecke +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cached_dir.c | 13 +-- + fs/cifs/cifsacl.c | 34 ++++----- + fs/cifs/cifssmb.c | 17 ++-- + fs/cifs/dir.c | 19 ++--- + fs/cifs/file.c | 35 +++++---- + fs/cifs/inode.c | 53 +++++++------- + fs/cifs/link.c | 66 +++++++++-------- + fs/cifs/smb1ops.c | 72 ++++++++++--------- + fs/cifs/smb2inode.c | 17 ++-- + fs/cifs/smb2ops.c | 191 ++++++++++++++++++++++++++------------------------- + 10 files changed, 274 insertions(+), 243 deletions(-) + +--- a/fs/cifs/cached_dir.c ++++ b/fs/cifs/cached_dir.c +@@ -181,12 +181,13 @@ int open_cached_dir(unsigned int xid, st + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- oparms.tcon = tcon; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE); +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.fid = pfid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE), ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .fid = pfid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -1423,14 +1423,15 @@ static struct cifs_ntsd *get_cifs_acl_by + tcon = tlink_tcon(tlink); + xid = get_xid(); + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = READ_CONTROL; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.disposition = FILE_OPEN; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = READ_CONTROL, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .disposition = FILE_OPEN, ++ .path = path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (!rc) { +@@ -1489,14 +1490,15 @@ int set_cifs_acl(struct cifs_ntsd *pnnts + else + access_flags = WRITE_DAC; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = access_flags; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.disposition = FILE_OPEN; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = access_flags, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .disposition = FILE_OPEN, ++ .path = path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) { +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -5314,14 +5314,15 @@ CIFSSMBSetPathInfoFB(const unsigned int + struct cifs_fid fid; + int rc; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.disposition = FILE_OPEN; +- oparms.path = fileName; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_WRITE, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .disposition = FILE_OPEN, ++ .path = fileName, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -295,15 +295,16 @@ static int cifs_do_create(struct inode * + if (!tcon->unix_ext && (mode & S_IWUGO) == 0) + create_options |= CREATE_OPTION_READONLY; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = desired_access; +- oparms.create_options = cifs_create_options(cifs_sb, create_options); +- oparms.disposition = disposition; +- oparms.path = full_path; +- oparms.fid = fid; +- oparms.reconnect = false; +- oparms.mode = mode; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = desired_access, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .disposition = disposition, ++ .path = full_path, ++ .fid = fid, ++ .mode = mode, ++ }; + rc = server->ops->open(xid, &oparms, oplock, buf); + if (rc) { + cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -260,14 +260,15 @@ static int cifs_nt_open(const char *full + if (f_flags & O_DIRECT) + create_options |= CREATE_NO_BUFFER; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = desired_access; +- oparms.create_options = cifs_create_options(cifs_sb, create_options); +- oparms.disposition = disposition; +- oparms.path = full_path; +- oparms.fid = fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = desired_access, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .disposition = disposition, ++ .path = full_path, ++ .fid = fid, ++ }; + + rc = server->ops->open(xid, &oparms, oplock, buf); + if (rc) +@@ -848,14 +849,16 @@ cifs_reopen_file(struct cifsFileInfo *cf + if (server->ops->get_lease_key) + server->ops->get_lease_key(inode, &cfile->fid); + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = desired_access; +- oparms.create_options = cifs_create_options(cifs_sb, create_options); +- oparms.disposition = disposition; +- oparms.path = full_path; +- oparms.fid = &cfile->fid; +- oparms.reconnect = true; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = desired_access, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .disposition = disposition, ++ .path = full_path, ++ .fid = &cfile->fid, ++ .reconnect = true, ++ }; + + /* + * Can not refresh inode by passing in file_info buf to be returned by +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -508,14 +508,15 @@ cifs_sfu_type(struct cifs_fattr *fattr, + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_READ; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_READ, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .path = path, ++ .fid = &fid, ++ }; + + if (tcon->ses->server->oplocks) + oplock = REQ_OPLOCK; +@@ -1513,14 +1514,15 @@ cifs_rename_pending_delete(const char *f + goto out; + } + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = DELETE | FILE_WRITE_ATTRIBUTES, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .path = full_path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc != 0) +@@ -2107,15 +2109,16 @@ cifs_do_rename(const unsigned int xid, s + if (to_dentry->d_parent != from_dentry->d_parent) + goto do_rename_exit; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- /* open the file to be renamed -- we need DELETE perms */ +- oparms.desired_access = DELETE; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.path = from_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ /* open the file to be renamed -- we need DELETE perms */ ++ .desired_access = DELETE, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .path = from_path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc == 0) { +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -271,14 +271,15 @@ cifs_query_mf_symlink(unsigned int xid, + int buf_type = CIFS_NO_BUFFER; + FILE_ALL_INFO file_info; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_READ; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_READ, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .path = path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, &file_info); + if (rc) +@@ -313,14 +314,15 @@ cifs_create_mf_symlink(unsigned int xid, + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms = {0}; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_CREATE; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_WRITE, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_CREATE, ++ .path = path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) +@@ -355,13 +357,14 @@ smb3_query_mf_symlink(unsigned int xid, + __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct smb2_file_all_info *pfile_info = NULL; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_READ; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_READ, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .fid = &fid, ++ }; + + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); + if (utf16_path == NULL) +@@ -421,14 +424,15 @@ smb3_create_mf_symlink(unsigned int xid, + if (!utf16_path) + return -ENOMEM; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_CREATE; +- oparms.fid = &fid; +- oparms.reconnect = false; +- oparms.mode = 0644; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_WRITE, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_CREATE, ++ .fid = &fid, ++ .mode = 0644, ++ }; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, + NULL, NULL); +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -576,14 +576,15 @@ static int cifs_query_path_info(const un + if (!(le32_to_cpu(fi.Attributes) & ATTR_REPARSE)) + return 0; + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.disposition = FILE_OPEN; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .disposition = FILE_OPEN, ++ .path = full_path, ++ .fid = &fid, ++ }; + + /* Need to check if this is a symbolic link or not */ + tmprc = CIFS_open(xid, &oparms, &oplock, NULL); +@@ -823,14 +824,15 @@ smb_set_file_info(struct inode *inode, c + goto out; + } + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); +- oparms.disposition = FILE_OPEN; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), ++ .disposition = FILE_OPEN, ++ .path = full_path, ++ .fid = &fid, ++ }; + + cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); + rc = CIFS_open(xid, &oparms, &oplock, NULL); +@@ -998,15 +1000,16 @@ cifs_query_symlink(const unsigned int xi + goto out; + } + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.create_options = cifs_create_options(cifs_sb, +- OPEN_REPARSE_POINT); +- oparms.disposition = FILE_OPEN; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .create_options = cifs_create_options(cifs_sb, ++ OPEN_REPARSE_POINT), ++ .disposition = FILE_OPEN, ++ .path = full_path, ++ .fid = &fid, ++ }; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) +@@ -1115,15 +1118,16 @@ cifs_make_node(unsigned int xid, struct + + cifs_dbg(FYI, "sfu compat create special file\n"); + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | +- CREATE_OPTION_SPECIAL); +- oparms.disposition = FILE_CREATE; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_WRITE, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | ++ CREATE_OPTION_SPECIAL), ++ .disposition = FILE_CREATE, ++ .path = full_path, ++ .fid = &fid, ++ }; + + if (tcon->ses->server->oplocks) + oplock = REQ_OPLOCK; +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -104,14 +104,15 @@ static int smb2_compound_op(const unsign + goto finished; + } + +- vars->oparms.tcon = tcon; +- vars->oparms.desired_access = desired_access; +- vars->oparms.disposition = create_disposition; +- vars->oparms.create_options = cifs_create_options(cifs_sb, create_options); +- vars->oparms.fid = &fid; +- vars->oparms.reconnect = false; +- vars->oparms.mode = mode; +- vars->oparms.cifs_sb = cifs_sb; ++ vars->oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = desired_access, ++ .disposition = create_disposition, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .fid = &fid, ++ .mode = mode, ++ .cifs_sb = cifs_sb, ++ }; + + rqst[num_rqst].rq_iov = &vars->open_iov[0]; + rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE; +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -772,12 +772,13 @@ smb2_qfs_tcon(const unsigned int xid, st + struct cifs_open_parms oparms; + struct cifs_fid fid; + +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, + NULL, NULL); +@@ -817,12 +818,13 @@ smb2_is_path_accessible(const unsigned i + if (!utf16_path) + return -ENOMEM; + +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, + &err_iov, &err_buftype); +@@ -1098,13 +1100,13 @@ smb2_set_ea(const unsigned int xid, stru + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- memset(&oparms, 0, sizeof(oparms)); +- oparms.tcon = tcon; +- oparms.desired_access = FILE_WRITE_EA; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_WRITE_EA, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +@@ -1454,12 +1456,12 @@ smb2_ioctl_query_info(const unsigned int + rqst[0].rq_iov = &vars->open_iov[0]; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- memset(&oparms, 0, sizeof(oparms)); +- oparms.tcon = tcon; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, create_options); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .fid = &fid, ++ }; + + if (qi.flags & PASSTHRU_FSCTL) { + switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) { +@@ -2089,12 +2091,13 @@ smb3_notify(const unsigned int xid, stru + } + + tcon = cifs_sb_master_tcon(cifs_sb); +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL, + NULL); +@@ -2160,12 +2163,13 @@ smb2_query_dir_first(const unsigned int + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = fid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +@@ -2491,12 +2495,13 @@ smb2_query_info_compound(const unsigned + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- oparms.tcon = tcon; +- oparms.desired_access = desired_access; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = desired_access, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +@@ -2624,12 +2629,13 @@ smb311_queryfs(const unsigned int xid, s + if (!tcon->posix_extensions) + return smb2_queryfs(xid, tcon, cifs_sb, buf); + +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .fid = &fid, ++ }; + + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, + NULL, NULL); +@@ -2917,13 +2923,13 @@ smb2_query_symlink(const unsigned int xi + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- memset(&oparms, 0, sizeof(oparms)); +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, create_options); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, create_options), ++ .fid = &fid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +@@ -3057,13 +3063,13 @@ smb2_query_reparse_tag(const unsigned in + rqst[0].rq_iov = open_iov; + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + +- memset(&oparms, 0, sizeof(oparms)); +- oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.disposition = FILE_OPEN; +- oparms.create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT); +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = FILE_READ_ATTRIBUTES, ++ .disposition = FILE_OPEN, ++ .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT), ++ .fid = &fid, ++ }; + + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); +@@ -3197,17 +3203,20 @@ get_smb2_acl_by_path(struct cifs_sb_info + return ERR_PTR(rc); + } + +- oparms.tcon = tcon; +- oparms.desired_access = READ_CONTROL; +- oparms.disposition = FILE_OPEN; +- /* +- * When querying an ACL, even if the file is a symlink we want to open +- * the source not the target, and so the protocol requires that the +- * client specify this flag when opening a reparse point +- */ +- oparms.create_options = cifs_create_options(cifs_sb, 0) | OPEN_REPARSE_POINT; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = READ_CONTROL, ++ .disposition = FILE_OPEN, ++ /* ++ * When querying an ACL, even if the file is a symlink ++ * we want to open the source not the target, and so ++ * the protocol requires that the client specify this ++ * flag when opening a reparse point ++ */ ++ .create_options = cifs_create_options(cifs_sb, 0) | ++ OPEN_REPARSE_POINT, ++ .fid = &fid, ++ }; + + if (info & SACL_SECINFO) + oparms.desired_access |= SYSTEM_SECURITY; +@@ -3266,13 +3275,14 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, _ + return rc; + } + +- oparms.tcon = tcon; +- oparms.desired_access = access_flags; +- oparms.create_options = cifs_create_options(cifs_sb, 0); +- oparms.disposition = FILE_OPEN; +- oparms.path = path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .desired_access = access_flags, ++ .create_options = cifs_create_options(cifs_sb, 0), ++ .disposition = FILE_OPEN, ++ .path = path, ++ .fid = &fid, ++ }; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, + NULL, NULL); +@@ -5134,15 +5144,16 @@ smb2_make_node(unsigned int xid, struct + + cifs_dbg(FYI, "sfu compat create special file\n"); + +- oparms.tcon = tcon; +- oparms.cifs_sb = cifs_sb; +- oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | +- CREATE_OPTION_SPECIAL); +- oparms.disposition = FILE_CREATE; +- oparms.path = full_path; +- oparms.fid = &fid; +- oparms.reconnect = false; ++ oparms = (struct cifs_open_parms) { ++ .tcon = tcon, ++ .cifs_sb = cifs_sb, ++ .desired_access = GENERIC_WRITE, ++ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | ++ CREATE_OPTION_SPECIAL), ++ .disposition = FILE_CREATE, ++ .path = full_path, ++ .fid = &fid, ++ }; + + if (tcon->ses->server->oplocks) + oplock = REQ_OPLOCK; diff --git a/queue-6.1/cifs-introduce-cifs_io_parms-in-smb2_async_writev.patch b/queue-6.1/cifs-introduce-cifs_io_parms-in-smb2_async_writev.patch new file mode 100644 index 00000000000..09826d7d866 --- /dev/null +++ b/queue-6.1/cifs-introduce-cifs_io_parms-in-smb2_async_writev.patch @@ -0,0 +1,138 @@ +From d643a8a446fc46c06837d08a056f69da2ff16025 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 1 Feb 2023 16:21:39 +0100 +Subject: cifs: introduce cifs_io_parms in smb2_async_writev() + +From: Stefan Metzmacher + +commit d643a8a446fc46c06837d08a056f69da2ff16025 upstream. + +This will simplify the following changes and makes it easy to get +in passed in from the caller in future. + +Signed-off-by: Stefan Metzmacher +Cc: Steve French +Cc: Tom Talpey +Cc: Long Li +Cc: Namjae Jeon +Cc: David Howells +Cc: linux-cifs@vger.kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2pdu.c | 53 +++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 39 insertions(+), 14 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4504,10 +4504,27 @@ smb2_async_writev(struct cifs_writedata + struct kvec iov[1]; + struct smb_rqst rqst = { }; + unsigned int total_len; ++ struct cifs_io_parms _io_parms; ++ struct cifs_io_parms *io_parms = NULL; + + if (!wdata->server) + server = wdata->server = cifs_pick_channel(tcon->ses); + ++ /* ++ * in future we may get cifs_io_parms passed in from the caller, ++ * but for now we construct it here... ++ */ ++ _io_parms = (struct cifs_io_parms) { ++ .tcon = tcon, ++ .server = server, ++ .offset = wdata->offset, ++ .length = wdata->bytes, ++ .persistent_fid = wdata->cfile->fid.persistent_fid, ++ .volatile_fid = wdata->cfile->fid.volatile_fid, ++ .pid = wdata->pid, ++ }; ++ io_parms = &_io_parms; ++ + rc = smb2_plain_req_init(SMB2_WRITE, tcon, server, + (void **) &req, &total_len); + if (rc) +@@ -4517,26 +4534,31 @@ smb2_async_writev(struct cifs_writedata + flags |= CIFS_TRANSFORM_REQ; + + shdr = (struct smb2_hdr *)req; +- shdr->Id.SyncId.ProcessId = cpu_to_le32(wdata->cfile->pid); ++ shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid); + +- req->PersistentFileId = wdata->cfile->fid.persistent_fid; +- req->VolatileFileId = wdata->cfile->fid.volatile_fid; ++ req->PersistentFileId = io_parms->persistent_fid; ++ req->VolatileFileId = io_parms->volatile_fid; + req->WriteChannelInfoOffset = 0; + req->WriteChannelInfoLength = 0; + req->Channel = 0; +- req->Offset = cpu_to_le64(wdata->offset); ++ req->Offset = cpu_to_le64(io_parms->offset); + req->DataOffset = cpu_to_le16( + offsetof(struct smb2_write_req, Buffer)); + req->RemainingBytes = 0; + +- trace_smb3_write_enter(0 /* xid */, wdata->cfile->fid.persistent_fid, +- tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes); ++ trace_smb3_write_enter(0 /* xid */, ++ io_parms->persistent_fid, ++ io_parms->tcon->tid, ++ io_parms->tcon->ses->Suid, ++ io_parms->offset, ++ io_parms->length); ++ + #ifdef CONFIG_CIFS_SMB_DIRECT + /* + * If we want to do a server RDMA read, fill in and append + * smbd_buffer_descriptor_v1 to the end of write request + */ +- if (server->rdma && !server->sign && wdata->bytes >= ++ if (server->rdma && !server->sign && io_parms->length >= + server->smbd_conn->rdma_readwrite_threshold) { + + struct smbd_buffer_descriptor_v1 *v1; +@@ -4590,14 +4612,14 @@ smb2_async_writev(struct cifs_writedata + } + #endif + cifs_dbg(FYI, "async write at %llu %u bytes\n", +- wdata->offset, wdata->bytes); ++ io_parms->offset, io_parms->length); + + #ifdef CONFIG_CIFS_SMB_DIRECT + /* For RDMA read, I/O size is in RemainingBytes not in Length */ + if (!wdata->mr) +- req->Length = cpu_to_le32(wdata->bytes); ++ req->Length = cpu_to_le32(io_parms->length); + #else +- req->Length = cpu_to_le32(wdata->bytes); ++ req->Length = cpu_to_le32(io_parms->length); + #endif + + if (wdata->credits.value > 0) { +@@ -4605,7 +4627,7 @@ smb2_async_writev(struct cifs_writedata + SMB2_MAX_BUFFER_SIZE)); + shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8); + +- rc = adjust_credits(server, &wdata->credits, wdata->bytes); ++ rc = adjust_credits(server, &wdata->credits, io_parms->length); + if (rc) + goto async_writev_out; + +@@ -4618,9 +4640,12 @@ smb2_async_writev(struct cifs_writedata + + if (rc) { + trace_smb3_write_err(0 /* no xid */, +- req->PersistentFileId, +- tcon->tid, tcon->ses->Suid, wdata->offset, +- wdata->bytes, rc); ++ io_parms->persistent_fid, ++ io_parms->tcon->tid, ++ io_parms->tcon->ses->Suid, ++ io_parms->offset, ++ io_parms->length, ++ rc); + kref_put(&wdata->refcount, release); + cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); + } diff --git a/queue-6.1/cifs-return-a-single-use-cfid-if-we-did-not-get-a-lease.patch b/queue-6.1/cifs-return-a-single-use-cfid-if-we-did-not-get-a-lease.patch new file mode 100644 index 00000000000..89a6539e84a --- /dev/null +++ b/queue-6.1/cifs-return-a-single-use-cfid-if-we-did-not-get-a-lease.patch @@ -0,0 +1,95 @@ +From 8e843bf38f7be0766642a91523cfa65f2b021a8a Mon Sep 17 00:00:00 2001 +From: Ronnie Sahlberg +Date: Fri, 17 Feb 2023 13:35:01 +1000 +Subject: cifs: return a single-use cfid if we did not get a lease + +From: Ronnie Sahlberg + +commit 8e843bf38f7be0766642a91523cfa65f2b021a8a upstream. + +If we did not get a lease we can still return a single use cfid to the caller. +The cfid will not have has_lease set and will thus not be shared with any +other concurrent users and will be freed immediately when the caller +drops the handle. + +This avoids extra roundtrips for servers that do not support directory leases +where they would first fail to get a cfid with a lease and then fallback +to try a normal SMB2_open() + +Signed-off-by: Ronnie Sahlberg +Cc: stable@vger.kernel.org +Reviewed-by: Bharath SM +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cached_dir.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/cifs/cached_dir.c ++++ b/fs/cifs/cached_dir.c +@@ -14,6 +14,7 @@ + + static struct cached_fid *init_cached_dir(const char *path); + static void free_cached_dir(struct cached_fid *cfid); ++static void smb2_close_cached_fid(struct kref *ref); + + static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, + const char *path, +@@ -221,6 +222,7 @@ int open_cached_dir(unsigned int xid, st + } + goto oshr_free; + } ++ cfid->tcon = tcon; + cfid->is_open = true; + + o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; +@@ -233,7 +235,6 @@ int open_cached_dir(unsigned int xid, st + if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) + goto oshr_free; + +- + smb2_parse_contexts(server, o_rsp, + &oparms.fid->epoch, + oparms.fid->lease_key, &oplock, +@@ -260,7 +261,6 @@ int open_cached_dir(unsigned int xid, st + } + } + cfid->dentry = dentry; +- cfid->tcon = tcon; + cfid->time = jiffies; + cfid->has_lease = true; + +@@ -271,7 +271,7 @@ oshr_free: + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); + spin_lock(&cfids->cfid_list_lock); +- if (!cfid->has_lease) { ++ if (rc && !cfid->has_lease) { + if (cfid->on_list) { + list_del(&cfid->entry); + cfid->on_list = false; +@@ -280,6 +280,15 @@ oshr_free: + rc = -ENOENT; + } + spin_unlock(&cfids->cfid_list_lock); ++ if (!rc && !cfid->has_lease) { ++ /* ++ * We are guaranteed to have two references at this point. ++ * One for the caller and one for a potential lease. ++ * Release the Lease-ref so that the directory will be closed ++ * when the caller closes the cached handle. ++ */ ++ kref_put(&cfid->refcount, smb2_close_cached_fid); ++ } + if (rc) { + if (cfid->is_open) + SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, +@@ -340,6 +349,7 @@ smb2_close_cached_fid(struct kref *ref) + if (cfid->is_open) { + SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, + cfid->fid.volatile_fid); ++ atomic_dec(&cfid->tcon->num_remote_opens); + } + + free_cached_dir(cfid); diff --git a/queue-6.1/cifs-split-out-smb3_use_rdma_offload-helper.patch b/queue-6.1/cifs-split-out-smb3_use_rdma_offload-helper.patch new file mode 100644 index 00000000000..c51078a606a --- /dev/null +++ b/queue-6.1/cifs-split-out-smb3_use_rdma_offload-helper.patch @@ -0,0 +1,83 @@ +From a6559cc1d35d3eeafb0296aca347b2f745a28a74 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 1 Feb 2023 16:21:40 +0100 +Subject: cifs: split out smb3_use_rdma_offload() helper + +From: Stefan Metzmacher + +commit a6559cc1d35d3eeafb0296aca347b2f745a28a74 upstream. + +We should have the logic to decide if we want rdma offload +in a single spot in order to advance it in future. + +Signed-off-by: Stefan Metzmacher +Cc: Steve French +Cc: Tom Talpey +Cc: Long Li +Cc: Namjae Jeon +Cc: David Howells +Cc: linux-cifs@vger.kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2pdu.c | 34 ++++++++++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 6 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4063,6 +4063,32 @@ SMB2_flush(const unsigned int xid, struc + return rc; + } + ++#ifdef CONFIG_CIFS_SMB_DIRECT ++static inline bool smb3_use_rdma_offload(struct cifs_io_parms *io_parms) ++{ ++ struct TCP_Server_Info *server = io_parms->server; ++ struct cifs_tcon *tcon = io_parms->tcon; ++ ++ /* we can only offload if we're connected */ ++ if (!server || !tcon) ++ return false; ++ ++ /* we can only offload on an rdma connection */ ++ if (!server->rdma || !server->smbd_conn) ++ return false; ++ ++ /* we don't support signed offload yet */ ++ if (server->sign) ++ return false; ++ ++ /* offload also has its overhead, so only do it if desired */ ++ if (io_parms->length < server->smbd_conn->rdma_readwrite_threshold) ++ return false; ++ ++ return true; ++} ++#endif /* CONFIG_CIFS_SMB_DIRECT */ ++ + /* + * To form a chain of read requests, any read requests after the first should + * have the end_of_chain boolean set to true. +@@ -4106,9 +4132,7 @@ smb2_new_read_req(void **buf, unsigned i + * If we want to do a RDMA write, fill in and append + * smbd_buffer_descriptor_v1 to the end of read request + */ +- if (server->rdma && rdata && !server->sign && +- rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) { +- ++ if (smb3_use_rdma_offload(io_parms)) { + struct smbd_buffer_descriptor_v1 *v1; + bool need_invalidate = server->dialect == SMB30_PROT_ID; + +@@ -4558,9 +4582,7 @@ smb2_async_writev(struct cifs_writedata + * If we want to do a server RDMA read, fill in and append + * smbd_buffer_descriptor_v1 to the end of write request + */ +- if (server->rdma && !server->sign && io_parms->length >= +- server->smbd_conn->rdma_readwrite_threshold) { +- ++ if (smb3_use_rdma_offload(io_parms)) { + struct smbd_buffer_descriptor_v1 *v1; + bool need_invalidate = server->dialect == SMB30_PROT_ID; + diff --git a/queue-6.1/kvm-s390-disable-migration-mode-when-dirty-tracking-is-disabled.patch b/queue-6.1/kvm-s390-disable-migration-mode-when-dirty-tracking-is-disabled.patch new file mode 100644 index 00000000000..a2325135697 --- /dev/null +++ b/queue-6.1/kvm-s390-disable-migration-mode-when-dirty-tracking-is-disabled.patch @@ -0,0 +1,158 @@ +From f2d3155e2a6bac44d16f04415a321e8707d895c6 Mon Sep 17 00:00:00 2001 +From: Nico Boehr +Date: Fri, 27 Jan 2023 15:05:32 +0100 +Subject: KVM: s390: disable migration mode when dirty tracking is disabled + +From: Nico Boehr + +commit f2d3155e2a6bac44d16f04415a321e8707d895c6 upstream. + +Migration mode is a VM attribute which enables tracking of changes in +storage attributes (PGSTE). It assumes dirty tracking is enabled on all +memslots to keep a dirty bitmap of pages with changed storage attributes. + +When enabling migration mode, we currently check that dirty tracking is +enabled for all memslots. However, userspace can disable dirty tracking +without disabling migration mode. + +Since migration mode is pointless with dirty tracking disabled, disable +migration mode whenever userspace disables dirty tracking on any slot. + +Also update the documentation to clarify that dirty tracking must be +enabled when enabling migration mode, which is already enforced by the +code in kvm_s390_vm_start_migration(). + +Also highlight in the documentation for KVM_S390_GET_CMMA_BITS that it +can now fail with -EINVAL when dirty tracking is disabled while +migration mode is on. Move all the error codes to a table so this stays +readable. + +To disable migration mode, slots_lock should be held, which is taken +in kvm_set_memory_region() and thus held in +kvm_arch_prepare_memory_region(). + +Restructure the prepare code a bit so all the sanity checking is done +before disabling migration mode. This ensures migration mode isn't +disabled when some sanity check fails. + +Cc: stable@vger.kernel.org +Fixes: 190df4a212a7 ("KVM: s390: CMMA tracking, ESSA emulation, migration mode") +Signed-off-by: Nico Boehr +Reviewed-by: Janosch Frank +Reviewed-by: Claudio Imbrenda +Link: https://lore.kernel.org/r/20230127140532.230651-2-nrb@linux.ibm.com +Message-Id: <20230127140532.230651-2-nrb@linux.ibm.com> +[frankja@linux.ibm.com: fixed commit message typo, moved api.rst error table upwards] +Signed-off-by: Janosch Frank +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/virt/kvm/api.rst | 18 ++++++++----- + Documentation/virt/kvm/devices/vm.rst | 4 ++ + arch/s390/kvm/kvm-s390.c | 47 +++++++++++++++++++++++----------- + 3 files changed, 48 insertions(+), 21 deletions(-) + +--- a/Documentation/virt/kvm/api.rst ++++ b/Documentation/virt/kvm/api.rst +@@ -4483,6 +4483,18 @@ not holding a previously reported uncorr + :Parameters: struct kvm_s390_cmma_log (in, out) + :Returns: 0 on success, a negative value on error + ++Errors: ++ ++ ====== ============================================================= ++ ENOMEM not enough memory can be allocated to complete the task ++ ENXIO if CMMA is not enabled ++ EINVAL if KVM_S390_CMMA_PEEK is not set but migration mode was not enabled ++ EINVAL if KVM_S390_CMMA_PEEK is not set but dirty tracking has been ++ disabled (and thus migration mode was automatically disabled) ++ EFAULT if the userspace address is invalid or if no page table is ++ present for the addresses (e.g. when using hugepages). ++ ====== ============================================================= ++ + This ioctl is used to get the values of the CMMA bits on the s390 + architecture. It is meant to be used in two scenarios: + +@@ -4563,12 +4575,6 @@ mask is unused. + + values points to the userspace buffer where the result will be stored. + +-This ioctl can fail with -ENOMEM if not enough memory can be allocated to +-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if +-KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with +--EFAULT if the userspace address is invalid or if no page table is +-present for the addresses (e.g. when using hugepages). +- + 4.108 KVM_S390_SET_CMMA_BITS + ---------------------------- + +--- a/Documentation/virt/kvm/devices/vm.rst ++++ b/Documentation/virt/kvm/devices/vm.rst +@@ -302,6 +302,10 @@ Allows userspace to start migration mode + Setting this attribute when migration mode is already active will have + no effects. + ++Dirty tracking must be enabled on all memslots, else -EINVAL is returned. When ++dirty tracking is disabled on any memslot, migration mode is automatically ++stopped. ++ + :Parameters: none + :Returns: -ENOMEM if there is not enough free memory to start migration mode; + -EINVAL if the state of the VM is invalid (e.g. no memory defined); +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -5579,23 +5579,40 @@ int kvm_arch_prepare_memory_region(struc + if (kvm_s390_pv_get_handle(kvm)) + return -EINVAL; + +- if (change == KVM_MR_DELETE || change == KVM_MR_FLAGS_ONLY) +- return 0; +- +- /* A few sanity checks. We can have memory slots which have to be +- located/ended at a segment boundary (1MB). The memory in userland is +- ok to be fragmented into various different vmas. It is okay to mmap() +- and munmap() stuff in this slot after doing this call at any time */ +- +- if (new->userspace_addr & 0xffffful) +- return -EINVAL; ++ if (change != KVM_MR_DELETE && change != KVM_MR_FLAGS_ONLY) { ++ /* ++ * A few sanity checks. We can have memory slots which have to be ++ * located/ended at a segment boundary (1MB). The memory in userland is ++ * ok to be fragmented into various different vmas. It is okay to mmap() ++ * and munmap() stuff in this slot after doing this call at any time ++ */ ++ ++ if (new->userspace_addr & 0xffffful) ++ return -EINVAL; ++ ++ size = new->npages * PAGE_SIZE; ++ if (size & 0xffffful) ++ return -EINVAL; ++ ++ if ((new->base_gfn * PAGE_SIZE) + size > kvm->arch.mem_limit) ++ return -EINVAL; ++ } + +- size = new->npages * PAGE_SIZE; +- if (size & 0xffffful) +- return -EINVAL; ++ if (!kvm->arch.migration_mode) ++ return 0; + +- if ((new->base_gfn * PAGE_SIZE) + size > kvm->arch.mem_limit) +- return -EINVAL; ++ /* ++ * Turn off migration mode when: ++ * - userspace creates a new memslot with dirty logging off, ++ * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and ++ * dirty logging is turned off. ++ * Migration mode expects dirty page logging being enabled to store ++ * its dirty bitmap. ++ */ ++ if (change != KVM_MR_DELETE && ++ !(new->flags & KVM_MEM_LOG_DIRTY_PAGES)) ++ WARN(kvm_s390_vm_stop_migration(kvm), ++ "Failed to stop migration mode"); + + return 0; + } diff --git a/queue-6.1/s390-discard-.interp-section.patch b/queue-6.1/s390-discard-.interp-section.patch new file mode 100644 index 00000000000..fbd13d46e87 --- /dev/null +++ b/queue-6.1/s390-discard-.interp-section.patch @@ -0,0 +1,48 @@ +From e9c9cb90e76ffaabcc7ca8f275d9e82195fd6367 Mon Sep 17 00:00:00 2001 +From: Ilya Leoshkevich +Date: Mon, 23 Jan 2023 22:50:32 +0100 +Subject: s390: discard .interp section + +From: Ilya Leoshkevich + +commit e9c9cb90e76ffaabcc7ca8f275d9e82195fd6367 upstream. + +When debugging vmlinux with QEMU + GDB, the following GDB error may +occur: + + (gdb) c + Continuing. + Warning: + Cannot insert breakpoint -1. + Cannot access memory at address 0xffffffffffff95c0 + + Command aborted. + (gdb) + +The reason is that, when .interp section is present, GDB tries to +locate the file specified in it in memory and put a number of +breakpoints there (see enable_break() function in gdb/solib-svr4.c). +Sometimes GDB finds a bogus location that matches its heuristics, +fails to set a breakpoint and stops. This makes further debugging +impossible. + +The .interp section contains misleading information anyway (vmlinux +does not need ld.so), so fix by discarding it. + +Signed-off-by: Ilya Leoshkevich +Cc: +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/kernel/vmlinux.lds.S | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/s390/kernel/vmlinux.lds.S ++++ b/arch/s390/kernel/vmlinux.lds.S +@@ -228,5 +228,6 @@ SECTIONS + DISCARDS + /DISCARD/ : { + *(.eh_frame) ++ *(.interp) + } + } diff --git a/queue-6.1/s390-extmem-return-correct-segment-type-in-__segment_load.patch b/queue-6.1/s390-extmem-return-correct-segment-type-in-__segment_load.patch new file mode 100644 index 00000000000..ac526d021e2 --- /dev/null +++ b/queue-6.1/s390-extmem-return-correct-segment-type-in-__segment_load.patch @@ -0,0 +1,76 @@ +From 8c42dd78df148c90e48efff204cce38743906a79 Mon Sep 17 00:00:00 2001 +From: Gerald Schaefer +Date: Mon, 27 Feb 2023 20:03:00 +0100 +Subject: s390/extmem: return correct segment type in __segment_load() + +From: Gerald Schaefer + +commit 8c42dd78df148c90e48efff204cce38743906a79 upstream. + +Commit f05f62d04271f ("s390/vmem: get rid of memory segment list") +reshuffled the call to vmem_add_mapping() in __segment_load(), which now +overwrites rc after it was set to contain the segment type code. + +As result, __segment_load() will now always return 0 on success, which +corresponds to the segment type code SEG_TYPE_SW, i.e. a writeable +segment. This results in a kernel crash when loading a read-only segment +as dcssblk block device, and trying to write to it. + +Instead of reshuffling code again, make sure to return the segment type +on success, and also describe this rather delicate and unexpected logic +in the function comment. Also initialize new segtype variable with +invalid value, to prevent possible future confusion. + +Fixes: f05f62d04271 ("s390/vmem: get rid of memory segment list") +Cc: # 5.9+ +Signed-off-by: Gerald Schaefer +Reviewed-by: Heiko Carstens +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/mm/extmem.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/arch/s390/mm/extmem.c ++++ b/arch/s390/mm/extmem.c +@@ -289,15 +289,17 @@ segment_overlaps_others (struct dcss_seg + + /* + * real segment loading function, called from segment_load ++ * Must return either an error code < 0, or the segment type code >= 0 + */ + static int + __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end) + { + unsigned long start_addr, end_addr, dummy; + struct dcss_segment *seg; +- int rc, diag_cc; ++ int rc, diag_cc, segtype; + + start_addr = end_addr = 0; ++ segtype = -1; + seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); + if (seg == NULL) { + rc = -ENOMEM; +@@ -326,9 +328,9 @@ __segment_load (char *name, int do_nonsh + seg->res_name[8] = '\0'; + strlcat(seg->res_name, " (DCSS)", sizeof(seg->res_name)); + seg->res->name = seg->res_name; +- rc = seg->vm_segtype; +- if (rc == SEG_TYPE_SC || +- ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) ++ segtype = seg->vm_segtype; ++ if (segtype == SEG_TYPE_SC || ++ ((segtype == SEG_TYPE_SR || segtype == SEG_TYPE_ER) && !do_nonshared)) + seg->res->flags |= IORESOURCE_READONLY; + + /* Check for overlapping resources before adding the mapping. */ +@@ -386,7 +388,7 @@ __segment_load (char *name, int do_nonsh + out_free: + kfree(seg); + out: +- return rc; ++ return rc < 0 ? rc : segtype; + } + + /* diff --git a/queue-6.1/s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch b/queue-6.1/s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch new file mode 100644 index 00000000000..5dd0f072243 --- /dev/null +++ b/queue-6.1/s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch @@ -0,0 +1,54 @@ +From cd57953936f2213dfaccce10d20f396956222c7d Mon Sep 17 00:00:00 2001 +From: Vasily Gorbik +Date: Wed, 1 Mar 2023 17:58:06 +0100 +Subject: s390/kprobes: fix current_kprobe never cleared after kprobes reenter + +From: Vasily Gorbik + +commit cd57953936f2213dfaccce10d20f396956222c7d upstream. + +Recent test_kprobe_missed kprobes kunit test uncovers the following +problem. Once kprobe is triggered from another kprobe (kprobe reenter), +all future kprobes on this cpu are considered as kprobe reenter, thus +pre_handler and post_handler are not being called and kprobes are counted +as "missed". + +Commit b9599798f953 ("[S390] kprobes: activation and deactivation") +introduced a simpler scheme for kprobes (de)activation and status +tracking by using push_kprobe/pop_kprobe, which supposed to work for +both initial kprobe entry as well as kprobe reentry and helps to avoid +handling those two cases differently. The problem is that a sequence of +calls in case of kprobes reenter: +push_kprobe() <- NULL (current_kprobe) +push_kprobe() <- kprobe1 (current_kprobe) +pop_kprobe() -> kprobe1 (current_kprobe) +pop_kprobe() -> kprobe1 (current_kprobe) +leaves "kprobe1" as "current_kprobe" on this cpu, instead of setting it +to NULL. In fact push_kprobe/pop_kprobe can only store a single state +(there is just one prev_kprobe in kprobe_ctlblk). Which is a hack but +sufficient, there is no need to have another prev_kprobe just to store +NULL. To make a simple and backportable fix simply reset "prev_kprobe" +when kprobe is poped from this "stack". No need to worry about +"kprobe_status" in this case, because its value is only checked when +current_kprobe != NULL. + +Cc: stable@vger.kernel.org +Fixes: b9599798f953 ("[S390] kprobes: activation and deactivation") +Reviewed-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/kernel/kprobes.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/s390/kernel/kprobes.c ++++ b/arch/s390/kernel/kprobes.c +@@ -279,6 +279,7 @@ static void pop_kprobe(struct kprobe_ctl + { + __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); + kcb->kprobe_status = kcb->prev_kprobe.status; ++ kcb->prev_kprobe.kp = NULL; + } + NOKPROBE_SYMBOL(pop_kprobe); + diff --git a/queue-6.1/s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch b/queue-6.1/s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch new file mode 100644 index 00000000000..e48104dae5d --- /dev/null +++ b/queue-6.1/s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch @@ -0,0 +1,80 @@ +From 42e19e6f04984088b6f9f0507c4c89a8152d9730 Mon Sep 17 00:00:00 2001 +From: Vasily Gorbik +Date: Wed, 1 Mar 2023 02:23:08 +0100 +Subject: s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler + +From: Vasily Gorbik + +commit 42e19e6f04984088b6f9f0507c4c89a8152d9730 upstream. + +Recent test_kprobe_missed kprobes kunit test uncovers the following error +(reported when CONFIG_DEBUG_ATOMIC_SLEEP is enabled): + +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580 +in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 662, name: kunit_try_catch +preempt_count: 0, expected: 0 +RCU nest depth: 0, expected: 0 +no locks held by kunit_try_catch/662. +irq event stamp: 280 +hardirqs last enabled at (279): [<00000003e60a3d42>] __do_pgm_check+0x17a/0x1c0 +hardirqs last disabled at (280): [<00000003e3bd774a>] kprobe_exceptions_notify+0x27a/0x318 +softirqs last enabled at (0): [<00000003e3c5c890>] copy_process+0x14a8/0x4c80 +softirqs last disabled at (0): [<0000000000000000>] 0x0 +CPU: 46 PID: 662 Comm: kunit_try_catch Tainted: G N 6.2.0-173644-g44c18d77f0c0 #2 +Hardware name: IBM 3931 A01 704 (LPAR) +Call Trace: + [<00000003e60a3a00>] dump_stack_lvl+0x120/0x198 + [<00000003e3d02e82>] __might_resched+0x60a/0x668 + [<00000003e60b9908>] __mutex_lock+0xc0/0x14e0 + [<00000003e60bad5a>] mutex_lock_nested+0x32/0x40 + [<00000003e3f7b460>] unregister_kprobe+0x30/0xd8 + [<00000003e51b2602>] test_kprobe_missed+0xf2/0x268 + [<00000003e51b5406>] kunit_try_run_case+0x10e/0x290 + [<00000003e51b7dfa>] kunit_generic_run_threadfn_adapter+0x62/0xb8 + [<00000003e3ce30f8>] kthread+0x2d0/0x398 + [<00000003e3b96afa>] __ret_from_fork+0x8a/0xe8 + [<00000003e60ccada>] ret_from_fork+0xa/0x40 + +The reason for this error report is that kprobes handling code failed +to restore irqs. + +The problem is that when kprobe is triggered from another kprobe +post_handler current sequence of enable_singlestep / disable_singlestep +is the following: +enable_singlestep <- original kprobe (saves kprobe_saved_imask) +enable_singlestep <- kprobe triggered from post_handler (clobbers kprobe_saved_imask) +disable_singlestep <- kprobe triggered from post_handler (restores kprobe_saved_imask) +disable_singlestep <- original kprobe (restores wrong clobbered kprobe_saved_imask) + +There is just one kprobe_ctlblk per cpu and both calls saves and +loads irq mask to kprobe_saved_imask. To fix the problem simply move +resume_execution (which calls disable_singlestep) before calling +post_handler. This also fixes the problem that post_handler is called +with pt_regs which were not yet adjusted after single-stepping. + +Cc: stable@vger.kernel.org +Fixes: 4ba069b802c2 ("[S390] add kprobes support.") +Reviewed-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/kernel/kprobes.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/s390/kernel/kprobes.c ++++ b/arch/s390/kernel/kprobes.c +@@ -433,12 +433,11 @@ static int post_kprobe_handler(struct pt + if (!p) + return 0; + ++ resume_execution(p, regs); + if (kcb->kprobe_status != KPROBE_REENTER && p->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + p->post_handler(p, regs, 0); + } +- +- resume_execution(p, regs); + pop_kprobe(kcb); + preempt_enable_no_resched(); + diff --git a/queue-6.1/scsi-mpi3mr-fix-issues-in-mpi3mr_get_all_tgt_info.patch b/queue-6.1/scsi-mpi3mr-fix-issues-in-mpi3mr_get_all_tgt_info.patch new file mode 100644 index 00000000000..bc1227040ef --- /dev/null +++ b/queue-6.1/scsi-mpi3mr-fix-issues-in-mpi3mr_get_all_tgt_info.patch @@ -0,0 +1,95 @@ +From fb428a2005fc1260d18b989cc5199f281617f44d Mon Sep 17 00:00:00 2001 +From: Shin'ichiro Kawasaki +Date: Tue, 14 Feb 2023 09:50:16 +0900 +Subject: scsi: mpi3mr: Fix issues in mpi3mr_get_all_tgt_info() + +From: Shin'ichiro Kawasaki + +commit fb428a2005fc1260d18b989cc5199f281617f44d upstream. + +The function mpi3mr_get_all_tgt_info() has four issues: + +1) It calculates valid entry length in alltgt_info assuming the header part + of the struct mpi3mr_device_map_info would equal to sizeof(u32). The + correct size is sizeof(u64). + +2) When it calculates the valid entry length kern_entrylen, it excludes one + entry by subtracting 1 from num_devices. + +3) It copies num_device by calling memcpy(). Substitution is enough. + +4) It does not specify the calculated length to sg_copy_from_buffer(). + Instead, it specifies the payload length which is larger than the + alltgt_info size. It causes "BUG: KASAN: slab-out-of-bounds". + +Fix the issues by using the correct header size, removing the subtraction +from num_devices, replacing the memcpy() with substitution and specifying +the correct length to sg_copy_from_buffer(). + +Link: https://lore.kernel.org/r/20230214005019.1897251-2-shinichiro.kawasaki@wdc.com +Cc: stable@vger.kernel.org +Fixes: f5e6d5a34376 ("scsi: mpi3mr: Add support for driver commands") +Signed-off-by: Shin'ichiro Kawasaki +Acked-by: Sathya Prakash Veerichetty +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/mpi3mr/mpi3mr_app.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c +index 9baac224b213..72054e3a26cb 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_app.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_app.c +@@ -312,7 +312,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + num_devices++; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + +- if ((job->request_payload.payload_len == sizeof(u32)) || ++ if ((job->request_payload.payload_len <= sizeof(u64)) || + list_empty(&mrioc->tgtdev_list)) { + sg_copy_from_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, +@@ -320,14 +320,14 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + return 0; + } + +- kern_entrylen = (num_devices - 1) * sizeof(*devmap_info); +- size = sizeof(*alltgt_info) + kern_entrylen; ++ kern_entrylen = num_devices * sizeof(*devmap_info); ++ size = sizeof(u64) + kern_entrylen; + alltgt_info = kzalloc(size, GFP_KERNEL); + if (!alltgt_info) + return -ENOMEM; + + devmap_info = alltgt_info->dmi; +- memset((u8 *)devmap_info, 0xFF, (kern_entrylen + sizeof(*devmap_info))); ++ memset((u8 *)devmap_info, 0xFF, kern_entrylen); + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) { + if (i < num_devices) { +@@ -344,9 +344,10 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + num_devices = i; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + +- memcpy(&alltgt_info->num_devices, &num_devices, sizeof(num_devices)); ++ alltgt_info->num_devices = num_devices; + +- usr_entrylen = (job->request_payload.payload_len - sizeof(u32)) / sizeof(*devmap_info); ++ usr_entrylen = (job->request_payload.payload_len - sizeof(u64)) / ++ sizeof(*devmap_info); + usr_entrylen *= sizeof(*devmap_info); + min_entrylen = min(usr_entrylen, kern_entrylen); + if (min_entrylen && (!memcpy(&alltgt_info->dmi, devmap_info, min_entrylen))) { +@@ -358,7 +359,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + + sg_copy_from_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, +- alltgt_info, job->request_payload.payload_len); ++ alltgt_info, (min_entrylen + sizeof(u64))); + rval = 0; + out: + kfree(alltgt_info); +-- +2.39.2 + diff --git a/queue-6.1/scsi-mpi3mr-fix-missing-mrioc-evtack_cmds-initialization.patch b/queue-6.1/scsi-mpi3mr-fix-missing-mrioc-evtack_cmds-initialization.patch new file mode 100644 index 00000000000..6c900edf148 --- /dev/null +++ b/queue-6.1/scsi-mpi3mr-fix-missing-mrioc-evtack_cmds-initialization.patch @@ -0,0 +1,44 @@ +From e39ea831ebad4ab15c4748cb62a397a8abcca36e Mon Sep 17 00:00:00 2001 +From: Shin'ichiro Kawasaki +Date: Tue, 14 Feb 2023 09:50:19 +0900 +Subject: scsi: mpi3mr: Fix missing mrioc->evtack_cmds initialization + +From: Shin'ichiro Kawasaki + +commit e39ea831ebad4ab15c4748cb62a397a8abcca36e upstream. + +Commit c1af985d27da ("scsi: mpi3mr: Add Event acknowledgment logic") +introduced an array mrioc->evtack_cmds but initialization of the array +elements was missed. They are just zero cleared. The function +mpi3mr_complete_evt_ack() refers host_tag field of the elements. Due to the +zero value of the host_tag field, the function calls clear_bit() for +mrico->evtack_cmds_bitmap with wrong bit index. This results in memory +access to invalid address and "BUG: KASAN: use-after-free". This BUG was +observed at eHBA-9600 firmware update to version 8.3.1.0. To fix it, add +the missing initialization of mrioc->evtack_cmds. + +Link: https://lore.kernel.org/r/20230214005019.1897251-5-shinichiro.kawasaki@wdc.com +Cc: stable@vger.kernel.org +Fixes: c1af985d27da ("scsi: mpi3mr: Add Event acknowledgment logic") +Signed-off-by: Shin'ichiro Kawasaki +Reviewed-by: Damien Le Moal +Acked-by: Sathya Prakash Veerichetty +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/mpi3mr/mpi3mr_os.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/scsi/mpi3mr/mpi3mr_os.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_os.c +@@ -4952,6 +4952,10 @@ mpi3mr_probe(struct pci_dev *pdev, const + mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], + MPI3MR_HOSTTAG_DEVRMCMD_MIN + i); + ++ for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) ++ mpi3mr_init_drv_cmd(&mrioc->evtack_cmds[i], ++ MPI3MR_HOSTTAG_EVTACKCMD_MIN + i); ++ + if (pdev->revision) + mrioc->enable_segqueue = true; + diff --git a/queue-6.1/scsi-mpi3mr-remove-unnecessary-memcpy-to-alltgt_info-dmi.patch b/queue-6.1/scsi-mpi3mr-remove-unnecessary-memcpy-to-alltgt_info-dmi.patch new file mode 100644 index 00000000000..a6b23eea7d1 --- /dev/null +++ b/queue-6.1/scsi-mpi3mr-remove-unnecessary-memcpy-to-alltgt_info-dmi.patch @@ -0,0 +1,71 @@ +From eeb270aee3e085411399f129fc14fa04bd6d83cf Mon Sep 17 00:00:00 2001 +From: Shin'ichiro Kawasaki +Date: Tue, 14 Feb 2023 09:50:17 +0900 +Subject: scsi: mpi3mr: Remove unnecessary memcpy() to alltgt_info->dmi + +From: Shin'ichiro Kawasaki + +commit eeb270aee3e085411399f129fc14fa04bd6d83cf upstream. + +In the function mpi3mr_get_all_tgt_info(), devmap_info points to +alltgt_info->dmi then there is no need to memcpy() data from devmap_info to +alltgt_info->dmi. Remove the unnecessary memcpy(). This also allows to +remove the local variable 'rval' and the goto label 'out'. + +Link: https://lore.kernel.org/r/20230214005019.1897251-3-shinichiro.kawasaki@wdc.com +Cc: stable@vger.kernel.org +Fixes: f5e6d5a34376 ("scsi: mpi3mr: Add support for driver commands") +Signed-off-by: Shin'ichiro Kawasaki +Acked-by: Sathya Prakash Veerichetty +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/mpi3mr/mpi3mr_app.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c +index 72054e3a26cb..bff637702397 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_app.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_app.c +@@ -293,7 +293,6 @@ static long mpi3mr_bsg_pel_enable(struct mpi3mr_ioc *mrioc, + static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + struct bsg_job *job) + { +- long rval = -EINVAL; + u16 num_devices = 0, i = 0, size; + unsigned long flags; + struct mpi3mr_tgt_dev *tgtdev; +@@ -304,7 +303,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + if (job->request_payload.payload_len < sizeof(u32)) { + dprint_bsg_err(mrioc, "%s: invalid size argument\n", + __func__); +- return rval; ++ return -EINVAL; + } + + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); +@@ -350,20 +349,12 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + sizeof(*devmap_info); + usr_entrylen *= sizeof(*devmap_info); + min_entrylen = min(usr_entrylen, kern_entrylen); +- if (min_entrylen && (!memcpy(&alltgt_info->dmi, devmap_info, min_entrylen))) { +- dprint_bsg_err(mrioc, "%s:%d: device map info copy failed\n", +- __func__, __LINE__); +- rval = -EFAULT; +- goto out; +- } + + sg_copy_from_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + alltgt_info, (min_entrylen + sizeof(u64))); +- rval = 0; +-out: + kfree(alltgt_info); +- return rval; ++ return 0; + } + /** + * mpi3mr_get_change_count - Get topology change count +-- +2.39.2 + diff --git a/queue-6.1/series b/queue-6.1/series index 3ff52428dbf..539e1e010f1 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -666,3 +666,19 @@ io_uring-add-reschedule-point-to-handle_tw_list.patch io_uring-rsrc-disallow-multi-source-reg-buffers.patch io_uring-remove-msg_nosignal-from-recvmsg.patch io_uring-fix-fget-leak-when-fs-don-t-support-nowait-buffered-read.patch +s390-extmem-return-correct-segment-type-in-__segment_load.patch +s390-discard-.interp-section.patch +s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch +s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch +kvm-s390-disable-migration-mode-when-dirty-tracking-is-disabled.patch +cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch +cifs-fix-uninitialized-memory-reads-for-oparms.mode.patch +cifs-fix-mount-on-old-smb-servers.patch +cifs-introduce-cifs_io_parms-in-smb2_async_writev.patch +cifs-split-out-smb3_use_rdma_offload-helper.patch +cifs-don-t-try-to-use-rdma-offload-on-encrypted-connections.patch +cifs-check-the-lease-context-if-we-actually-got-a-lease.patch +cifs-return-a-single-use-cfid-if-we-did-not-get-a-lease.patch +scsi-mpi3mr-fix-missing-mrioc-evtack_cmds-initialization.patch +scsi-mpi3mr-fix-issues-in-mpi3mr_get_all_tgt_info.patch +scsi-mpi3mr-remove-unnecessary-memcpy-to-alltgt_info-dmi.patch