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

Configure Feed

Select the types of activity you want to include in your feed.

net: ethtool: Adjust exactly ETH_GSTRING_LEN-long stats to use memcpy

Many drivers populate the stats buffer using C-String based APIs (e.g.
ethtool_sprintf() and ethtool_puts()), usually when building up the
list of stats individually (i.e. with a for() loop). This, however,
requires that the source strings be populated in such a way as to have
a terminating NUL byte in the source.

Other drivers populate the stats buffer directly using one big memcpy()
of an entire array of strings. No NUL termination is needed here, as the
bytes are being directly passed through. Yet others will build up the
stats buffer individually, but also use memcpy(). This, too, does not
need NUL termination of the source strings.

However, there are cases where the strings that populate the
source stats strings are exactly ETH_GSTRING_LEN long, and GCC
15's -Wunterminated-string-initialization option complains that the
trailing NUL byte has been truncated. This situation is fine only if the
driver is using the memcpy() approach. If the C-String APIs are used,
the destination string name will have its final byte truncated by the
required trailing NUL byte applied by the C-string API.

For drivers that are already using memcpy() but have initializers that
truncate the NUL terminator, mark their source strings as __nonstring to
silence the GCC warnings.

For drivers that have initializers that truncate the NUL terminator and
are using the C-String APIs, switch to memcpy() to avoid destination
string truncation and mark their source strings as __nonstring to silence
the GCC warnings. (Also introduce ethtool_cpy() as a helper to make this
an easy replacement).

Specifically the following warnings were investigated and addressed:

../drivers/net/ethernet/chelsio/cxgb/cxgb2.c:364:9: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
364 | "TxFramesAbortedDueToXSCollisions",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/ethernet/freescale/enetc/enetc_ethtool.c:165:33: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
165 | { ENETC_PM_R1523X(0), "MAC rx 1523 to max-octet packets" },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/ethernet/freescale/enetc/enetc_ethtool.c:190:33: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
190 | { ENETC_PM_T1523X(0), "MAC tx 1523 to max-octet packets" },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/ethernet/google/gve/gve_ethtool.c:76:9: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
76 | "adminq_dcfg_device_resources_cnt", "adminq_set_driver_parameter_cnt",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c:117:53: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
117 | STMMAC_STAT(ptp_rx_msg_type_pdelay_follow_up),
| ^
../drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c:46:12: note: in definition of macro 'STMMAC_STAT'
46 | { #m, sizeof_field(struct stmmac_extra_stats, m), \
| ^
../drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c:328:24: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
328 | .str = "a_mac_control_frames_transmitted",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c:340:24: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (33 chars into 32 available) [-Wunterminated-string-initialization]
340 | .str = "a_pause_mac_ctrl_frames_received",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Kees Cook <kees@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com> # for mlxsw
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20250416010210.work.904-kees@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kees Cook and committed by
Jakub Kicinski
151e13ec fe733618

+18 -7
+1 -1
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
··· 351 351 adapter->msg_enable = val; 352 352 } 353 353 354 - static const char stats_strings[][ETH_GSTRING_LEN] = { 354 + static const char stats_strings[][ETH_GSTRING_LEN] __nonstring_array = { 355 355 "TxOctetsOK", 356 356 "TxOctetsBad", 357 357 "TxUnicastFramesOK",
+2 -2
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
··· 141 141 142 142 static const struct { 143 143 int reg; 144 - char name[ETH_GSTRING_LEN]; 144 + char name[ETH_GSTRING_LEN] __nonstring; 145 145 } enetc_port_counters[] = { 146 146 { ENETC_PM_REOCT(0), "MAC rx ethernet octets" }, 147 147 { ENETC_PM_RALN(0), "MAC rx alignment errors" }, ··· 264 264 break; 265 265 266 266 for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) 267 - ethtool_puts(&data, enetc_port_counters[i].name); 267 + ethtool_cpy(&data, enetc_port_counters[i].name); 268 268 269 269 break; 270 270 }
+2 -2
drivers/net/ethernet/google/gve/gve_ethtool.c
··· 67 67 "tx_xsk_sent[%u]", "tx_xdp_xmit[%u]", "tx_xdp_xmit_errors[%u]" 68 68 }; 69 69 70 - static const char gve_gstrings_adminq_stats[][ETH_GSTRING_LEN] = { 70 + static const char gve_gstrings_adminq_stats[][ETH_GSTRING_LEN] __nonstring_array = { 71 71 "adminq_prod_cnt", "adminq_cmd_fail", "adminq_timeouts", 72 72 "adminq_describe_device_cnt", "adminq_cfg_device_resources_cnt", 73 73 "adminq_register_page_list_cnt", "adminq_unregister_page_list_cnt", ··· 113 113 i); 114 114 115 115 for (i = 0; i < ARRAY_SIZE(gve_gstrings_adminq_stats); i++) 116 - ethtool_puts(&s, gve_gstrings_adminq_stats[i]); 116 + ethtool_cpy(&s, gve_gstrings_adminq_stats[i]); 117 117 118 118 break; 119 119
+1 -1
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
··· 262 262 } 263 263 264 264 struct mlxsw_sp_port_hw_stats { 265 - char str[ETH_GSTRING_LEN]; 265 + char str[ETH_GSTRING_LEN] __nonstring; 266 266 u64 (*getter)(const char *payload); 267 267 bool cells_bytes; 268 268 };
+1 -1
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
··· 37 37 #define ETHTOOL_DMA_OFFSET 55 38 38 39 39 struct stmmac_stats { 40 - char stat_string[ETH_GSTRING_LEN]; 40 + char stat_string[ETH_GSTRING_LEN] __nonstring; 41 41 int sizeof_stat; 42 42 int stat_offset; 43 43 };
+11
include/linux/ethtool.h
··· 1330 1330 */ 1331 1331 extern void ethtool_puts(u8 **data, const char *str); 1332 1332 1333 + /** 1334 + * ethtool_cpy - Write possibly-not-NUL-terminated string to ethtool string data 1335 + * @data: Pointer to a pointer to the start of string to write into 1336 + * @str: NUL-byte padded char array of size ETH_GSTRING_LEN to copy from 1337 + */ 1338 + #define ethtool_cpy(data, str) do { \ 1339 + BUILD_BUG_ON(sizeof(str) != ETH_GSTRING_LEN); \ 1340 + memcpy(*(data), str, ETH_GSTRING_LEN); \ 1341 + *(data) += ETH_GSTRING_LEN; \ 1342 + } while (0) 1343 + 1333 1344 /* Link mode to forced speed capabilities maps */ 1334 1345 struct ethtool_forced_speed_map { 1335 1346 u32 speed;