summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2023-03-14 10:59:51 +0100
committerJohannes Berg <johannes.berg@intel.com>2023-03-22 13:31:18 +0100
commite626dad92383ca16d1d71e66124a272a0cbfe7bd (patch)
treeaaff82328031e5dbaad29ea3719b9484080f716c /net/mac80211
parentwifi: mac80211: add support for letting drivers register tc offload support (diff)
downloadlinux-e626dad92383ca16d1d71e66124a272a0cbfe7bd.tar.xz
linux-e626dad92383ca16d1d71e66124a272a0cbfe7bd.zip
wifi: mac80211: fix race in mesh sequence number assignment
Since the sequence number is shared across different tx queues, it needs to be atomic in order to avoid accidental duplicate assignment Signed-off-by: Felix Fietkau <nbd@nbd.name> Link: https://lore.kernel.org/r/20230314095956.62085-2-nbd@nbd.name Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mesh.c6
2 files changed, 3 insertions, 5 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b2535614483e..04017d5c435a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -696,7 +696,7 @@ struct ieee80211_if_mesh {
struct mesh_stats mshstats;
struct mesh_config mshcfg;
atomic_t estab_plinks;
- u32 mesh_seqnum;
+ atomic_t mesh_seqnum;
bool accepting_plinks;
int num_gates;
struct beacon_data __rcu *beacon;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5a99b8f6e465..0608ed415831 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -752,10 +752,8 @@ unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
- /* FIXME: racy -- TX on multiple queues can be concurrent */
- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
- sdata->u.mesh.mesh_seqnum++;
-
+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
+ &meshhdr->seqnum);
if (addr4or5 && !addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A4;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);