From ff917923f4fb9c83717ba135ee47d7e4c1567bb7 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Tue, 28 Jul 2026 17:54:55 +0500 Subject: staging: rtl8723bs: fix OOB read in rtw_action_frame_parse() 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 Link: https://patch.msgid.link/20260728125456.32359-3-meatuni001@gmail.com Signed-off-by: Greg Kroah-Hartman --- scripts/atomic/gen-atomic-fallback.sh | 336 ++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100755 scripts/atomic/gen-atomic-fallback.sh (limited to 'scripts/atomic/gen-atomic-fallback.sh') diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh new file mode 100755 index 000000000..f80d69cfe --- /dev/null +++ b/scripts/atomic/gen-atomic-fallback.sh @@ -0,0 +1,336 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +ATOMICDIR=$(dirname $0) + +. ${ATOMICDIR}/atomic-tbl.sh + +#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...) +gen_template_fallback() +{ + local template="$1"; shift + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift + + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" + + . ${template} +} + +#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_order_fallback() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local tmpl_order=${order#_} + local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}" + gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" +} + +#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_fallback() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" +} + +#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_order_variant() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift + + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + local basename="${atomic}_${pfx}${name}${sfx}" + + local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" + + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + + printf "static __always_inline ${ret}\n" + printf "raw_${atomicname}(${params})\n" + printf "{\n" + + # Where there is no possible fallback, this order variant is mandatory + # and must be provided by arch code. Add a comment to the header to + # make this obvious. + # + # Ideally we'd error on a missing definition, but arch code might + # define this order variant as a C function without a preprocessor + # symbol. + if [ -z ${template} ] && [ -z "${order}" ] && ! meta_has_relaxed "${meta}"; then + printf "\t${retstmt}arch_${atomicname}(${args});\n" + printf "}\n\n" + return + fi + + printf "#if defined(arch_${atomicname})\n" + printf "\t${retstmt}arch_${atomicname}(${args});\n" + + # Allow FULL/ACQUIRE/RELEASE ops to be defined in terms of RELAXED ops + if [ "${order}" != "_relaxed" ] && meta_has_relaxed "${meta}"; then + printf "#elif defined(arch_${basename}_relaxed)\n" + gen_order_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + fi + + # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops + if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then + printf "#elif defined(arch_${basename})\n" + printf "\t${retstmt}arch_${basename}(${args});\n" + fi + + printf "#else\n" + if [ ! -z "${template}" ]; then + gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + else + printf "#error \"Unable to define raw_${atomicname}\"\n" + fi + + printf "#endif\n" + printf "}\n\n" +} + + +#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) +gen_proto_order_variants() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local atomic="$1" + + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + + if meta_has_acquire "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" + fi + + if meta_has_release "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" + fi + + if meta_has_relaxed "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" + fi +} + +#gen_basic_fallbacks(basename) +gen_basic_fallbacks() +{ + local basename="$1"; shift +cat << EOF +#define raw_${basename}_acquire arch_${basename} +#define raw_${basename}_release arch_${basename} +#define raw_${basename}_relaxed arch_${basename} +EOF +} + +gen_order_fallbacks() +{ + local xchg="$1"; shift + +cat < + +EOF + +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do + gen_xchg_fallbacks "${xchg}" +done + +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do + gen_try_cmpxchg_order_fallbacks "${cmpxchg}" +done + +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do + gen_def_and_try_cmpxchg_fallback "" "${cmpxchg}" "_local" +done + +for cmpxchg in "cmpxchg"; do + gen_def_and_try_cmpxchg_fallback "sync_" "${cmpxchg}" "" +done + +grep '^[a-z]' "$1" | while read name meta args; do + gen_proto "${meta}" "${name}" "atomic" "int" ${args} +done + +cat < +#endif + +EOF + +grep '^[a-z]' "$1" | while read name meta args; do + gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} +done + +cat <