mac80211: debugfs: calculate free buffer size correctly
authorMordechay Goodstein <mordechay.goodstein@intel.com>
Thu, 21 Oct 2021 14:30:36 +0000 (16:30 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 21 Oct 2021 14:46:02 +0000 (16:46 +0200)
In breaking patch buf memory moved from stack to heap and sizeof(buf)
change from size of actual memory to size of the pointer to the heap.

Fix this by holding a separated variable for allocate size.

Fixes: 01f84f0ed3b4 ("mac80211: reduce stack usage in debugfs")
Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Link: https://lore.kernel.org/r/20211021163035.b9ae48c06e27.I6a6ed197110eae28cf4f6e38ce36828a7c136337@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/debugfs_sta.c

index da22725..481f01b 100644 (file)
@@ -153,20 +153,20 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
        rcu_read_lock();
 
        p += scnprintf(p,
-                      bufsz+buf-p,
+                      bufsz + buf - p,
                       "target %uus interval %uus ecn %s\n",
                       codel_time_to_us(sta->cparams.target),
                       codel_time_to_us(sta->cparams.interval),
                       sta->cparams.ecn ? "yes" : "no");
        p += scnprintf(p,
-                      bufsz+buf-p,
+                      bufsz + buf - p,
                       "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");
 
        for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
                if (!sta->sta.txq[i])
                        continue;
                txqi = to_txq_info(sta->sta.txq[i]);
-               p += scnprintf(p, bufsz+buf-p,
+               p += scnprintf(p, bufsz + buf - p,
                               "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",
                               txqi->txq.tid,
                               txqi->txq.ac,
@@ -315,22 +315,23 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
                                        size_t count, loff_t *ppos)
 {
        char *buf, *p;
+       ssize_t bufsz = 71 + IEEE80211_NUM_TIDS * 40;
        int i;
        struct sta_info *sta = file->private_data;
        struct tid_ampdu_rx *tid_rx;
        struct tid_ampdu_tx *tid_tx;
        ssize_t ret;
 
-       buf = kzalloc(71 + IEEE80211_NUM_TIDS * 40, GFP_KERNEL);
+       buf = kzalloc(bufsz, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
        p = buf;
 
        rcu_read_lock();
 
-       p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
+       p += scnprintf(p, bufsz + buf - p, "next dialog_token: %#02x\n",
                        sta->ampdu_mlme.dialog_token_allocator + 1);
-       p += scnprintf(p, sizeof(buf) + buf - p,
+       p += scnprintf(p, bufsz + buf - p,
                       "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
 
        for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
@@ -340,21 +341,21 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
                tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
                tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid);
 
-               p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
+               p += scnprintf(p, bufsz + buf - p, "%02d", i);
+               p += scnprintf(p, bufsz + buf - p, "\t\t%x",
                               tid_rx_valid);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
+               p += scnprintf(p, bufsz + buf - p, "\t%#.2x",
                               tid_rx_valid ?
                                        sta->ampdu_mlme.tid_rx_token[i] : 0);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
+               p += scnprintf(p, bufsz + buf - p, "\t%#.3x",
                                tid_rx ? tid_rx->ssn : 0);
 
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
+               p += scnprintf(p, bufsz + buf - p, "\t\t%x", !!tid_tx);
+               p += scnprintf(p, bufsz + buf - p, "\t%#.2x",
                                tid_tx ? tid_tx->dialog_token : 0);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
+               p += scnprintf(p, bufsz + buf - p, "\t%03d",
                                tid_tx ? skb_queue_len(&tid_tx->pending) : 0);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\n");
+               p += scnprintf(p, bufsz + buf - p, "\n");
        }
        rcu_read_unlock();
 
@@ -444,19 +445,20 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
        } while (0)
        char *buf, *p;
        int i;
+       ssize_t bufsz = 512;
        struct sta_info *sta = file->private_data;
        struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;
        ssize_t ret;
 
-       buf = kzalloc(512, GFP_KERNEL);
+       buf = kzalloc(bufsz, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
        p = buf;
 
-       p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n",
+       p += scnprintf(p, bufsz + buf - p, "ht %ssupported\n",
                        htc->ht_supported ? "" : "not ");
        if (htc->ht_supported) {
-               p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap);
+               p += scnprintf(p, bufsz + buf - p, "cap: %#.4x\n", htc->cap);
 
                PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDPC");
                PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40");
@@ -498,23 +500,23 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
 
                PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection");
 
-               p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n",
+               p += scnprintf(p, bufsz + buf - p, "ampdu factor/density: %d/%d\n",
                                htc->ampdu_factor, htc->ampdu_density);
-               p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:");
+               p += scnprintf(p, bufsz + buf - p, "MCS mask:");
 
                for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
-                       p += scnprintf(p, sizeof(buf)+buf-p, " %.2x",
+                       p += scnprintf(p, bufsz + buf - p, " %.2x",
                                        htc->mcs.rx_mask[i]);
-               p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+               p += scnprintf(p, bufsz + buf - p, "\n");
 
                /* If not set this is meaningless */
                if (le16_to_cpu(htc->mcs.rx_highest)) {
-                       p += scnprintf(p, sizeof(buf)+buf-p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "MCS rx highest: %d Mbps\n",
                                       le16_to_cpu(htc->mcs.rx_highest));
                }
 
-               p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n",
+               p += scnprintf(p, bufsz + buf - p, "MCS tx params: %x\n",
                                htc->mcs.tx_params);
        }
 
@@ -531,56 +533,57 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
        struct sta_info *sta = file->private_data;
        struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap;
        ssize_t ret;
+       ssize_t bufsz = 512;
 
-       buf = kzalloc(512, GFP_KERNEL);
+       buf = kzalloc(bufsz, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
        p = buf;
 
-       p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n",
+       p += scnprintf(p, bufsz + buf - p, "VHT %ssupported\n",
                        vhtc->vht_supported ? "" : "not ");
        if (vhtc->vht_supported) {
-               p += scnprintf(p, sizeof(buf) + buf - p, "cap: %#.8x\n",
+               p += scnprintf(p, bufsz + buf - p, "cap: %#.8x\n",
                               vhtc->cap);
 #define PFLAG(a, b)                                                    \
                do {                                                    \
                        if (vhtc->cap & IEEE80211_VHT_CAP_ ## a)        \
-                               p += scnprintf(p, sizeof(buf) + buf - p, \
+                               p += scnprintf(p, bufsz + buf - p, \
                                               "\t\t%s\n", b);          \
                } while (0)
 
                switch (vhtc->cap & 0x3) {
                case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\tMAX-MPDU-3895\n");
                        break;
                case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\tMAX-MPDU-7991\n");
                        break;
                case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\tMAX-MPDU-11454\n");
                        break;
                default:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\tMAX-MPDU-UNKNOWN\n");
                }
                switch (vhtc->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
                case 0:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\t80Mhz\n");
                        break;
                case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\t160Mhz\n");
                        break;
                case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\t80+80Mhz\n");
                        break;
                default:
-                       p += scnprintf(p, sizeof(buf) + buf - p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "\t\tUNKNOWN-MHZ: 0x%x\n",
                                       (vhtc->cap >> 2) & 0x3);
                }
@@ -588,15 +591,15 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
                PFLAG(SHORT_GI_80, "SHORT-GI-80");
                PFLAG(SHORT_GI_160, "SHORT-GI-160");
                PFLAG(TXSTBC, "TXSTBC");
-               p += scnprintf(p, sizeof(buf) + buf - p,
+               p += scnprintf(p, bufsz + buf - p,
                               "\t\tRXSTBC_%d\n", (vhtc->cap >> 8) & 0x7);
                PFLAG(SU_BEAMFORMER_CAPABLE, "SU-BEAMFORMER-CAPABLE");
                PFLAG(SU_BEAMFORMEE_CAPABLE, "SU-BEAMFORMEE-CAPABLE");
-               p += scnprintf(p, sizeof(buf) + buf - p,
+               p += scnprintf(p, bufsz + buf - p,
                        "\t\tBEAMFORMEE-STS: 0x%x\n",
                        (vhtc->cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK) >>
                        IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
-               p += scnprintf(p, sizeof(buf) + buf - p,
+               p += scnprintf(p, bufsz + buf - p,
                        "\t\tSOUNDING-DIMENSIONS: 0x%x\n",
                        (vhtc->cap & IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
                        >> IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
@@ -604,28 +607,28 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
                PFLAG(MU_BEAMFORMEE_CAPABLE, "MU-BEAMFORMEE-CAPABLE");
                PFLAG(VHT_TXOP_PS, "TXOP-PS");
                PFLAG(HTC_VHT, "HTC-VHT");
-               p += scnprintf(p, sizeof(buf) + buf - p,
+               p += scnprintf(p, bufsz + buf - p,
                        "\t\tMPDU-LENGTH-EXPONENT: 0x%x\n",
                        (vhtc->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
                PFLAG(VHT_LINK_ADAPTATION_VHT_UNSOL_MFB,
                      "LINK-ADAPTATION-VHT-UNSOL-MFB");
-               p += scnprintf(p, sizeof(buf) + buf - p,
+               p += scnprintf(p, bufsz + buf - p,
                        "\t\tLINK-ADAPTATION-VHT-MRQ-MFB: 0x%x\n",
                        (vhtc->cap & IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB) >> 26);
                PFLAG(RX_ANTENNA_PATTERN, "RX-ANTENNA-PATTERN");
                PFLAG(TX_ANTENNA_PATTERN, "TX-ANTENNA-PATTERN");
 
-               p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n",
+               p += scnprintf(p, bufsz + buf - p, "RX MCS: %.4x\n",
                               le16_to_cpu(vhtc->vht_mcs.rx_mcs_map));
                if (vhtc->vht_mcs.rx_highest)
-                       p += scnprintf(p, sizeof(buf)+buf-p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "MCS RX highest: %d Mbps\n",
                                       le16_to_cpu(vhtc->vht_mcs.rx_highest));
-               p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n",
+               p += scnprintf(p, bufsz + buf - p, "TX MCS: %.4x\n",
                               le16_to_cpu(vhtc->vht_mcs.tx_mcs_map));
                if (vhtc->vht_mcs.tx_highest)
-                       p += scnprintf(p, sizeof(buf)+buf-p,
+                       p += scnprintf(p, bufsz + buf - p,
                                       "MCS TX highest: %d Mbps\n",
                                       le16_to_cpu(vhtc->vht_mcs.tx_highest));
 #undef PFLAG