From: Greg Kroah-Hartman Date: Tue, 20 Feb 2024 15:37:17 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v4.19.307~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4a856046149922efd3be2af78c32c349bf12a979;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: rdma-irdma-ensure-iwarp-qp-queue-memory-is-os-paged-aligned.patch smb-client-fix-parsing-of-smb3.1.1-posix-create-context.patch smb-client-fix-potential-oobs-in-smb2_parse_contexts.patch --- diff --git a/queue-6.1/rdma-irdma-ensure-iwarp-qp-queue-memory-is-os-paged-aligned.patch b/queue-6.1/rdma-irdma-ensure-iwarp-qp-queue-memory-is-os-paged-aligned.patch new file mode 100644 index 00000000000..7332baccc0a --- /dev/null +++ b/queue-6.1/rdma-irdma-ensure-iwarp-qp-queue-memory-is-os-paged-aligned.patch @@ -0,0 +1,42 @@ +From 0a5ec366de7e94192669ba08de6ed336607fd282 Mon Sep 17 00:00:00 2001 +From: Mike Marciniszyn +Date: Wed, 29 Nov 2023 14:21:42 -0600 +Subject: RDMA/irdma: Ensure iWarp QP queue memory is OS paged aligned + +From: Mike Marciniszyn + +commit 0a5ec366de7e94192669ba08de6ed336607fd282 upstream. + +The SQ is shared for between kernel and used by storing the kernel page +pointer and passing that to a kmap_atomic(). + +This then requires that the alignment is PAGE_SIZE aligned. + +Fix by adding an iWarp specific alignment check. + +Fixes: e965ef0e7b2c ("RDMA/irdma: Split QP handler into irdma_reg_user_mr_type_qp") +Link: https://lore.kernel.org/r/20231129202143.1434-3-shiraz.saleem@intel.com +Signed-off-by: Mike Marciniszyn +Signed-off-by: Shiraz Saleem +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/hw/irdma/verbs.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2845,6 +2845,13 @@ static struct ib_mr *irdma_reg_user_mr(s + + switch (req.reg_type) { + case IRDMA_MEMREG_TYPE_QP: ++ /* iWarp: Catch page not starting on OS page boundary */ ++ if (!rdma_protocol_roce(&iwdev->ibdev, 1) && ++ ib_umem_offset(iwmr->region)) { ++ err = -EINVAL; ++ goto error; ++ } ++ + total = req.sq_pages + req.rq_pages + shadow_pgcnt; + if (total > iwmr->page_cnt) { + err = -EINVAL; diff --git a/queue-6.1/series b/queue-6.1/series index 1d410f277a9..83d677ef53b 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -187,3 +187,6 @@ parisc-fix-random-data-corruption-from-exception-handler.patch nfsd-fix-release_lockowner.patch nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch hrtimer-ignore-slack-time-for-rt-tasks-in-schedule_hrtimeout_range.patch +rdma-irdma-ensure-iwarp-qp-queue-memory-is-os-paged-aligned.patch +smb-client-fix-potential-oobs-in-smb2_parse_contexts.patch +smb-client-fix-parsing-of-smb3.1.1-posix-create-context.patch diff --git a/queue-6.1/smb-client-fix-parsing-of-smb3.1.1-posix-create-context.patch b/queue-6.1/smb-client-fix-parsing-of-smb3.1.1-posix-create-context.patch new file mode 100644 index 00000000000..58654e206f6 --- /dev/null +++ b/queue-6.1/smb-client-fix-parsing-of-smb3.1.1-posix-create-context.patch @@ -0,0 +1,36 @@ +From 76025cc2285d9ede3d717fe4305d66f8be2d9346 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Fri, 19 Jan 2024 01:08:26 -0300 +Subject: smb: client: fix parsing of SMB3.1.1 POSIX create context + +From: Paulo Alcantara + +commit 76025cc2285d9ede3d717fe4305d66f8be2d9346 upstream. + +The data offset for the SMB3.1.1 POSIX create context will always be +8-byte aligned so having the check 'noff + nlen >= doff' in +smb2_parse_contexts() is wrong as it will lead to -EINVAL because noff ++ nlen == doff. + +Fix the sanity check to correctly handle aligned create context data. + +Fixes: af1689a9b770 ("smb: client: fix potential OOBs in smb2_parse_contexts()") +Signed-off-by: Paulo Alcantara +Signed-off-by: Steve French +Signed-off-by: Guruswamy Basavaiah +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -2184,7 +2184,7 @@ int smb2_parse_contexts(struct TCP_Serve + + noff = le16_to_cpu(cc->NameOffset); + nlen = le16_to_cpu(cc->NameLength); +- if (noff + nlen >= doff) ++ if (noff + nlen > doff) + return -EINVAL; + + name = (char *)cc + noff; diff --git a/queue-6.1/smb-client-fix-potential-oobs-in-smb2_parse_contexts.patch b/queue-6.1/smb-client-fix-potential-oobs-in-smb2_parse_contexts.patch new file mode 100644 index 00000000000..cfece8264ae --- /dev/null +++ b/queue-6.1/smb-client-fix-potential-oobs-in-smb2_parse_contexts.patch @@ -0,0 +1,246 @@ +From af1689a9b7701d9907dfc84d2a4b57c4bc907144 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Mon, 11 Dec 2023 10:26:41 -0300 +Subject: smb: client: fix potential OOBs in smb2_parse_contexts() + +From: Paulo Alcantara + +commit af1689a9b7701d9907dfc84d2a4b57c4bc907144 upstream. + +Validate offsets and lengths before dereferencing create contexts in +smb2_parse_contexts(). + +This fixes following oops when accessing invalid create contexts from +server: + + BUG: unable to handle page fault for address: ffff8881178d8cc3 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 4a01067 P4D 4a01067 PUD 0 + Oops: 0000 [#1] PREEMPT SMP NOPTI + CPU: 3 PID: 1736 Comm: mount.cifs Not tainted 6.7.0-rc4 #1 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS + rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 + RIP: 0010:smb2_parse_contexts+0xa0/0x3a0 [cifs] + Code: f8 10 75 13 48 b8 93 ad 25 50 9c b4 11 e7 49 39 06 0f 84 d2 00 + 00 00 8b 45 00 85 c0 74 61 41 29 c5 48 01 c5 41 83 fd 0f 76 55 <0f> b7 + 7d 04 0f b7 45 06 4c 8d 74 3d 00 66 83 f8 04 75 bc ba 04 00 + RSP: 0018:ffffc900007939e0 EFLAGS: 00010216 + RAX: ffffc90000793c78 RBX: ffff8880180cc000 RCX: ffffc90000793c90 + RDX: ffffc90000793cc0 RSI: ffff8880178d8cc0 RDI: ffff8880180cc000 + RBP: ffff8881178d8cbf R08: ffffc90000793c22 R09: 0000000000000000 + R10: ffff8880180cc000 R11: 0000000000000024 R12: 0000000000000000 + R13: 0000000000000020 R14: 0000000000000000 R15: ffffc90000793c22 + FS: 00007f873753cbc0(0000) GS:ffff88806bc00000(0000) + knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: ffff8881178d8cc3 CR3: 00000000181ca000 CR4: 0000000000750ef0 + PKRU: 55555554 + Call Trace: + + ? __die+0x23/0x70 + ? page_fault_oops+0x181/0x480 + ? search_module_extables+0x19/0x60 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? exc_page_fault+0x1b6/0x1c0 + ? asm_exc_page_fault+0x26/0x30 + ? smb2_parse_contexts+0xa0/0x3a0 [cifs] + SMB2_open+0x38d/0x5f0 [cifs] + ? smb2_is_path_accessible+0x138/0x260 [cifs] + smb2_is_path_accessible+0x138/0x260 [cifs] + cifs_is_path_remote+0x8d/0x230 [cifs] + cifs_mount+0x7e/0x350 [cifs] + cifs_smb3_do_mount+0x128/0x780 [cifs] + smb3_get_tree+0xd9/0x290 [cifs] + vfs_get_tree+0x2c/0x100 + ? capable+0x37/0x70 + path_mount+0x2d7/0xb80 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? _raw_spin_unlock_irqrestore+0x44/0x60 + __x64_sys_mount+0x11a/0x150 + do_syscall_64+0x47/0xf0 + entry_SYSCALL_64_after_hwframe+0x6f/0x77 + RIP: 0033:0x7f8737657b1e + +Reported-by: Robert Morris +Cc: stable@vger.kernel.org +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +[Guru: Modified the patch to be applicable to the cached_dir.c file.] +Signed-off-by: Guruswamy Basavaiah +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/cached_dir.c | 8 ++- + fs/smb/client/smb2pdu.c | 91 +++++++++++++++++++++++++++------------------ + fs/smb/client/smb2proto.h | 12 +++-- + 3 files changed, 67 insertions(+), 44 deletions(-) + +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -268,10 +268,12 @@ 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, ++ rc = smb2_parse_contexts(server, rsp_iov, + &oparms.fid->epoch, +- oparms.fid->lease_key, &oplock, +- NULL, NULL); ++ oparms.fid->lease_key, ++ &oplock, NULL, NULL); ++ if (rc) ++ goto oshr_free; + if (!(oplock & SMB2_LEASE_READ_CACHING_HE)) + goto oshr_free; + qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -2145,17 +2145,18 @@ parse_posix_ctxt(struct create_context * + posix->nlink, posix->mode, posix->reparse_tag); + } + +-void +-smb2_parse_contexts(struct TCP_Server_Info *server, +- struct smb2_create_rsp *rsp, +- unsigned int *epoch, char *lease_key, __u8 *oplock, +- struct smb2_file_all_info *buf, +- struct create_posix_rsp *posix) ++int smb2_parse_contexts(struct TCP_Server_Info *server, ++ struct kvec *rsp_iov, ++ unsigned int *epoch, ++ char *lease_key, __u8 *oplock, ++ struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix) + { +- char *data_offset; ++ struct smb2_create_rsp *rsp = rsp_iov->iov_base; + struct create_context *cc; +- unsigned int next; +- unsigned int remaining; ++ size_t rem, off, len; ++ size_t doff, dlen; ++ size_t noff, nlen; + char *name; + static const char smb3_create_tag_posix[] = { + 0x93, 0xAD, 0x25, 0x50, 0x9C, +@@ -2164,45 +2165,63 @@ smb2_parse_contexts(struct TCP_Server_In + }; + + *oplock = 0; +- data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); +- remaining = le32_to_cpu(rsp->CreateContextsLength); +- cc = (struct create_context *)data_offset; ++ ++ off = le32_to_cpu(rsp->CreateContextsOffset); ++ rem = le32_to_cpu(rsp->CreateContextsLength); ++ if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len) ++ return -EINVAL; ++ cc = (struct create_context *)((u8 *)rsp + off); + + /* Initialize inode number to 0 in case no valid data in qfid context */ + if (buf) + buf->IndexNumber = 0; + +- while (remaining >= sizeof(struct create_context)) { +- name = le16_to_cpu(cc->NameOffset) + (char *)cc; +- if (le16_to_cpu(cc->NameLength) == 4 && +- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) +- *oplock = server->ops->parse_lease_buf(cc, epoch, +- lease_key); +- else if (buf && (le16_to_cpu(cc->NameLength) == 4) && +- strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) +- parse_query_id_ctxt(cc, buf); +- else if ((le16_to_cpu(cc->NameLength) == 16)) { +- if (posix && +- memcmp(name, smb3_create_tag_posix, 16) == 0) ++ while (rem >= sizeof(*cc)) { ++ doff = le16_to_cpu(cc->DataOffset); ++ dlen = le32_to_cpu(cc->DataLength); ++ if (check_add_overflow(doff, dlen, &len) || len > rem) ++ return -EINVAL; ++ ++ noff = le16_to_cpu(cc->NameOffset); ++ nlen = le16_to_cpu(cc->NameLength); ++ if (noff + nlen >= doff) ++ return -EINVAL; ++ ++ name = (char *)cc + noff; ++ switch (nlen) { ++ case 4: ++ if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) { ++ *oplock = server->ops->parse_lease_buf(cc, epoch, ++ lease_key); ++ } else if (buf && ++ !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) { ++ parse_query_id_ctxt(cc, buf); ++ } ++ break; ++ case 16: ++ if (posix && !memcmp(name, smb3_create_tag_posix, 16)) + parse_posix_ctxt(cc, buf, posix); ++ break; ++ default: ++ cifs_dbg(FYI, "%s: unhandled context (nlen=%zu dlen=%zu)\n", ++ __func__, nlen, dlen); ++ if (IS_ENABLED(CONFIG_CIFS_DEBUG2)) ++ cifs_dump_mem("context data: ", cc, dlen); ++ break; + } +- /* else { +- cifs_dbg(FYI, "Context not matched with len %d\n", +- le16_to_cpu(cc->NameLength)); +- cifs_dump_mem("Cctxt name: ", name, 4); +- } */ + +- next = le32_to_cpu(cc->Next); +- if (!next) ++ off = le32_to_cpu(cc->Next); ++ if (!off) + break; +- remaining -= next; +- cc = (struct create_context *)((char *)cc + next); ++ if (check_sub_overflow(rem, off, &rem)) ++ return -EINVAL; ++ cc = (struct create_context *)((u8 *)cc + off); + } + + if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) + *oplock = rsp->OplockLevel; + +- return; ++ return 0; + } + + static int +@@ -3082,8 +3101,8 @@ SMB2_open(const unsigned int xid, struct + } + + +- smb2_parse_contexts(server, rsp, &oparms->fid->epoch, +- oparms->fid->lease_key, oplock, buf, posix); ++ rc = smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch, ++ oparms->fid->lease_key, oplock, buf, posix); + creat_exit: + SMB2_open_free(&rqst); + free_rsp_buf(resp_buftype, rsp); +--- a/fs/smb/client/smb2proto.h ++++ b/fs/smb/client/smb2proto.h +@@ -249,11 +249,13 @@ extern int smb3_validate_negotiate(const + + extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, + enum securityEnum); +-extern void smb2_parse_contexts(struct TCP_Server_Info *server, +- struct smb2_create_rsp *rsp, +- unsigned int *epoch, char *lease_key, +- __u8 *oplock, struct smb2_file_all_info *buf, +- struct create_posix_rsp *posix); ++int smb2_parse_contexts(struct TCP_Server_Info *server, ++ struct kvec *rsp_iov, ++ unsigned int *epoch, ++ char *lease_key, __u8 *oplock, ++ struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix); ++ + extern int smb3_encryption_required(const struct cifs_tcon *tcon); + extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, + struct kvec *iov, unsigned int min_buf_size);