Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: cfg80211: allocate memory for link_station info structure

Currently, station_info structure is passed to fill station statistics
from mac80211/drivers. After NL message send to user space for requested
station statistics, memory for station statistics is freed in cfg80211.
Therefore, memory allocation/free for link station statistics should
also happen in cfg80211 only.

Hence, allocate the memory for link_station structure for all
possible links and free in cfg80211_sinfo_release_content().

Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
Link: https://patch.msgid.link/20250528054420.3050133-6-quic_sarishar@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Sarika Sharma and committed by
Johannes Berg
49e47223 2d226d41

+31 -3
+7
include/net/cfg80211.h
··· 8577 8577 static inline void cfg80211_sinfo_release_content(struct station_info *sinfo) 8578 8578 { 8579 8579 kfree(sinfo->pertid); 8580 + 8581 + for (int link_id = 0; link_id < ARRAY_SIZE(sinfo->links); link_id++) { 8582 + if (sinfo->links[link_id]) { 8583 + kfree(sinfo->links[link_id]->pertid); 8584 + kfree(sinfo->links[link_id]); 8585 + } 8586 + } 8580 8587 } 8581 8588 8582 8589 /**
+24 -3
net/wireless/nl80211.c
··· 7366 7366 struct wireless_dev *wdev; 7367 7367 u8 mac_addr[ETH_ALEN]; 7368 7368 int sta_idx = cb->args[2]; 7369 - int err; 7369 + int err, i; 7370 7370 7371 7371 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); 7372 7372 if (err) ··· 7386 7386 7387 7387 while (1) { 7388 7388 memset(&sinfo, 0, sizeof(sinfo)); 7389 + 7390 + for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { 7391 + sinfo.links[i] = 7392 + kzalloc(sizeof(*sinfo.links[0]), GFP_KERNEL); 7393 + if (!sinfo.links[i]) { 7394 + err = -ENOMEM; 7395 + goto out_err; 7396 + } 7397 + } 7398 + 7389 7399 err = rdev_dump_station(rdev, wdev->netdev, sta_idx, 7390 7400 mac_addr, &sinfo); 7391 7401 if (err == -ENOENT) ··· 7420 7410 cb->args[2] = sta_idx; 7421 7411 err = skb->len; 7422 7412 out_err: 7413 + cfg80211_sinfo_release_content(&sinfo); 7423 7414 wiphy_unlock(&rdev->wiphy); 7424 7415 7425 7416 return err; ··· 7433 7422 struct station_info sinfo; 7434 7423 struct sk_buff *msg; 7435 7424 u8 *mac_addr = NULL; 7436 - int err; 7425 + int err, i; 7437 7426 7438 7427 memset(&sinfo, 0, sizeof(sinfo)); 7439 7428 ··· 7445 7434 if (!rdev->ops->get_station) 7446 7435 return -EOPNOTSUPP; 7447 7436 7437 + for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { 7438 + sinfo.links[i] = kzalloc(sizeof(*sinfo.links[0]), GFP_KERNEL); 7439 + if (!sinfo.links[i]) { 7440 + cfg80211_sinfo_release_content(&sinfo); 7441 + return -ENOMEM; 7442 + } 7443 + } 7444 + 7448 7445 err = rdev_get_station(rdev, dev, mac_addr, &sinfo); 7449 - if (err) 7446 + if (err) { 7447 + cfg80211_sinfo_release_content(&sinfo); 7450 7448 return err; 7449 + } 7451 7450 7452 7451 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 7453 7452 if (!msg) {