devlink: Replace strlcat() with seq_buf
Subsystems (3)
PATCH 1/1 devlink: Replace strlcat() with seq_buf
In preparation for removing the strlcat() API[1], replace its uses in __devlink_compat_running_version().
The function accumulates a variable number of version strings into a fixed buffer, which is what seq_buf is for. The seq_buf is anchored at the end of any existing string in the buffer and each version string is appended with a single seq_buf_printf(). The output is unchanged, including under truncation.
---
The patch was tested as follows, on top of net-next:
- x86_64 allmodconfig and allyesconfig builds of net/devlink/dev.o at W=1 produce no warnings.
- A userspace comparison of the old and new construction ran with randomized version lists and buffer contents across all buffer fill levels. The outputs are byte-identical in every case, including on overflow.
- The changed path was exercised in a QEMU guest through the ethtool GDRVINFO ioctl against a netdevsim device, before and after the change, with identical fw_version output.
net/devlink/dev.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/devlink/dev.c +7 -2
@@ -5,6 +5,7 @@*/ #include <linux/device.h> +#include <linux/seq_buf.h> #include <net/genetlink.h> #include <net/sock.h> #include "devl_internal.h"
@@ -1188,8 +1189,10 @@ static void __devlink_compat_running_version(struct devlink *devlink, char *buf, size_t len) {struct devlink_info_req req = {}; +size_t used =strnlen (buf, len);const struct nlattr *nlattr;struct sk_buff *msg; +struct seq_buf sb;int rem, err; msg =nlmsg_new (NLMSG_DEFAULT_SIZE ,GFP_KERNEL );
@@ -1201,6 +1204,8 @@ static void __devlink_compat_running_version(struct devlink *devlink,if (err) goto free_msg; +seq_buf_init (&sb, buf + used, len - used); +nla_for_each_attr_type (nlattr,DEVLINK_ATTR_INFO_VERSION_RUNNING , (void *)msg->data, msg->len, rem) {const struct nlattr *kv;
@@ -1208,8 +1213,8 @@ static void __devlink_compat_running_version(struct devlink *devlink,nla_for_each_nested_type (kv,DEVLINK_ATTR_INFO_VERSION_VALUE , nlattr, rem_kv) { -strlcat (buf,nla_data (kv), len); -strlcat (buf," " , len); +seq_buf_printf (&sb,"%s " , + (const char *)nla_data (kv)); } } free_msg:
Signature · 1 line
2.47.3
Quoted 11 lines · Ian Bridges
In preparation for removing the
strlcat()API[1], replace its uses in__devlink_compat_running_version().The function accumulates a variable number of version strings into a fixed buffer, which is what
seq_bufis for. Theseq_bufis anchored at the end of any existing string in the buffer and each version string is appended with a singleseq_buf_printf(). The output is unchanged, including under truncation.Signed-off-by Ian Bridges <[email protected]>
Quoted 11 lines
---
The patch was tested as follows, on top of net-next:
-x86_64allmodconfig and allyesconfig builds ofnet/devlink/dev.oat W=1 produce no warnings.
- A userspace comparison of the old and new construction ran with randomized version lists and buffer contents across all buffer fill levels. The outputs are byte-identical in every case, including on overflow.
- The changed path was exercised in a QEMU guest through the ethtool GDRVINFO ioctl against a netdevsim device, before and after the change, with identicalfw_versionoutput.
Jakub Kicinski
maintainerQuoted 10 lines · On Fri, 3 Jul 2026 22:49:08 -0500 Ian Bridges wrote:
In preparation for removing the
strlcat()API[1], replace its uses in__devlink_compat_running_version().The function accumulates a variable number of version strings into a fixed buffer, which is what
seq_bufis for. Theseq_bufis anchored at the end of any existing string in the buffer and each version string is appended with a singleseq_buf_printf(). The output is unchanged, including under truncation.
It's fine.