mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
wifi: p54: validate curve data length in the calibration curve converters
p54_convert_rev0() and p54_convert_rev1() read calibration curve
data from the device-supplied EEPROM entry using channel and
points-per-channel counts taken verbatim from that same entry, so
an entry that declares more data than it carries drives an
out-of-bounds read past the EEPROM buffer (verified with a KASAN
reproducer of the conversion loop). The sibling converters
p54_convert_output_limits() and p54_convert_db() already validate
their counts against the entry length; this path was missed.
Reject the entry when the counts do not fit in the entry data.
Fixes: eff1a59c48 ("[P54]: add mac80211-based driver for prism54 softmac hardware")
Cc: stable@vger.kernel.org
Assisted-by: GLM:5.3
Signed-off-by: Shengzhuo Wei <me@cherr.cc>
Link: https://patch.msgid.link/20260831-p54-pda-validation-v2-1-dae566b388c8@cherr.cc
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c46cfaf8db
commit
ce858fa6b8
|
|
@ -414,17 +414,22 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
|
|||
}
|
||||
|
||||
static int p54_convert_rev0(struct ieee80211_hw *dev,
|
||||
struct pda_pa_curve_data *curve_data)
|
||||
struct pda_pa_curve_data *curve_data, size_t len)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct p54_pa_curve_data_sample *dst;
|
||||
struct pda_pa_curve_data_sample_rev0 *src;
|
||||
size_t needed = curve_data->channels *
|
||||
(sizeof(*src) * curve_data->points_per_channel + 2);
|
||||
size_t cd_len = sizeof(*curve_data) +
|
||||
(curve_data->points_per_channel*sizeof(*dst) + 2) *
|
||||
curve_data->channels;
|
||||
unsigned int i, j;
|
||||
void *source, *target;
|
||||
|
||||
if (len < sizeof(*curve_data) + needed)
|
||||
return -EINVAL;
|
||||
|
||||
priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
|
||||
GFP_KERNEL);
|
||||
if (!priv->curve_data)
|
||||
|
|
@ -466,17 +471,22 @@ static int p54_convert_rev0(struct ieee80211_hw *dev,
|
|||
}
|
||||
|
||||
static int p54_convert_rev1(struct ieee80211_hw *dev,
|
||||
struct pda_pa_curve_data *curve_data)
|
||||
struct pda_pa_curve_data *curve_data, size_t len)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct p54_pa_curve_data_sample *dst;
|
||||
struct pda_pa_curve_data_sample_rev1 *src;
|
||||
size_t needed = curve_data->channels *
|
||||
(sizeof(*src) * curve_data->points_per_channel + 3);
|
||||
size_t cd_len = sizeof(*curve_data) +
|
||||
(curve_data->points_per_channel*sizeof(*dst) + 2) *
|
||||
curve_data->channels;
|
||||
unsigned int i, j;
|
||||
void *source, *target;
|
||||
|
||||
if (len < sizeof(*curve_data) + needed)
|
||||
return -EINVAL;
|
||||
|
||||
priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
|
||||
GFP_KERNEL);
|
||||
if (!priv->curve_data)
|
||||
|
|
@ -763,6 +773,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
|
|||
case PDR_PRISM_PA_CAL_CURVE_DATA: {
|
||||
struct pda_pa_curve_data *curve_data =
|
||||
(struct pda_pa_curve_data *)entry->data;
|
||||
|
||||
if (data_len < sizeof(*curve_data)) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
|
|
@ -770,10 +781,10 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
|
|||
|
||||
switch (curve_data->cal_method_rev) {
|
||||
case 0:
|
||||
err = p54_convert_rev0(dev, curve_data);
|
||||
err = p54_convert_rev0(dev, curve_data, data_len);
|
||||
break;
|
||||
case 1:
|
||||
err = p54_convert_rev1(dev, curve_data);
|
||||
err = p54_convert_rev1(dev, curve_data, data_len);
|
||||
break;
|
||||
default:
|
||||
wiphy_err(dev->wiphy,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user