diff options
| author | Jinke Han <jinkehan@didiglobal.com> | 2026-09-08 15:37:42 +0800 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2026-09-17 09:48:42 +0200 |
| commit | a5f7a5bb3b7f28ba7e4fa246775b29a0e5537255 (patch) | |
| tree | 73fef824f9a846cf935869d0dbc5070ef6e2f741 /sound/soc/sof/ipc4-priv.h | |
| download | linux-stable-a5f7a5bb3b7f28ba7e4fa246775b29a0e5537255.tar.gz linux-stable-a5f7a5bb3b7f28ba7e4fa246775b29a0e5537255.zip | |
x86/kprobes: Fix crash when probing CS CALL instructionsgrafted
When using eBPF to probe CS CALL instructions within a function,
a crash can be triggered.
The eBPF tool probes offset 257 of the __hrtimer_run_queues()
function:
<__hrtimer_run_queues+249>: nopl 0x0(%rax,%rax,1)
<__hrtimer_run_queues+254>: mov %r14,%rdi
<__hrtimer_run_queues+257>: cs call <__x86_indirect_thunk_r12>
<__hrtimer_run_queues+263>: mov %eax,%r12d
<__hrtimer_run_queues+266>: xchg %ax,%ax
<__hrtimer_run_queues+268>: mov %r13,%rdi
Which triggers this crash:
BUG: unable to handle page fault for address: 00000000000f41c9
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 0 P4D 0
Oops: 0002 [#1] SMP NOPTI
CPU: 1 PID: 0 Comm: swapper/1 Kdump: loaded Tainted: P
RIP: 0010:__hrtimer_run_queues+0x106/0x230
Note that __hrtimer_run_queues+0x106 is __hrtimer_run_queues+262, which is
at the 6th byte of the above CS CALL instruction. Since the CS CALL
instruction occupies 6 bytes, the exception occurred in the middle of that
call instruction.
The root cause is that when using eBPF tools to probe in the middle of a
function, a kprobe with INT3 is used as the underlying implementation.
During single-step emulation of the original CALL instruction,
int3_emulate_call() assumes that the probed CALL instruction is 5 bytes
long. However, the actual CS-prefixed CALL instruction occupies 6 bytes,
so it constructs an incorrect exception return address. When the CPU
returns from the kprobe handler, the next instruction to be executed is at
the address of the last byte of that CS CALL instruction. Coincidentally,
starting from that address, the CPU fetches and decodes a completely
different instruction, which ultimately triggers a kernel crash.
Fix the issue by using the actual instruction length obtained from
the instruction decoder when constructing the exception return
address, rather than relying on the hardcoded CALL_INSN_SIZE macro.
[ mingo: Refined the changelog ]
Fixes: 6256e668b7af ("x86/kprobes: Use int3 instead of debug trap for single-step")
Suggested-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Jinke Han <jinkehan@didiglobal.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: Yafang Shao <laoar.shao@gmail.com>
Acked-by: Borislav Petkov <bp@alien8.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://patch.msgid.link/20260908073742.GA10517@didi-ThinkCentre-M920t-N000
Diffstat (limited to 'sound/soc/sof/ipc4-priv.h')
| -rw-r--r-- | sound/soc/sof/ipc4-priv.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h new file mode 100644 index 000000000..a8cdf9bc7 --- /dev/null +++ b/sound/soc/sof/ipc4-priv.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef __SOUND_SOC_SOF_IPC4_PRIV_H +#define __SOUND_SOC_SOF_IPC4_PRIV_H + +#include <linux/idr.h> +#include <sound/sof/ext_manifest4.h> +#include <sound/sof/ipc4/header.h> +#include "sof-priv.h" + +/* The DSP window indices are fixed */ +#define SOF_IPC4_INBOX_WINDOW_IDX 0 +#define SOF_IPC4_OUTBOX_WINDOW_IDX 1 +#define SOF_IPC4_DEBUG_WINDOW_IDX 2 + +enum sof_ipc4_mtrace_type { + SOF_IPC4_MTRACE_NOT_AVAILABLE = 0, + SOF_IPC4_MTRACE_INTEL_CAVS_1_5, + SOF_IPC4_MTRACE_INTEL_CAVS_1_8, + SOF_IPC4_MTRACE_INTEL_CAVS_2, +}; + +/** + * struct sof_ipc4_fw_module - IPC4 module info + * @sof_man4_module: Module info + * @fw_mod_cfg: Pointer to the module config start of the module + * @m_ida: Module instance identifier + * @private: Module private data + */ +struct sof_ipc4_fw_module { + struct sof_man4_module man4_module_entry; + const struct sof_man4_module_config *fw_mod_cfg; + struct ida m_ida; + void *private; +}; + +/** + * struct sof_ipc4_fw_library - IPC4 library information + * @sof_fw: SOF Firmware of the library + * @id: Library ID. 0 is reserved for basefw, external libraries must have unique + * ID number between 1 and (sof_ipc4_fw_data.max_libs_count - 1) + * Note: sof_ipc4_fw_data.max_libs_count == 1 implies that external libraries + * are not supported + * @num_modules : Number of FW modules in the library + * @modules: Array of FW modules + */ +struct sof_ipc4_fw_library { + struct sof_firmware sof_fw; + const char *name; + u32 id; + int num_modules; + struct sof_ipc4_fw_module *modules; +}; + +/** + * struct sof_ipc4_fw_data - IPC4-specific data + * @manifest_fw_hdr_offset: FW header offset in the manifest + * @fw_lib_xa: XArray for firmware libraries, including basefw (ID = 0) + * Used to store the FW libraries and to manage the unique IDs of the + * libraries. + * @nhlt: NHLT table either from the BIOS or the topology manifest + * @mtrace_type: mtrace type supported on the booted platform + * @mtrace_log_bytes: log bytes as reported by the firmware via fw_config reply + * @num_playback_streams: max number of playback DMAs, needed for CHAIN_DMA offset + * @num_capture_streams: max number of capture DMAs + * @max_num_pipelines: max number of pipelines + * @max_libs_count: Maximum number of libraries support by the FW including the + * base firmware + * @fw_context_save: Firmware supports full context save and restore + * @libraries_restored: The libraries have been retained during firmware boot + * + * @load_library: Callback function for platform dependent library loading + * @pipeline_state_mutex: Mutex to protect pipeline triggers, ref counts, states and deletion + */ +struct sof_ipc4_fw_data { + u32 manifest_fw_hdr_offset; + struct xarray fw_lib_xa; + void *nhlt; + enum sof_ipc4_mtrace_type mtrace_type; + u32 mtrace_log_bytes; + int num_playback_streams; + int num_capture_streams; + int max_num_pipelines; + u32 max_libs_count; + bool fw_context_save; + bool libraries_restored; + + int (*load_library)(struct snd_sof_dev *sdev, + struct sof_ipc4_fw_library *fw_lib, bool reload); + void (*intel_configure_mic_privacy)(struct snd_sof_dev *sdev, + struct sof_ipc4_intel_mic_privacy_cap *caps); + struct mutex pipeline_state_mutex; /* protect pipeline triggers, ref counts and states */ +}; + +extern const struct sof_ipc_fw_loader_ops ipc4_loader_ops; +extern const struct sof_ipc_tplg_ops ipc4_tplg_ops; +extern const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops; +extern const struct sof_ipc_pcm_ops ipc4_pcm_ops; +extern const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops; + +int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 instance_id, u32 state); +int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core); + +int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev); +int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev); +int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev); +struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, + const guid_t *uuid); + +struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev, + u32 module_id, int instance_id); + +struct sof_ipc4_base_module_cfg; +void sof_ipc4_update_cpc_from_manifest(struct snd_sof_dev *sdev, + struct sof_ipc4_fw_module *fw_module, + struct sof_ipc4_base_module_cfg *basecfg); + +size_t sof_ipc4_find_debug_slot_offset_by_type(struct snd_sof_dev *sdev, + u32 slot_type); + +void sof_ipc4_mic_privacy_state_change(struct snd_sof_dev *sdev, bool state); + +enum sof_ipc4_pipeline_state; +const char *sof_ipc4_pipeline_state_str(enum sof_ipc4_pipeline_state state); + +#endif |
