drivers/net/wireless/virtual/mac80211_hwsim.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
Prevent a division by zero crash when userspace provides a zero beacon
interval value. The crash occurs in the beacon timer setup code path when
info->beacon_int is 0, causing bcn_int to be 0 and triggering a divide
error in the do_div() macro.The issue can be triggered from userspace via
nl80211/cfg80211 when configuring a virtual interface in AP mode with an
invalid beacon interval.
Fixes: e57f8a489c29 ("wifi: mac80211_hwsim: send a beacon per link")
Reported-by: syzbot+5bb5f06f99924ea0cf86@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5bb5f06f99924ea0cf86
Signed-off-by: Deepakkumar Karn <dkarn@redhat.com>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 5903d82e1ab1..e67e2c989ea6 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -2595,11 +2595,14 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
link_data->beacon_int = info->beacon_int * 1024;
tsf = mac80211_hwsim_get_tsf(hw, vif);
bcn_int = link_data->beacon_int;
- until_tbtt = bcn_int - do_div(tsf, bcn_int);
+ /* Proceed only when bcn_int != 0 */
+ if (bcn_int) {
+ until_tbtt = bcn_int - do_div(tsf, bcn_int);
- hrtimer_start(&link_data->beacon_timer,
- ns_to_ktime(until_tbtt * NSEC_PER_USEC),
- HRTIMER_MODE_REL_SOFT);
+ hrtimer_start(&link_data->beacon_timer,
+ ns_to_ktime(until_tbtt * NSEC_PER_USEC),
+ HRTIMER_MODE_REL_SOFT);
+ }
} else if (!info->enable_beacon) {
unsigned int count = 0;
ieee80211_iterate_active_interfaces_atomic(
--
2.51.1
On Fri, 2025-12-05 at 21:05 +0530, Deepakkumar Karn wrote: > Prevent a division by zero crash when userspace provides a zero beacon > interval value. The crash occurs in the beacon timer setup code path when > info->beacon_int is 0, causing bcn_int to be 0 and triggering a divide > error in the do_div() macro.The issue can be triggered from userspace via > nl80211/cfg80211 when configuring a virtual interface in AP mode with an > invalid beacon interval. Seems like we should not let userspace do that, to protect all other drivers too, not just hwsim. johannes
On Fri, 05 Dec 2025 18:39:49 +0100, Johannes Berg wrote: > Seems like we should not let userspace do that, to protect all other > drivers too, not just hwsim. As suggested, we should provide a zero-value division check for other drivers as well. I will investigate other places where divide errors can occur due to edge cases. Please let me know if you meant something different. In the meantime, I will analyze other drivers for similar cases. Thanks, Deepakkumar Karn
On Sat, 2025-12-06 at 04:33 +0530, Deepakkumar Karn wrote: > On Fri, 05 Dec 2025 18:39:49 +0100, Johannes Berg wrote: > > Seems like we should not let userspace do that, to protect all other > > drivers too, not just hwsim. > > As suggested, we should provide a zero-value division check for other > drivers as well. I will investigate other places where divide errors can > occur due to edge cases. What, no no. > Please let me know if you meant something different. In the meantime, > I will analyze other drivers for similar cases. I did. My point is we shouldn't _have_ to check any drivers for this at all, it's nonsense and higher layers (here cfg80211) should reject it. johannes
> On Sat, 2025-12-06 at 04:33 +0530, Deepakkumar Karn wrote:
> > On Fri, 05 Dec 2025 18:39:49 +0100, Johannes Berg wrote:
> > > Seems like we should not let userspace do that, to protect all other
> > > drivers too, not just hwsim.
> >
> > As suggested, we should provide a zero-value division check for other
> > drivers as well. I will investigate other places where divide errors can
> > occur due to edge cases.
> What, no no.
> > Please let me know if you meant something different. In the meantime,
> > I will analyze other drivers for similar cases.
> I did. My point is we shouldn't _have_ to check any drivers for this at
> all, it's nonsense and higher layers (here cfg80211) should reject it.
Thank you for your response Johannes. cfg80211 already have validation
in cfg80211_validate_beacon_int(). The problem seems to occur in
case of interface shutdown which calls ieee80211_do_stop() that makes
beacon_int = 0 or set_tsf which causes divides by zero.
What if we:
1. Handle off-channel operation:
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index ae82533e3c02..14a103d320e3 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -156,10 +156,12 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
&sdata->state)) {
- sdata->vif.bss_conf.enable_beacon = true;
- ieee80211_link_info_change_notify(
- sdata, &sdata->deflink,
- BSS_CHANGED_BEACON_ENABLED);
+ if (sdata->vif.bss_conf.beacon_int) {
+ sdata->vif.bss_conf.enable_beacon = true;
+ ieee80211_link_info_change_notify(
+ sdata, &sdata->deflink,
+ BSS_CHANGED_BEACON_ENABLED);
+ }
}
}
2. Handle case where debugfs is written after shutdown or any race condition during disable beaconing:
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 551f5eb4e747..8363cdd17a97 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -1242,7 +1242,7 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *conf;
conf = link_conf_dereference_protected(vif, data->link_data[0].link_id);
- if (conf && !conf->enable_beacon)
+ if ((conf && !conf->enable_beacon) || !bcn_int)
return;
/* adjust after beaconing with new timestamp at old TBTT */
3. As other drivers already have beacon_int 0 value validation, consider
earlier patch along with above 2 points?
On Sat, 2025-12-06 at 23:03 +0530, Deepakkumar Karn wrote:
>
>
> Thank you for your response Johannes. cfg80211 already have validation
> in cfg80211_validate_beacon_int().
Oh OK.
> The problem seems to occur in
> case of interface shutdown which calls ieee80211_do_stop() that makes
> beacon_int = 0 or set_tsf which causes divides by zero.
Why would that call set_tsf()?
And yeah that should make beacon_int=0, but not have beaconing enabled.
> What if we:
> 1. Handle off-channel operation:
> if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
> &sdata->state)) {
> - sdata->vif.bss_conf.enable_beacon = true;
> - ieee80211_link_info_change_notify(
> - sdata, &sdata->deflink,
> - BSS_CHANGED_BEACON_ENABLED);
> + if (sdata->vif.bss_conf.beacon_int) {
> + sdata->vif.bss_conf.enable_beacon = true;
> + ieee80211_link_info_change_notify(
> + sdata, &sdata->deflink,
> + BSS_CHANGED_BEACON_ENABLED);
> + }
don't follow, that only does it when beacon was actually stopped ...
maybe do_stop() needs to clear that bit if there's a possibility of this
happening in the wrong order, but I don't see how there could be a race
since off-channel must also be stopped at that point anyway, unless that
is in the wrong order.
> 2. Handle case where debugfs is written after shutdown or any race condition during disable beaconing:
>
> diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
> index 551f5eb4e747..8363cdd17a97 100644
> --- a/drivers/net/wireless/virtual/mac80211_hwsim.c
first of all, I really do think you should *not* (need to) modify hwsim
at all
> conf = link_conf_dereference_protected(vif, data->link_data[0].link_id);
> - if (conf && !conf->enable_beacon)
> + if ((conf && !conf->enable_beacon) || !bcn_int)
> return;
But this also makes no sense, it shouldn't be possible to have beacon
enabled and beacon interval == 0.
johannes
On Mon, Dec 8, 2025 at 2:00 PM Johannes Berg <johannes@sipsolutions.net> wrote:
>
> On Sat, 2025-12-06 at 23:03 +0530, Deepakkumar Karn wrote:
> >
> >
> > Thank you for your response Johannes. cfg80211 already have validation
> > in cfg80211_validate_beacon_int().
>
> Oh OK.
>
> > The problem seems to occur in
> > case of interface shutdown which calls ieee80211_do_stop() that makes
> > beacon_int = 0 or set_tsf which causes divides by zero.
>
> Why would that call set_tsf()?
>
> And yeah that should make beacon_int=0, but not have beaconing enabled.
>
> > What if we:
> > 1. Handle off-channel operation:
>
> > if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
> > &sdata->state)) {
> > - sdata->vif.bss_conf.enable_beacon = true;
> > - ieee80211_link_info_change_notify(
> > - sdata, &sdata->deflink,
> > - BSS_CHANGED_BEACON_ENABLED);
> > + if (sdata->vif.bss_conf.beacon_int) {
> > + sdata->vif.bss_conf.enable_beacon = true;
> > + ieee80211_link_info_change_notify(
> > + sdata, &sdata->deflink,
> > + BSS_CHANGED_BEACON_ENABLED);
> > + }
>
> don't follow, that only does it when beacon was actually stopped ...
> maybe do_stop() needs to clear that bit if there's a possibility of this
> happening in the wrong order, but I don't see how there could be a race
> since off-channel must also be stopped at that point anyway, unless that
> is in the wrong order.
>
> > 2. Handle case where debugfs is written after shutdown or any race condition during disable beaconing:
> >
> > diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
> > index 551f5eb4e747..8363cdd17a97 100644
> > --- a/drivers/net/wireless/virtual/mac80211_hwsim.c
>
> first of all, I really do think you should *not* (need to) modify hwsim
> at all
>
> > conf = link_conf_dereference_protected(vif, data->link_data[0].link_id);
> > - if (conf && !conf->enable_beacon)
> > + if ((conf && !conf->enable_beacon) || !bcn_int)
> > return;
>
> But this also makes no sense, it shouldn't be possible to have beacon
> enabled and beacon interval == 0.
>
Thank you Johannes. As you highlighted I searched for a code path if
there is any place that has the
invariant condition of beacon being enabled and beacon int is 0 but
none seems to be having that.
Regards,
Deepakkumar Karn
© 2016 - 2025 Red Hat, Inc.