All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-wireless@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: Review of __counted_by in wireless (was Re: [PATCH wireless] wifi: cfg80211: remove scan request n_channels counted_by)
Date: Mon, 21 Jul 2025 11:36:53 -0700	[thread overview]
Message-ID: <202507210907.987737BFD@keescook> (raw)
In-Reply-To: <adb4d011c640aacb2273f81a4ad6e658ea2f52f1.camel@sipsolutions.net>

On Tue, Jul 15, 2025 at 10:24:16AM +0200, Johannes Berg wrote:
> If you feel motivated you could help review and perhaps annotate the
> still existing ones I guess, I'm thinking we should have comments there
> like this perhaps:
> 
> --- a/net/mac80211/parse.c
> +++ b/net/mac80211/parse.c
> @@ -54,8 +54,9 @@ struct ieee80211_elems_parse {
>          * scratch buffer that can be used for various element parsing related
>          * tasks, e.g., element de-fragmentation etc.
>          */
> -       size_t scratch_len;
>         u8 *scratch_pos;
> +       /* __counted_by: scratch_len tracks the allocation and doesn't change */
> +       size_t scratch_len;
>         u8 scratch[] __counted_by(scratch_len);
>  };

This seemed like a good project to compare my manual review against a
review performed by the LLM I've been playing with, and it did okay. It
missed several dynamic cases and I had to prod it into getting them
right, and it couldn't find some allocation patterns on its own. It did
spontaneously find the le/ge counted_by variants, which was nice. Anyway,
here are the results...


Static Counters (28 structures)

Almost all follow the pattern:
	instance = alloc(...N...);
	instance->counter = N;
where counter is set once and never changes. (Some are copying existing
data and never changing the counter variable.)

- struct ath10k_ce_ring (drivers/net/wireless/ath/ath10k/)
      void *per_transfer_context[] __counted_by(nentries)

- struct wmi_set_link_monitor_cmd (drivers/net/wireless/ath/wil6210/)
      s8 rssi_thresholds_list[] __counted_by(rssi_thresholds_list_size)

- struct mt76_rx_tid (drivers/net/wireless/mediatek/mt76/)
      struct sk_buff *reorder_buf[] __counted_by(size)

- struct p54_cal_database (drivers/net/wireless/intersil/p54/)
      u8 data[] __counted_by(len)

- struct libipw_txb (drivers/net/wireless/intel/ipw2x00/)
      struct sk_buff *fragments[] __counted_by(nr_frags)

- struct at76_command (drivers/net/wireless/atmel/)
      u8 data[] __counted_by_le(size)

- struct brcmf_gscan_config (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      struct brcmf_gscan_bucket_config bucket[] __counted_by(count_of_channel_buckets)

- struct brcmf_fw_request (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      struct brcmf_fw_item items[] __counted_by(n_items)

- struct brcmf_fweh_event_map (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      struct brcmf_fweh_event_name items[] __counted_by(n_items)

- struct brcmf_fweh_info (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      int evt_handler[] __counted_by(num_event_codes)

- struct brcmf_fweh_queue_item (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      u8 data[] __counted_by(datalen)

- struct brcmf_eventmsgs_ext (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      u8 mask[] __counted_by(len)

- struct brcmf_mf_params_le (drivers/net/wireless/broadcom/brcm80211/brcmfmac/)
      u8 data[] __counted_by(len)

- struct wcn36xx_hal_ind_msg (drivers/net/wireless/ath/wcn36xx/)
      u8 msg[] __counted_by(msg_len)

- struct iwl_mvm_acs_survey (drivers/net/wireless/intel/iwlwifi/)
      struct iwl_mvm_acs_survey_channel channels[] __counted_by(n_channels)

- struct rtw89_btc_btf_set_slot_table (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_btc_btf_slot tbls[] __counted_by(tbl_num)

- struct rtw89_btc_btf_set_mon_reg_v1 (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_btc_btf_reg regs[] __counted_by(reg_num)

- struct rtw89_btc_btf_set_mon_reg_v7 (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_btc_btf_reg regs[] __counted_by(len)

- struct rtw89_h2c_chinfo (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_h2c_ch elem[] __counted_by(ch_num)

- struct rtw89_h2c_chinfo_be (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_h2c_ch_be elem[] __counted_by(ch_num)

- struct rtw89_h2c_mrc_req_tsf (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_h2c_mrc_req_tsf_info infos[] __counted_by(req_tsf_num)

- struct rtw89_acpi_data (drivers/net/wireless/realtek/rtw89/)
      u8 buf[] __counted_by(len)

- struct rtw89_acpi_policy_6ghz (drivers/net/wireless/realtek/rtw89/)
      char country_list[] __counted_by(country_count)

- struct rtw89_regd_data (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_regulatory_info map[] __counted_by(nr)

- struct cfg80211_cqm_config (net/wireless/)
      s32 rssi_thresholds[] __counted_by(n_rssi_thresholds)

- struct ieee80211_elems_parse (net/mac80211/)
      u8 scratch[] __counted_by(scratch_len)

- struct cfg80211_tid_config (include/net/cfg80211.h)
      struct cfg80211_tid_cfg tid_conf[] __counted_by(n_tid_conf)

- struct cfg80211_acl_data (include/net/cfg80211.h)
      struct mac_address mac_addrs[] __counted_by(n_acl_entries)

- struct cfg80211_coalesce (include/net/cfg80211.h)
      struct cfg80211_coalesce_rules rules[] __counted_by(n_rules)

- struct cfg80211_pmsr_request (include/net/cfg80211.h)
      struct cfg80211_pmsr_request_peer peers[] __counted_by(n_peers)

Dynamic Counters (10 structures):

- struct wmi_start_scan_cmd (drivers/net/wireless/ath/wil6210/)
      struct wmi_start_scan_cmd_channel_list channel_list[] __counted_by(num_channels)

- struct rtw89_vif (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num)

- struct rtw89_sta (drivers/net/wireless/realtek/rtw89/)
      struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num)

- struct cfg80211_scan_request (include/net/cfg80211.h)
      struct ieee80211_channel *channels[] __counted_by(n_channels)

- struct cfg80211_sched_scan_request (include/net/cfg80211.h)
      struct ieee80211_channel *channels[] __counted_by(n_channels)

- struct cfg80211_mbssid_elems (include/net/cfg80211.h)
      struct cfg80211_mbssid_elem elem[] __counted_by(cnt)

- struct cfg80211_rnr_elems (include/net/cfg80211.h)
      struct cfg80211_rnr_elem elem[] __counted_by(cnt)

- struct cfg80211_sar_specs (include/net/cfg80211.h)
      struct cfg80211_sar_sub_specs sub_specs[] __counted_by(num_sub_specs)

- struct cfg80211_wowlan_nd_match (include/net/cfg80211.h)
      u32 channels[] __counted_by(n_channels)

- struct cfg80211_wowlan_nd_info (include/net/cfg80211.h)
      struct cfg80211_wowlan_nd_match *matches[] __counted_by(n_matches)


In the review, I found 3 existing bugs, which I've set as separate
patches now:
https://lore.kernel.org/lkml/20250721181810.work.575-kees@kernel.org/
https://lore.kernel.org/lkml/20250721182521.work.540-kees@kernel.org/
https://lore.kernel.org/lkml/20250721183125.work.183-kees@kernel.org/

At the end of the day, with the above fixes, I think the dynamic cases
appear safe, as they all follow basically the same pattern of allocating
some max size and then filling/filtering the actual population of the
array. (So I think cfg80211_scan_request is correctly used at this point,
but I understand your desire to remove __counted_by on it.)

Do you want me to send patches for the static cases to add comments or
is that too much churn?

-Kees

-- 
Kees Cook

  parent reply	other threads:[~2025-07-21 18:36 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-14 12:21 [PATCH wireless] wifi: cfg80211: remove scan request n_channels counted_by Johannes Berg
2025-07-15  5:04 ` Kees Cook
2025-07-15  8:24   ` Johannes Berg
2025-07-18  0:05     ` Kees Cook
2025-07-18  8:26       ` Johannes Berg
2025-07-21 18:36     ` Kees Cook [this message]
2025-07-21 18:52       ` Review of __counted_by in wireless (was Re: [PATCH wireless] wifi: cfg80211: remove scan request n_channels counted_by) Johannes Berg

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=202507210907.987737BFD@keescook \
    --to=kees@kernel.org \
    --cc=johannes@sipsolutions.net \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.