From: Paul Gortmaker <paul.gortmaker(a)windriver.com>
This is a bit long, but I've never touched this code and all I can do is
compile test it. So the below basically represents a capture of my
thought process in fixing this for the v5.15.y-stable branch.
I am hoping the folks who normally work with this code can double check
that I didn't get off-track somewhere...
CVE-2023-38431 points at commit 368ba06881c3 ("ksmbd: check the
validation of pdu_size in ksmbd_conn_handler_loop") as the fix:
https://nvd.nist.gov/vuln/detail/CVE-2023-38431
For convenience, here is a link to the fix:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/f…
It was added in v6.4
git describe --contains 368ba06881c3
v6.4-rc6~2^2~1
...and backported to several stable releases. But just not v5.15.
Why not v5.15? If we look at the code the fix patches with "git blame"
we get commit 0626e6641f6b4 ("cifsd: add server handler for central
processing and tranport layers")
$git describe --contains 0626e6641f6b4
v5.15-rc1~183^2~94
So that would have been the commit the "Fixes:" line would have pointed
at if it had one.
Applying the fix to v5.15 reveals two problems. The 1st is a trivial
file rename (fs/smb/server/connection.c --> fs/ksmbd/connection.c for
v5.15) and then the commit *applies*. The 2nd problem is only revealed
at compile time...
The compile fails because the v5.15 baseline does not have smb2_get_msg().
Where does that come from?
commit cb4517201b8acdb5fd5314494aaf86c267f22345
Author: Namjae Jeon <linkinjeon(a)kernel.org>
Date: Wed Nov 3 08:08:44 2021 +0900
ksmbd: remove smb2_buf_length in smb2_hdr
git describe --contains cb4517201b8a
v5.16-rc1~21^2~6
So now we see why v5.15 didn't get a linux-stable backport by default.
In cb4517201b8a we see:
+static inline void *smb2_get_msg(void *buf)
+{
+ return buf + 4;
+}
However we can't just take that context free of the rest of the commit,
and then glue it into v5.15. The whole reason the function exists is
because a length field of 4 was removed from the front of a struct.
If we look at the typical changes the struct change caused, we see:
- struct smb2_hdr *rcv_hdr2 = work->request_buf;
+ struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
If we manually inline that, we obviously get:
- struct smb2_hdr *rcv_hdr2 = work->request_buf;
+ struct smb2_hdr *rcv_hdr2 = work->request_buf + 4;
Now consider the lines added in the fix which is post struct reduction:
+#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
+ if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+ }
...and if we inline/expand everything, we get:
+ if (((struct smb2_hdr *)(conn->request_buf + 4))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < (sizeof(struct smb2_hdr) + 4))
+ break;
+ }
And so, by extension the v5.15 code, which is *pre* struct reduction, would
simply not have the "+4" and hence be:
+ if (((struct smb2_hdr *)(conn->request_buf))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < (sizeof(struct smb2_hdr)))
+ break;
+ }
If we then put the macro back (without the 4), the v5.15 version would be:
+#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr))
+ if (((struct smb2_hdr *)(conn->request_buf))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+ }
And so that is what I convinced myself is right to put in the backport.
If you read/reviewed this far - thanks!
Paul.
---
Namjae Jeon (1):
ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop
fs/ksmbd/connection.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--
2.40.0
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 41a506ef71eb38d94fe133f565c87c3e06ccc072
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2023080733-wife-elope-de1b@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
41a506ef71eb ("powerpc/ftrace: Create a dummy stackframe to fix stack unwind")
a5f04d1f2724 ("powerpc/ftrace: Regroup PPC64 specific operations in ftrace_mprofile.S")
228216716cb5 ("powerpc/ftrace: Refactor ftrace_{regs_}caller")
9bdb2eec3dde ("powerpc/ftrace: Don't use lmw/stmw in ftrace_regs_caller()")
76b372814b08 ("powerpc/ftrace: Style cleanup in ftrace_mprofile.S")
fc75f8733798 ("powerpc/ftrace: Have arch_ftrace_get_regs() return NULL unless FL_SAVE_REGS is set")
34d8dac807f0 ("powerpc/ftrace: Also save r1 in ftrace_caller()")
4ee83a2cfbc4 ("powerpc/ftrace: Remove ftrace_32.S")
41315494beed ("powerpc/ftrace: Prepare ftrace_64_mprofile.S for reuse by PPC32")
830213786c49 ("powerpc/ftrace: directly call of function graph tracer by ftrace caller")
0c81ed5ed438 ("powerpc/ftrace: Refactor ftrace_{en/dis}able_ftrace_graph_caller")
40b035efe288 ("powerpc/ftrace: Implement CONFIG_DYNAMIC_FTRACE_WITH_ARGS")
c75388a8ceff ("powerpc/ftrace: Prepare PPC64's ftrace_caller() for CONFIG_DYNAMIC_FTRACE_WITH_ARGS")
d95bf254be5f ("powerpc/ftrace: Prepare PPC32's ftrace_caller() for CONFIG_DYNAMIC_FTRACE_WITH_ARGS")
7bdb478c1d15 ("powerpc/ftrace: Simplify PPC32's return_to_handler()")
7875bc9b07cd ("powerpc/ftrace: Don't save again LR in ftrace_regs_caller() on PPC32")
c545b9f040f3 ("powerpc/inst: Define ppc_inst_t")
aebd1fb45c62 ("powerpc: flexible GPR range save/restore macros")
7dfbfb87c243 ("powerpc/ftrace: Activate HAVE_DYNAMIC_FTRACE_WITH_REGS on PPC32")
c93d4f6ecf4b ("powerpc/ftrace: Add module_trampoline_target() for PPC32")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 41a506ef71eb38d94fe133f565c87c3e06ccc072 Mon Sep 17 00:00:00 2001
From: Naveen N Rao <naveen(a)kernel.org>
Date: Wed, 21 Jun 2023 10:43:49 +0530
Subject: [PATCH] powerpc/ftrace: Create a dummy stackframe to fix stack unwind
With ppc64 -mprofile-kernel and ppc32 -pg, profiling instructions to
call into ftrace are emitted right at function entry. The instruction
sequence used is minimal to reduce overhead. Crucially, a stackframe is
not created for the function being traced. This breaks stack unwinding
since the function being traced does not have a stackframe for itself.
As such, it never shows up in the backtrace:
/sys/kernel/debug/tracing # echo 1 > /proc/sys/kernel/stack_tracer_enabled
/sys/kernel/debug/tracing # cat stack_trace
Depth Size Location (17 entries)
----- ---- --------
0) 4144 32 ftrace_call+0x4/0x44
1) 4112 432 get_page_from_freelist+0x26c/0x1ad0
2) 3680 496 __alloc_pages+0x290/0x1280
3) 3184 336 __folio_alloc+0x34/0x90
4) 2848 176 vma_alloc_folio+0xd8/0x540
5) 2672 272 __handle_mm_fault+0x700/0x1cc0
6) 2400 208 handle_mm_fault+0xf0/0x3f0
7) 2192 80 ___do_page_fault+0x3e4/0xbe0
8) 2112 160 do_page_fault+0x30/0xc0
9) 1952 256 data_access_common_virt+0x210/0x220
10) 1696 400 0xc00000000f16b100
11) 1296 384 load_elf_binary+0x804/0x1b80
12) 912 208 bprm_execve+0x2d8/0x7e0
13) 704 64 do_execveat_common+0x1d0/0x2f0
14) 640 160 sys_execve+0x54/0x70
15) 480 64 system_call_exception+0x138/0x350
16) 416 416 system_call_common+0x160/0x2c4
Fix this by having ftrace create a dummy stackframe for the function
being traced. With this, backtraces now capture the function being
traced:
/sys/kernel/debug/tracing # cat stack_trace
Depth Size Location (17 entries)
----- ---- --------
0) 3888 32 _raw_spin_trylock+0x8/0x70
1) 3856 576 get_page_from_freelist+0x26c/0x1ad0
2) 3280 64 __alloc_pages+0x290/0x1280
3) 3216 336 __folio_alloc+0x34/0x90
4) 2880 176 vma_alloc_folio+0xd8/0x540
5) 2704 416 __handle_mm_fault+0x700/0x1cc0
6) 2288 96 handle_mm_fault+0xf0/0x3f0
7) 2192 48 ___do_page_fault+0x3e4/0xbe0
8) 2144 192 do_page_fault+0x30/0xc0
9) 1952 608 data_access_common_virt+0x210/0x220
10) 1344 16 0xc0000000334bbb50
11) 1328 416 load_elf_binary+0x804/0x1b80
12) 912 64 bprm_execve+0x2d8/0x7e0
13) 848 176 do_execveat_common+0x1d0/0x2f0
14) 672 192 sys_execve+0x54/0x70
15) 480 64 system_call_exception+0x138/0x350
16) 416 416 system_call_common+0x160/0x2c4
This results in two additional stores in the ftrace entry code, but
produces reliable backtraces.
Fixes: 153086644fd1 ("powerpc/ftrace: Add support for -mprofile-kernel ftrace ABI")
Cc: stable(a)vger.kernel.org
Signed-off-by: Naveen N Rao <naveen(a)kernel.org>
Signed-off-by: Michael Ellerman <mpe(a)ellerman.id.au>
Link: https://msgid.link/20230621051349.759567-1-naveen@kernel.org
diff --git a/arch/powerpc/kernel/trace/ftrace_mprofile.S b/arch/powerpc/kernel/trace/ftrace_mprofile.S
index ffb1db386849..1f7d86de1538 100644
--- a/arch/powerpc/kernel/trace/ftrace_mprofile.S
+++ b/arch/powerpc/kernel/trace/ftrace_mprofile.S
@@ -33,6 +33,9 @@
* and then arrange for the ftrace function to be called.
*/
.macro ftrace_regs_entry allregs
+ /* Create a minimal stack frame for representing B */
+ PPC_STLU r1, -STACK_FRAME_MIN_SIZE(r1)
+
/* Create our stack frame + pt_regs */
PPC_STLU r1,-SWITCH_FRAME_SIZE(r1)
@@ -42,7 +45,7 @@
#ifdef CONFIG_PPC64
/* Save the original return address in A's stack frame */
- std r0, LRSAVE+SWITCH_FRAME_SIZE(r1)
+ std r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1)
/* Ok to continue? */
lbz r3, PACA_FTRACE_ENABLED(r13)
cmpdi r3, 0
@@ -77,6 +80,8 @@
mflr r7
/* Save it as pt_regs->nip */
PPC_STL r7, _NIP(r1)
+ /* Also save it in B's stackframe header for proper unwind */
+ PPC_STL r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
/* Save the read LR in pt_regs->link */
PPC_STL r0, _LINK(r1)
@@ -142,7 +147,7 @@
#endif
/* Pop our stack frame */
- addi r1, r1, SWITCH_FRAME_SIZE
+ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
#ifdef CONFIG_LIVEPATCH_64
/* Based on the cmpd above, if the NIP was altered handle livepatch */