]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: cfg80211: allocate memory for link_station info structure
authorSarika Sharma <quic_sarishar@quicinc.com>
Wed, 28 May 2025 05:44:15 +0000 (11:14 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 24 Jun 2025 13:19:26 +0000 (15:19 +0200)
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>
include/net/cfg80211.h
net/wireless/nl80211.c

index b008357cac03cedee4d04075681bb50267582fdb..7bf0c97d2ab139a65a4453da5d71ba001ff636ea 100644 (file)
@@ -8577,6 +8577,13 @@ int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp);
 static inline void cfg80211_sinfo_release_content(struct station_info *sinfo)
 {
        kfree(sinfo->pertid);
+
+       for (int link_id = 0; link_id < ARRAY_SIZE(sinfo->links); link_id++) {
+               if (sinfo->links[link_id]) {
+                       kfree(sinfo->links[link_id]->pertid);
+                       kfree(sinfo->links[link_id]);
+               }
+       }
 }
 
 /**
index 83f6291eac9297340700fb3108b89364b54bb839..5137824520a11540ae88b29ed3ef5def4393d222 100644 (file)
@@ -7366,7 +7366,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        struct wireless_dev *wdev;
        u8 mac_addr[ETH_ALEN];
        int sta_idx = cb->args[2];
-       int err;
+       int err, i;
 
        err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
        if (err)
@@ -7386,6 +7386,16 @@ static int nl80211_dump_station(struct sk_buff *skb,
 
        while (1) {
                memset(&sinfo, 0, sizeof(sinfo));
+
+               for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+                       sinfo.links[i] =
+                               kzalloc(sizeof(*sinfo.links[0]), GFP_KERNEL);
+                       if (!sinfo.links[i]) {
+                               err = -ENOMEM;
+                               goto out_err;
+                       }
+               }
+
                err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
                                        mac_addr, &sinfo);
                if (err == -ENOENT)
@@ -7410,6 +7420,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        cb->args[2] = sta_idx;
        err = skb->len;
  out_err:
+       cfg80211_sinfo_release_content(&sinfo);
        wiphy_unlock(&rdev->wiphy);
 
        return err;
@@ -7422,7 +7433,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
        struct station_info sinfo;
        struct sk_buff *msg;
        u8 *mac_addr = NULL;
-       int err;
+       int err, i;
 
        memset(&sinfo, 0, sizeof(sinfo));
 
@@ -7434,9 +7445,19 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->get_station)
                return -EOPNOTSUPP;
 
+       for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+               sinfo.links[i] = kzalloc(sizeof(*sinfo.links[0]), GFP_KERNEL);
+               if (!sinfo.links[i]) {
+                       cfg80211_sinfo_release_content(&sinfo);
+                       return -ENOMEM;
+               }
+       }
+
        err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
-       if (err)
+       if (err) {
+               cfg80211_sinfo_release_content(&sinfo);
                return err;
+       }
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg) {