summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/disasm.h
diff options
context:
space:
mode:
authorMuhammad Bilal <meatuni001@gmail.com>2026-07-28 17:54:55 +0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-01 12:15:16 +0200
commitff917923f4fb9c83717ba135ee47d7e4c1567bb7 (patch)
treec38fd8fcf58e1937b17fdbc6518b6f8b797fc15a /tools/perf/util/disasm.h
downloadlinux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.tar.gz
linux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.zip
staging: rtl8723bs: fix OOB read in rtw_action_frame_parse()grafted
rtw_action_frame_parse() takes a frame_len parameter but never actually checks it before indexing into the frame body: const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr); ... c = frame_body[0]; ... a = frame_body[1]; frame_body already points 24 bytes (sizeof(struct ieee80211_hdr_3addr)) into frame, so reading frame_body[0] and frame_body[1] requires frame_len >= 26. A management action frame shorter than that (e.g. exactly 24 bytes, the minimum a malicious peer can send) causes a 1-2 byte out-of-bounds read. This is reachable from rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() in ioctl_cfg80211.c, both of which pass attacker/user-influenced frame buffers and lengths straight through. Add the missing length check before frame_body is dereferenced. Fixes: 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal <meatuni001@gmail.com> Link: https://patch.msgid.link/20260728125456.32359-3-meatuni001@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/perf/util/disasm.h')
-rw-r--r--tools/perf/util/disasm.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
new file mode 100644
index 000000000..25756e3f4
--- /dev/null
+++ b/tools/perf/util/disasm.h
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __PERF_UTIL_DISASM_H
+#define __PERF_UTIL_DISASM_H
+
+#include "map_symbol.h"
+
+#ifdef HAVE_LIBDW_SUPPORT
+#include "dwarf-aux.h"
+#endif
+
+struct annotation_options;
+struct disasm_line;
+struct ins;
+struct evsel;
+struct symbol;
+struct data_loc_info;
+struct type_state;
+struct disasm_line;
+
+struct e_machine_and_e_flags {
+ uint32_t e_flags;
+ uint16_t e_machine;
+};
+
+struct arch {
+ /** @name: name such as "x86" or "powerpc". */
+ const char *name;
+ const struct ins *instructions;
+ size_t nr_instructions;
+ size_t nr_instructions_allocated;
+ const char *insn_suffix;
+ unsigned int model;
+ unsigned int family;
+ /** @id: ELF machine and flags associated with arch. */
+ struct e_machine_and_e_flags id;
+ bool sorted_instructions;
+ struct {
+ char comment_char;
+ char skip_functions_char;
+ char register_char;
+ char memory_ref_char;
+ char imm_char;
+ } objdump;
+ bool (*ins_is_fused)(const struct arch *arch, const char *ins1,
+ const char *ins2);
+ const struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
+#ifdef HAVE_LIBDW_SUPPORT
+ void (*update_insn_state)(struct type_state *state,
+ struct data_loc_info *dloc, Dwarf_Die *cu_die,
+ struct disasm_line *dl);
+#endif
+};
+
+struct ins {
+ const char *name;
+ const struct ins_ops *ops;
+};
+
+struct ins_operands {
+ char *raw;
+ struct {
+ char *raw;
+ char *name;
+ struct symbol *sym;
+ u64 addr;
+ s64 offset;
+ bool offset_avail;
+ bool outside;
+ bool multi_regs;
+ bool mem_ref;
+ } target;
+ union {
+ struct {
+ char *raw;
+ char *name;
+ u64 addr;
+ bool multi_regs;
+ bool mem_ref;
+ } source;
+ struct {
+ struct ins ins;
+ struct ins_operands *ops;
+ } locked;
+ struct {
+ char *raw_comment;
+ char *raw_func_start;
+ } jump;
+ };
+};
+
+struct ins_ops {
+ void (*free)(struct ins_operands *ops);
+ int (*parse)(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
+ struct disasm_line *dl);
+ int (*scnprintf)(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+ bool is_jump;
+ bool is_call;
+};
+
+struct annotate_args {
+ const struct arch *arch;
+ struct map_symbol *ms;
+ struct annotation_options *options;
+ s64 offset;
+ char *line;
+ int line_nr;
+ char *fileloc;
+};
+
+const struct arch *arch__find(uint16_t e_machine, uint32_t e_flags, const char *cpuid);
+bool arch__is_x86(const struct arch *arch);
+bool arch__is_powerpc(const struct arch *arch);
+
+extern const struct ins_ops call_ops;
+extern const struct ins_ops dec_ops;
+extern const struct ins_ops jump_ops;
+extern const struct ins_ops mov_ops;
+extern const struct ins_ops nop_ops;
+extern const struct ins_ops lock_ops;
+extern const struct ins_ops ret_ops;
+
+int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops);
+
+const struct arch *arch__new_arc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_arm(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_arm64(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_csky(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_loongarch(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_mips(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_powerpc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_riscv64(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_s390(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_sparc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_x86(const struct e_machine_and_e_flags *id, const char *cpuid);
+
+const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
+
+bool ins__is_call(const struct ins *ins);
+bool ins__is_jump(const struct ins *ins);
+bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2);
+bool ins__is_ret(const struct ins *ins);
+bool ins__is_lock(const struct ins *ins);
+
+const struct ins_ops *check_ppc_insn(struct disasm_line *dl);
+
+struct disasm_line *disasm_line__new(struct annotate_args *args);
+void disasm_line__free(struct disasm_line *dl);
+
+int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size,
+ bool raw, int max_ins_name);
+
+int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int call__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+
+void jump__delete(struct ins_operands *ops);
+
+int symbol__disassemble(struct symbol *sym, struct annotate_args *args);
+
+char *expand_tabs(char *line, char **storage, size_t *storage_len);
+
+#endif /* __PERF_UTIL_DISASM_H */