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 --- drivers/rpmsg/rpmsg_internal.h | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 drivers/rpmsg/rpmsg_internal.h (limited to 'drivers/rpmsg/rpmsg_internal.h') diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h new file mode 100644 index 000000000..a8b7065fd --- /dev/null +++ b/drivers/rpmsg/rpmsg_internal.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * remote processor messaging bus internals + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * + * Ohad Ben-Cohen + * Brian Swetland + */ + +#ifndef __RPMSG_INTERNAL_H__ +#define __RPMSG_INTERNAL_H__ + +#include +#include + +#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) +#define to_rpmsg_driver(d) container_of_const(d, struct rpmsg_driver, drv) + +extern const struct class rpmsg_class; + +/** + * struct rpmsg_device_ops - indirection table for the rpmsg_device operations + * @create_channel: create backend-specific channel, optional + * @release_channel: release backend-specific channel, optional + * @create_ept: create backend-specific endpoint, required + * @announce_create: announce presence of new channel, optional + * @announce_destroy: announce destruction of channel, optional + * + * Indirection table for the operations that a rpmsg backend should implement. + * @announce_create and @announce_destroy are optional as the backend might + * advertise new channels implicitly by creating the endpoints. + */ +struct rpmsg_device_ops { + struct rpmsg_device *(*create_channel)(struct rpmsg_device *rpdev, + struct rpmsg_channel_info *chinfo); + int (*release_channel)(struct rpmsg_device *rpdev, + struct rpmsg_channel_info *chinfo); + struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev, + rpmsg_rx_cb_t cb, void *priv, + struct rpmsg_channel_info chinfo); + + int (*announce_create)(struct rpmsg_device *rpdev); + int (*announce_destroy)(struct rpmsg_device *rpdev); +}; + +/** + * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations + * @destroy_ept: see @rpmsg_destroy_ept(), required + * @send: see @rpmsg_send(), required + * @sendto: see @rpmsg_sendto(), optional + * @trysend: see @rpmsg_trysend(), required + * @trysendto: see @rpmsg_trysendto(), optional + * @poll: see @rpmsg_poll(), optional + * @set_flow_control: see @rpmsg_set_flow_control(), optional + * @get_mtu: see @rpmsg_get_mtu(), optional + * + * Indirection table for the operations that a rpmsg backend should implement. + * In addition to @destroy_ept, the backend must at least implement @send and + * @trysend, while the variants sending data off-channel are optional. + */ +struct rpmsg_endpoint_ops { + void (*destroy_ept)(struct rpmsg_endpoint *ept); + + int (*send)(struct rpmsg_endpoint *ept, const void *data, int len); + int (*sendto)(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst); + + int (*trysend)(struct rpmsg_endpoint *ept, const void *data, int len); + int (*trysendto)(struct rpmsg_endpoint *ept, const void *data, int len, u32 dst); + __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, + poll_table *wait); + int (*set_flow_control)(struct rpmsg_endpoint *ept, bool pause, u32 dst); + ssize_t (*get_mtu)(struct rpmsg_endpoint *ept); +}; + +struct device *rpmsg_find_device(struct device *parent, + struct rpmsg_channel_info *chinfo); + +struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev, + struct rpmsg_channel_info *chinfo); +int rpmsg_release_channel(struct rpmsg_device *rpdev, + struct rpmsg_channel_info *chinfo); +/** + * rpmsg_ctrldev_register_device() - register a char device for control based on rpdev + * @rpdev: prepared rpdev to be used for creating endpoints + * + * This function wraps rpmsg_register_device() preparing the rpdev for use as + * basis for the rpmsg chrdev. + */ +static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev) +{ + return rpmsg_register_device_override(rpdev, "rpmsg_ctrl"); +} + +#endif -- cgit v1.3.1