{"id":990,"date":"2024-06-18T11:49:59","date_gmt":"2024-06-18T17:49:59","guid":{"rendered":"https:\/\/embeddedor.com\/blog\/?p=990"},"modified":"2024-07-10T16:19:01","modified_gmt":"2024-07-10T22:19:01","slug":"how-to-use-the-new-counted_by-attribute-in-c-and-linux","status":"publish","type":"post","link":"https:\/\/embeddedor.com\/blog\/2024\/06\/18\/how-to-use-the-new-counted_by-attribute-in-c-and-linux\/","title":{"rendered":"How to use the new counted_by attribute in C (and Linux)"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"234\" src=\"https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59-700x234.png\" alt=\"\" class=\"wp-image-1131\" srcset=\"https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59-700x234.png 700w, https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59-300x100.png 300w, https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59-768x256.png 768w, https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59-800x267.png 800w, https:\/\/embeddedor.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-09-18-59.png 1127w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_68 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title \" >Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/embeddedor.com\/blog\/2024\/06\/18\/how-to-use-the-new-counted_by-attribute-in-c-and-linux\/#The_counted_by_attribute\" title=\"The counted_by attribute\">The counted_by attribute<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/embeddedor.com\/blog\/2024\/06\/18\/how-to-use-the-new-counted_by-attribute-in-c-and-linux\/#The_counted_by_macro\" title=\"The __counted_by() macro\">The __counted_by() macro<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/embeddedor.com\/blog\/2024\/06\/18\/how-to-use-the-new-counted_by-attribute-in-c-and-linux\/#_counted_by_annotations_in_the_kernel\" title=\"__counted_by() annotations in the kernel\">__counted_by() annotations in the kernel<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_counted_by_attribute\"><\/span>The counted_by attribute<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The <code>counted_by<\/code> attribute was introduced in Clang-18 and will soon be available in GCC-15. Its purpose is to associate a <code>flexible-array member<\/code> with a struct member that will hold the number of elements in this array at some point at run-time. This association is critical for enabling runtime bounds checking via the <code>array bounds sanitizer<\/code> and the <code>__builtin_dynamic_object_size()<\/code> built-in function. In user-space, this extra level of security is enabled by <code><a href=\"https:\/\/developers.redhat.com\/articles\/2022\/09\/17\/gccs-new-fortification-level\" target=\"_blank\" rel=\"noreferrer noopener\">-D_FORTIFY_SOURCE=3<\/a><\/code>. Therefore, using this attribute correctly enhances C codebases with runtime bounds-checking coverage on flexible-array members.<\/p>\n\n\n\n<p>Here is an example of a flexible array annotated with this attribute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"c\" class=\"EnlighterJSRAW\">struct bounded_flex_struct {\n        ...\n        size_t count;\n        struct foo flex_array&#91;] __attribute__((__counted_by__(count)));\n};<\/code><\/code><\/pre>\n\n\n\n<p>In the above example, <code>count<\/code> is the struct member that will hold the number of elements of the flexible array at run-time. We will call this struct member the <em>counter<\/em>.<\/p>\n\n\n\n<p>In the Linux kernel, this attribute facilitates bounds-checking coverage through fortified APIs such as the <code>memcpy()<\/code> family of functions, which internally use <code>__builtin_dynamic_object_size()<\/code> (CONFIG_FORTIFY_SOURCE). As well as through the array-bounds sanitizer (CONFIG_UBSAN_BOUNDS).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_counted_by_macro\"><\/span>The __counted_by() macro<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In the kernel we wrap the <code>counted_by<\/code> attribute in the <code>__counted_by()<\/code> macro, as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"c\" class=\"EnlighterJSRAW\">#if __has_attribute(__counted_by__)\n# define __counted_by(member)           __attribute__((__counted_by__(member)))\n#else\n# define __counted_by(member)\n#endif<\/code><\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=c8248faf3ca276ebdf60f003b3e04bf764daba91\" target=\"_blank\" rel=\"noreferrer noopener\">c8248faf3ca27<\/a> (&#8220;Compiler Attributes: counted_by: Adjust name&#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>And with this we have been <a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/log\/?qt=grep&amp;q=__counted_by\" target=\"_blank\" rel=\"noreferrer noopener\">annotating flexible-array members<\/a> across the whole kernel tree over the last year.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"diff\" class=\"EnlighterJSRAW\">diff --git a\/drivers\/net\/ethernet\/chelsio\/cxgb4\/sched.h b\/drivers\/net\/ethernet\/chelsio\/cxgb4\/sched.h\nindex 5f8b871d79afac..6b3c778815f09e 100644\n--- a\/drivers\/net\/ethernet\/chelsio\/cxgb4\/sched.h\n+++ b\/drivers\/net\/ethernet\/chelsio\/cxgb4\/sched.h\n@@ -82,7 +82,7 @@ struct sched_class {\n \n struct sched_table {      \/* per port scheduling table *\/\n \tu8 sched_size;\n-\tstruct sched_class tab&#91;];\n+\tstruct sched_class tab&#91;] __counted_by(sched_size);\n };<\/code><\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=ceba9725fb4554c3cd07d055332272208b8a052f\" target=\"_blank\" rel=\"noreferrer noopener\">ceba9725fb45<\/a> (&#8220;cxgb4: Annotate struct sched_table with &#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>However, as we are about to see, not all <code>__counted_by()<\/code> annotations are always as straightforward as the one above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"_counted_by_annotations_in_the_kernel\"><\/span>__counted_by() annotations in the kernel<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>There are <a href=\"https:\/\/gcc.gnu.org\/pipermail\/gcc-patches\/2024-May\/653123.html\" target=\"_blank\" rel=\"noreferrer noopener\">a number of requirements<\/a> to properly use the <code>counted_by<\/code> attribute. One crucial requirement is that the <em>counter<\/em> must be initialized before the first reference to the flexible-array member. Another requirement is that the array must always contain at least as many elements as indicated by the <em>counter<\/em>. Below you can see an example of a kernel patch addressing these requirements.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"diff\" class=\"EnlighterJSRAW\">diff --git a\/drivers\/net\/wireless\/broadcom\/brcm80211\/brcmfmac\/fweh.c b\/drivers\/net\/wireless\/broadcom\/brcm80211\/brcmfmac\/fweh.c\nindex dac7eb77799bd1..68960ae9898713 100644\n--- a\/drivers\/net\/wireless\/broadcom\/brcm80211\/brcmfmac\/fweh.c\n+++ b\/drivers\/net\/wireless\/broadcom\/brcm80211\/brcmfmac\/fweh.c\n@@ -33,7 +33,7 @@ struct brcmf_fweh_queue_item {\n \tu8 ifaddr&#91;ETH_ALEN];\n \tstruct brcmf_event_msg_be emsg;\n \tu32 datalen;\n-\tu8 data&#91;];\n+\tu8 data&#91;] __counted_by(datalen);\n };\n \n \/*\n@@ -418,17 +418,17 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,\n \t    datalen + sizeof(*event_packet) &gt; packet_len)\n \t\treturn;\n \n-\tevent = kzalloc(sizeof(*event) + datalen, gfp);\n+\tevent = kzalloc(struct_size(event, data, datalen), gfp);\n \tif (!event)\n \t\treturn;\n \n+\tevent-&gt;datalen = datalen;\n \tevent-&gt;code = code;\n \tevent-&gt;ifidx = event_packet-&gt;msg.ifidx;\n \n \t\/* use memcpy to get aligned event message *\/\n \tmemcpy(&amp;event-&gt;emsg, &amp;event_packet-&gt;msg, sizeof(event-&gt;emsg));\n \tmemcpy(event-&gt;data, data, datalen);\n-\tevent-&gt;datalen = datalen;\n \tmemcpy(event-&gt;ifaddr, event_packet-&gt;eth.h_dest, ETH_ALEN);\n \n \tbrcmf_fweh_queue_event(fweh, event);<\/code><\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=62d19b35808816dc2bdf5031e5401230f6a915ba\" target=\"_blank\" rel=\"noreferrer noopener\">62d19b358088<\/a> (&#8220;wifi: brcmfmac: fweh: Add __counted_by&#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>In the patch above, <code>datalen<\/code> is the <em>counter<\/em> for the flexible-array member <code>data<\/code>. Notice how the assignment to the <em>counter<\/em> <code>event-&gt;datalen = datalen<\/code> had to be moved to before calling <code>memcpy(event-&gt;data, data, datalen)<\/code>, this ensures the <em>counter<\/em> is initialized before the first reference to the flexible array. Otherwise, the compiler would complain about trying to write into a flexible array of size zero, due to <code>datalen<\/code> being zeroed out by a previous call to <code>kzalloc()<\/code>. This assignment-after-memcpy has been quite common in the Linux kernel. However, when dealing with <code>counted_by<\/code> annotations, this pattern should be changed. Therefore, we have to be careful when doing these annotations. We should audit all instances of code that reference both the <em>counter<\/em> and the flexible array and ensure they meet the proper requirements.<\/p>\n\n\n\n<p>In the kernel, we&#8217;ve been learning from our mistakes and have fixed some buggy annotations we made in the beginning. Here are a couple of bugfixes to make you aware of these issues:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=6dc445c1905096b2ed4db1a84570375b4e00cc0f\" target=\"_blank\" rel=\"noreferrer noopener\">6dc445c19050<\/a> (&#8220;clk: bcm: rpi: Assign -&gt;num before accessing&#8230;&#8221;)<\/li>\n\n\n\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=9368cdf90f52a68120d039887ccff74ff33b4444\" target=\"_blank\" rel=\"noreferrer noopener\">9368cdf90f52<\/a> (&#8220;clk: bcm: dvp: Assign -&gt;num before accessing&#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>Another common issue is when the <em>counter<\/em> is updated inside a loop. See the patch below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"diff\" class=\"EnlighterJSRAW\">diff --git a\/drivers\/net\/wireless\/ath\/wil6210\/cfg80211.c b\/drivers\/net\/wireless\/ath\/wil6210\/cfg80211.c\nindex 8993028709ecfb..e8f1d30a8d73c5 100644\n--- a\/drivers\/net\/wireless\/ath\/wil6210\/cfg80211.c\n+++ b\/drivers\/net\/wireless\/ath\/wil6210\/cfg80211.c\n@@ -892,10 +892,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,\n \tstruct wil6210_priv *wil = wiphy_to_wil(wiphy);\n \tstruct wireless_dev *wdev = request-&gt;wdev;\n \tstruct wil6210_vif *vif = wdev_to_vif(wil, wdev);\n-\tstruct {\n-\t\tstruct wmi_start_scan_cmd cmd;\n-\t\tu16 chnl&#91;4];\n-\t} __packed cmd;\n+\tDEFINE_FLEX(struct wmi_start_scan_cmd, cmd,\n+\t\t    channel_list, num_channels, 4);\n \tuint i, n;\n \tint rc;\n \n@@ -977,9 +975,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,\n \tvif-&gt;scan_request = request;\n \tmod_timer(&amp;vif-&gt;scan_timer, jiffies + WIL6210_SCAN_TO);\n \n-\tmemset(&amp;cmd, 0, sizeof(cmd));\n-\tcmd.cmd.scan_type = WMI_ACTIVE_SCAN;\n-\tcmd.cmd.num_channels = 0;\n+\tcmd-&gt;scan_type = WMI_ACTIVE_SCAN;\n+\tcmd-&gt;num_channels = 0;\n \tn = min(request-&gt;n_channels, 4U);\n \tfor (i = 0; i &lt; n; i++) {\n \t\tint ch = request-&gt;channels&#91;i]-&gt;hw_value;\n@@ -991,7 +988,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,\n \t\t\tcontinue;\n \t\t}\n \t\t\/* 0-based channel indexes *\/\n-\t\tcmd.cmd.channel_list&#91;cmd.cmd.num_channels++].channel = ch - 1;\n+\t\tcmd-&gt;num_channels++;\n+\t\tcmd-&gt;channel_list&#91;cmd-&gt;num_channels - 1].channel = ch - 1;\n \t\twil_dbg_misc(wil, \"Scan for ch %d  : %d MHz\\n\", ch,\n \t\t\t     request-&gt;channels&#91;i]-&gt;center_freq);\n \t}\n@@ -1007,16 +1005,15 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,\n \tif (rc)\n \t\tgoto out_restore;\n \n-\tif (wil-&gt;discovery_mode &amp;&amp; cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {\n-\t\tcmd.cmd.discovery_mode = 1;\n+\tif (wil-&gt;discovery_mode &amp;&amp; cmd-&gt;scan_type == WMI_ACTIVE_SCAN) {\n+\t\tcmd-&gt;discovery_mode = 1;\n \t\twil_dbg_misc(wil, \"active scan with discovery_mode=1\\n\");\n \t}\n \n \tif (vif-&gt;mid == 0)\n \t\twil-&gt;radio_wdev = wdev;\n \trc = wmi_send(wil, WMI_START_SCAN_CMDID, vif-&gt;mid,\n-\t\t      &amp;cmd, sizeof(cmd.cmd) +\n-\t\t      cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list&#91;0]));\n+\t\t      cmd, struct_size(cmd, channel_list, cmd-&gt;num_channels));\n \n out_restore:\n \tif (rc) {\ndiff --git a\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h b\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h\nindex 71bf2ae27a984f..b47606d9068c8b 100644\n--- a\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h\n+++ b\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h\n@@ -474,7 +474,7 @@ struct wmi_start_scan_cmd {\n \tstruct {\n \t\tu8 channel;\n \t\tu8 reserved;\n-\t} channel_list&#91;];\n+\t} channel_list&#91;] __counted_by(num_channels);\n } __packed;\n \n #define WMI_MAX_PNO_SSID_NUM\t(16)<\/code><\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=34c34c242a1be24cb5da17fe2954c8c71caf815a\" target=\"_blank\" rel=\"noreferrer noopener\">34c34c242a1b<\/a> (&#8220;wifi: wil6210: cfg80211: Use __counted_by&#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>The patch above does a bit more than merely annotating the flexible array with the <code>__counted_by()<\/code> macro, but that&#8217;s material for a future post. For now, let&#8217;s focus on the following excerpt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"diff\" class=\"EnlighterJSRAW\">-\tcmd.cmd.scan_type = WMI_ACTIVE_SCAN;\n-\tcmd.cmd.num_channels = 0;\n+\tcmd-&gt;scan_type = WMI_ACTIVE_SCAN;\n+\tcmd-&gt;num_channels = 0;\n \tn = min(request-&gt;n_channels, 4U);\n \tfor (i = 0; i &lt; n; i++) {\n \t\tint ch = request-&gt;channels&#91;i]-&gt;hw_value;\n@@ -991,7 +988,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,\n \t\t\tcontinue;\n \t\t}\n \t\t\/* 0-based channel indexes *\/\n-\t\tcmd.cmd.channel_list&#91;cmd.cmd.num_channels++].channel = ch - 1;\n+\t\tcmd-&gt;num_channels++;\n+\t\tcmd-&gt;channel_list&#91;cmd-&gt;num_channels - 1].channel = ch - 1;\n \t\twil_dbg_misc(wil, \"Scan for ch %d  : %d MHz\\n\", ch,\n \t\t\t     request-&gt;channels&#91;i]-&gt;center_freq);\n \t}\n ...\n--- a\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h\n+++ b\/drivers\/net\/wireless\/ath\/wil6210\/wmi.h\n@@ -474,7 +474,7 @@ struct wmi_start_scan_cmd {\n \tstruct {\n \t\tu8 channel;\n \t\tu8 reserved;\n-\t} channel_list&#91;];\n+\t} channel_list&#91;] __counted_by(num_channels);\n } __packed;<\/code><\/code><\/pre>\n\n\n\n<p>Notice that in this case, <code>num_channels<\/code> is our <em>counter<\/em>, and it&#8217;s set to zero before the for loop. Inside the for loop, the original code used this variable as an index to access the flexible array, then updated it via a post-increment, all in one line: <code>cmd.cmd.channel_list[cmd.cmd.num_channels++]<\/code>. The issue is that once <code>channel_list<\/code> was annotated with the <code>__counted_by() <\/code>macro, the compiler enforces dynamic array indexing of <code>channel_list<\/code> to stay below <code>num_channels<\/code>. Since <code>num_channels<\/code> holds a value of zero at the moment of the array access, this leads to undefined behavior and may trigger a compiler warning.<\/p>\n\n\n\n<p>As shown in the patch, the solution is to increment <code>num_channels<\/code> before accessing the array, and then access the array through an index adjustment below <code>num_channels<\/code>.<\/p>\n\n\n\n<p>Another option is to avoid using the <em>counter<\/em> as an index for the flexible array altogether. This can be done by using an auxiliary variable instead. See an excerpt of a patch below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code data-enlighter-language=\"diff\" class=\"EnlighterJSRAW\">diff --git a\/include\/net\/bluetooth\/hci.h b\/include\/net\/bluetooth\/hci.h\nindex 38eb7ec86a1a65..21ebd70f3dcc97 100644\n--- a\/include\/net\/bluetooth\/hci.h\n+++ b\/include\/net\/bluetooth\/hci.h\n@@ -2143,7 +2143,7 @@ struct hci_cp_le_set_cig_params {\n \t__le16  c_latency;\n \t__le16  p_latency;\n \t__u8    num_cis;\n-\tstruct hci_cis_params cis&#91;];\n+\tstruct hci_cis_params cis&#91;] __counted_by(num_cis);\n } __packed;\n\n@@ -1722,34 +1717,33 @@ static int hci_le_create_big(struct hci_conn *conn, struct bt_iso_qos *qos)\n \n static int set_cig_params_sync(struct hci_dev *hdev, void *data)\n {\n ...\n\n+\tu8 aux_num_cis = 0;\n \tu8 cis_id;\n ...\n\n \tfor (cis_id = 0x00; cis_id &lt; 0xf0 &amp;&amp;\n-\t     pdu.cp.num_cis &lt; ARRAY_SIZE(pdu.cis); cis_id++) {\n+\t     aux_num_cis &lt; pdu-&gt;num_cis; cis_id++) {\n \t\tstruct hci_cis_params *cis;\n \n \t\tconn = hci_conn_hash_lookup_cis(hdev, NULL, 0, cig_id, cis_id);\n@@ -1758,7 +1752,7 @@ static int set_cig_params_sync(struct hci_dev *hdev, void *data)\n \n \t\tqos = &amp;conn-&gt;iso_qos;\n \n-\t\tcis = &amp;pdu.cis&#91;pdu.cp.num_cis++];\n+\t\tcis = &amp;pdu-&gt;cis&#91;aux_num_cis++];\n \t\tcis-&gt;cis_id = cis_id;\n \t\tcis-&gt;c_sdu  = cpu_to_le16(conn-&gt;iso_qos.ucast.out.sdu);\n \t\tcis-&gt;p_sdu  = cpu_to_le16(conn-&gt;iso_qos.ucast.in.sdu);\n@@ -1769,14 +1763,14 @@ static int set_cig_params_sync(struct hci_dev *hdev, void *data)\n \t\tcis-&gt;c_rtn  = qos-&gt;ucast.out.rtn;\n \t\tcis-&gt;p_rtn  = qos-&gt;ucast.in.rtn;\n \t}\n+\tpdu-&gt;num_cis = aux_num_cis;\n \n ...<\/code><\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git\/commit\/?id=ea9e148c803b24ebbc7a74171f22f42c8fd8d644\" target=\"_blank\" rel=\"noreferrer noopener\">ea9e148c803b<\/a> (&#8220;Bluetooth: hci_conn: Use __counted_by() and&#8230;&#8221;)<\/li>\n<\/ul>\n\n\n\n<p>Again, the entire patch does more than merely annotate the flexible-array member, but let&#8217;s just focus on how <code>aux_num_cis<\/code> is used to access flexible array <code>pdu-&gt;cis[]<\/code>.<\/p>\n\n\n\n<p>In this case, the <em>counter<\/em> is <code>num_cis<\/code>. As in our previous example, originally, the <em>counter<\/em> is used to directly access the flexible array: <code>&amp;pdu.cis[pdu.cp.num_cis++]<\/code>. However, the patch above introduces a new variable <code>aux_num_cis<\/code> to be used instead of the <em>counter<\/em>: <code>&amp;pdu-&gt;cis[aux_num_cis++]<\/code>. The <em>counter<\/em> is then updated after the loop: <code>pdu-&gt;num_cis = aux_num_cis<\/code>.<\/p>\n\n\n\n<p>Both solutions are acceptable, so use whichever is convenient for you. \ud83d\ude42<\/p>\n\n\n\n<p>Here, you can see a recent bugfix for some <a href=\"https:\/\/lore.kernel.org\/linux-hardening\/20240517153332.18271-1-dmantipov@yandex.ru\/\" target=\"_blank\" rel=\"noreferrer noopener\">buggy<\/a> annotations that missed the details discussed above:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[<a href=\"https:\/\/lore.kernel.org\/linux-hardening\/20240619211233.work.355-kees@kernel.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">PATCH<\/a>] wifi: iwlwifi: mvm: Fix <em>_counted_by usage in cfg80211_wowlan_nd<\/em>*<\/li>\n<\/ul>\n\n\n\n<p>In a future post, I&#8217;ll address the issue of annotating flexible arrays of flexible structures. Spoiler alert: <strong>don&#8217;t do it!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The counted_by attribute The counted_by attribute was introduced in Clang-18 and will soon be available in GCC-15. Its purpose is to associate a flexible-array member with a struct member that will hold the number of elements in this array at some point at run-time. This association is critical for enabling runtime bounds checking via the&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,13,9],"tags":[30],"class_list":["post-990","post","type-post","status-publish","format-standard","hentry","category-c","category-kernel-self-protection-project","category-linux-kernel-hardening","tag-planet-korg"],"_links":{"self":[{"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/posts\/990","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/comments?post=990"}],"version-history":[{"count":124,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/posts\/990\/revisions"}],"predecessor-version":[{"id":1155,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/posts\/990\/revisions\/1155"}],"wp:attachment":[{"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/media?parent=990"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/categories?post=990"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/embeddedor.com\/blog\/wp-json\/wp\/v2\/tags?post=990"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}