* [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers
@ 2026-11-06 7:46 Mariia Nikitash
2026-11-06 10:39 ` Alejandro Colomar
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Mariia Nikitash @ 2026-11-06 7:46 UTC (permalink / raw)
To: hverkuil, mchehab
Cc: linux-media, linux-kernel, linux-hardening, kees, justinstitt,
morbo, Mariia Nikitash
In preparation for removing the deprecated strlcat() API[1],
replace the strscpy() and strlcat() calls used to construct
V4L2 card names in the TEA5777 and TEA575x radio drivers.
seq_buf tracks the current write position and remaining capacity
across appends, avoiding repeated scans of the destination buffer.
This preserves the resulting strings, including truncation behavior.
Link: https://github.com/KSPP/linux/issues/370 [1]
Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com>
---
drivers/media/radio/radio-tea5777.c | 10 ++++++++--
drivers/media/radio/tea575x.c | 10 ++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index fb9de7bbcd19..2b1c7f6ddd60 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
@@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
struct radio_tea5777 *tea = video_drvdata(file);
+ struct seq_buf s;
strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strscpy(v->card, tea->card, sizeof(v->card));
- strlcat(v->card, " TEA5777", sizeof(v->card));
+
+ seq_buf_init(&s, (char *)v->card, sizeof(v->card));
+ seq_buf_puts(&s, (const char *)tea->card);
+ seq_buf_puts(&s, " TEA5777");
+ seq_buf_terminate(&s);
+
strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
return 0;
}
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c
index c37315226c42..e49228eb7c46 100644
--- a/drivers/media/radio/tea575x.c
+++ b/drivers/media/radio/tea575x.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/seq_buf.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <media/v4l2-device.h>
@@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
struct snd_tea575x *tea = video_drvdata(file);
+ struct seq_buf s;
strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strscpy(v->card, tea->card, sizeof(v->card));
- strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
+
+ seq_buf_init(&s, (char *)v->card, sizeof(v->card));
+ seq_buf_puts(&s, (const char *)tea->card);
+ seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757");
+ seq_buf_terminate(&s);
+
strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-06 7:46 [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers Mariia Nikitash @ 2026-11-06 10:39 ` Alejandro Colomar 2026-11-07 4:31 ` Mariia Nikitash 2026-11-08 21:02 ` David Laight 2026-11-10 10:08 ` Hans Verkuil 2 siblings, 1 reply; 14+ messages in thread From: Alejandro Colomar @ 2026-11-06 10:39 UTC (permalink / raw) To: Mariia Nikitash Cc: hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo [-- Attachment #1: Type: text/plain, Size: 3144 bytes --] Hi Mariia, > Date: 2026-11-05 23:46:39-0800 > From: Mariia Nikitash <nikitash.mariiaw@gmail.com> > > In preparation for removing the deprecated strlcat() API[1], > replace the strscpy() and strlcat() calls used to construct > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > seq_buf tracks the current write position and remaining capacity > across appends, avoiding repeated scans of the destination buffer. > This preserves the resulting strings, including truncation behavior. > > Link: https://github.com/KSPP/linux/issues/370 [1] > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> > --- > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > drivers/media/radio/tea575x.c | 10 ++++++++-- > 2 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > index fb9de7bbcd19..2b1c7f6ddd60 100644 > --- a/drivers/media/radio/radio-tea5777.c > +++ b/drivers/media/radio/radio-tea5777.c > @@ -13,6 +13,7 @@ > #include <linux/init.h> > #include <linux/module.h> > #include <linux/sched.h> > +#include <linux/seq_buf.h> > #include <linux/slab.h> > #include <media/v4l2-device.h> > #include <media/v4l2-dev.h> > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct radio_tea5777 *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, " TEA5777", sizeof(v->card)); > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, " TEA5777"); > + seq_buf_terminate(&s); > + Why are the casts needed? Have a lovely day! Alex > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > index c37315226c42..e49228eb7c46 100644 > --- a/drivers/media/radio/tea575x.c > +++ b/drivers/media/radio/tea575x.c > @@ -9,6 +9,7 @@ > #include <linux/module.h> > #include <linux/init.h> > #include <linux/slab.h> > +#include <linux/seq_buf.h> > #include <linux/sched.h> > #include <asm/io.h> > #include <media/v4l2-device.h> > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct snd_tea575x *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > + seq_buf_terminate(&s); > + > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } > -- > 2.43.0 > > -- <https://www.alejandro-colomar.es> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-06 10:39 ` Alejandro Colomar @ 2026-11-07 4:31 ` Mariia Nikitash 2026-11-07 7:39 ` Alejandro Colomar 0 siblings, 1 reply; 14+ messages in thread From: Mariia Nikitash @ 2026-11-07 4:31 UTC (permalink / raw) To: Alejandro Colomar Cc: hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On Fri, Nov 6, 2026 at 2:39 AM Alejandro Colomar <alx+linux-hardening@kernel.org> wrote: > > Hi Mariia, > > > Date: 2026-11-05 23:46:39-0800 > > From: Mariia Nikitash <nikitash.mariiaw@gmail.com> > > > > In preparation for removing the deprecated strlcat() API[1], > > replace the strscpy() and strlcat() calls used to construct > > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > > > seq_buf tracks the current write position and remaining capacity > > across appends, avoiding repeated scans of the destination buffer. > > This preserves the resulting strings, including truncation behavior. > > > > Link: https://github.com/KSPP/linux/issues/370 [1] > > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> > > --- > > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > > drivers/media/radio/tea575x.c | 10 ++++++++-- > > 2 files changed, 16 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > > index fb9de7bbcd19..2b1c7f6ddd60 100644 > > --- a/drivers/media/radio/radio-tea5777.c > > +++ b/drivers/media/radio/radio-tea5777.c > > @@ -13,6 +13,7 @@ > > #include <linux/init.h> > > #include <linux/module.h> > > #include <linux/sched.h> > > +#include <linux/seq_buf.h> > > #include <linux/slab.h> > > #include <media/v4l2-device.h> > > #include <media/v4l2-dev.h> > > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > struct v4l2_capability *v) > > { > > struct radio_tea5777 *tea = video_drvdata(file); > > + struct seq_buf s; > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, " TEA5777"); > > + seq_buf_terminate(&s); > > + > > Why are the casts needed? Hi Alex, I added the casts to make conversions from u8/__u8 to character-pointer types expected by the seq_buf helpers explicit. I'm also considering simplifying these two-part string constructions using scnprintf() instead. Would this approach be preferred? > Have a lovely day! > Alex Thanks, Mariia > > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > > index c37315226c42..e49228eb7c46 100644 > > --- a/drivers/media/radio/tea575x.c > > +++ b/drivers/media/radio/tea575x.c > > @@ -9,6 +9,7 @@ > > #include <linux/module.h> > > #include <linux/init.h> > > #include <linux/slab.h> > > +#include <linux/seq_buf.h> > > #include <linux/sched.h> > > #include <asm/io.h> > > #include <media/v4l2-device.h> > > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > struct v4l2_capability *v) > > { > > struct snd_tea575x *tea = video_drvdata(file); > > + struct seq_buf s; > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > > + seq_buf_terminate(&s); > > + > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > -- > > 2.43.0 > > > > > > -- > <https://www.alejandro-colomar.es> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-07 4:31 ` Mariia Nikitash @ 2026-11-07 7:39 ` Alejandro Colomar 0 siblings, 0 replies; 14+ messages in thread From: Alejandro Colomar @ 2026-11-07 7:39 UTC (permalink / raw) To: Mariia Nikitash Cc: hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo [-- Attachment #1: Type: text/plain, Size: 1482 bytes --] Hi Mariia, > Date: 2026-11-06 20:31:53-0800 > From: Mariia Nikitash <nikitash.mariiaw@gmail.com> > [...] > > > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > > struct v4l2_capability *v) > > > { > > > struct radio_tea5777 *tea = video_drvdata(file); > > > + struct seq_buf s; > > > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > > + > > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > > + seq_buf_puts(&s, (const char *)tea->card); > > > + seq_buf_puts(&s, " TEA5777"); > > > + seq_buf_terminate(&s); > > > + > > > > Why are the casts needed? > > Hi Alex, > > I added the casts to make conversions from u8/__u8 to > character-pointer types expected by the seq_buf helpers explicit. I was surprised that it wasn't needed before. In theory, strscpy() should be expecting the same types, so if it wasn't needed before, it shouldn't be needed now (and conversely, if it is needed now, it would have been needed before). > > I'm also considering simplifying these two-part string constructions > using scnprintf() instead. Would this approach be preferred? I certainly prefer scnprintf() over seq_buf. :) Have a lovely day! Alex -- <https://www.alejandro-colomar.es> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-06 7:46 [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers Mariia Nikitash 2026-11-06 10:39 ` Alejandro Colomar @ 2026-11-08 21:02 ` David Laight 2026-11-08 21:25 ` Alejandro Colomar 2026-11-10 10:08 ` Hans Verkuil 2 siblings, 1 reply; 14+ messages in thread From: David Laight @ 2026-11-08 21:02 UTC (permalink / raw) To: Mariia Nikitash Cc: hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On Thu, 5 Nov 2026 23:46:39 -0800 Mariia Nikitash <nikitash.mariiaw@gmail.com> wrote: > In preparation for removing the deprecated strlcat() API[1], > replace the strscpy() and strlcat() calls used to construct > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > seq_buf tracks the current write position and remaining capacity > across appends, avoiding repeated scans of the destination buffer. > This preserves the resulting strings, including truncation behavior. seq_buf is just OTT. Using to replace a single strcat() is just silly. There is no point doing these patches until there is a sensible alternative. > > Link: https://github.com/KSPP/linux/issues/370 [1] > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> > --- > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > drivers/media/radio/tea575x.c | 10 ++++++++-- > 2 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > index fb9de7bbcd19..2b1c7f6ddd60 100644 > --- a/drivers/media/radio/radio-tea5777.c > +++ b/drivers/media/radio/radio-tea5777.c > @@ -13,6 +13,7 @@ > #include <linux/init.h> > #include <linux/module.h> > #include <linux/sched.h> > +#include <linux/seq_buf.h> > #include <linux/slab.h> > #include <media/v4l2-device.h> > #include <media/v4l2-dev.h> > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct radio_tea5777 *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, " TEA5777", sizeof(v->card)); What is wrong with (and almost OTT): #define TEA5777 " TEA5777" BUILD_BUG_ON(sizeof(TEA5777) <= sizeof(v->card)) len = strscpy(v->card, tea->card, sizeof(v->card) - sizeof(TEA5777) + 1); if (len < 0) goto fail; memcpy(v->card + len, TEA5777, sizeof(TEA5777); What might be useful is a helper that would let you write: len = strscpy(v->card, tea->card); len = strscpy_at(v->card, len, " TEA5777" [, implied_length]); if (len < 0) goto fail; David > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, " TEA5777"); > + seq_buf_terminate(&s); > + > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > index c37315226c42..e49228eb7c46 100644 > --- a/drivers/media/radio/tea575x.c > +++ b/drivers/media/radio/tea575x.c > @@ -9,6 +9,7 @@ > #include <linux/module.h> > #include <linux/init.h> > #include <linux/slab.h> > +#include <linux/seq_buf.h> > #include <linux/sched.h> > #include <asm/io.h> > #include <media/v4l2-device.h> > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct snd_tea575x *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > + seq_buf_terminate(&s); > + > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-08 21:02 ` David Laight @ 2026-11-08 21:25 ` Alejandro Colomar 2026-11-12 17:54 ` Kees Cook 0 siblings, 1 reply; 14+ messages in thread From: Alejandro Colomar @ 2026-11-08 21:25 UTC (permalink / raw) To: David Laight Cc: Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo [-- Attachment #1: Type: text/plain, Size: 3549 bytes --] Hi David, > Date: 2026-11-08 21:02:32+0000 > From: David Laight <david.laight.linux@gmail.com> > [...] > > seq_buf is just OTT. > Using to replace a single strcat() is just silly. > There is no point doing these patches until there is a sensible alternative. Agree. [...] > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > What is wrong with (and almost OTT): > #define TEA5777 " TEA5777" > BUILD_BUG_ON(sizeof(TEA5777) <= sizeof(v->card)) > > len = strscpy(v->card, tea->card, sizeof(v->card) - sizeof(TEA5777) + 1); I can answer this one: bugs (particularly, off by one) are quite prone in such code. From the Authors of strlcat(3), you can look at OpenBSD's manual page: Since it is known how many characters were copied the first time, things can be sped up a bit by using a copy instead of an append: char *dir, *file, pname[PATH_MAX]; size_t n; ... n = strlcpy(pname, dir, sizeof(pname)); if (n >= sizeof(pname)) goto toolong; if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n) goto toolong; However, one may question the validity of such optimizations, as they defeat the whole purpose of strlcpy() and strlcat(). As a matter of fact, the first version of this manual page got it wrong. > if (len < 0) > goto fail; > memcpy(v->card + len, TEA5777, sizeof(TEA5777); > > What might be useful is a helper that would let you write: > len = strscpy(v->card, tea->card); > len = strscpy_at(v->card, len, " TEA5777" [, implied_length]); > if (len < 0) > goto fail; Indeed, as said in other threads, I have such an API: p = v->card; e = ARRAY_END(v->card); p = stpecpy(p, e, tea->card); p = stpecpy(p, e, " TEA5777"); if (p == NULL) goto fail; Linus didn't like my function name. We could indeed call it strscpy_at(). Have a lovely night! Alex > > David > > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, " TEA5777"); > > + seq_buf_terminate(&s); > > + > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > > index c37315226c42..e49228eb7c46 100644 > > --- a/drivers/media/radio/tea575x.c > > +++ b/drivers/media/radio/tea575x.c > > @@ -9,6 +9,7 @@ > > #include <linux/module.h> > > #include <linux/init.h> > > #include <linux/slab.h> > > +#include <linux/seq_buf.h> > > #include <linux/sched.h> > > #include <asm/io.h> > > #include <media/v4l2-device.h> > > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > struct v4l2_capability *v) > > { > > struct snd_tea575x *tea = video_drvdata(file); > > + struct seq_buf s; > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > > + seq_buf_terminate(&s); > > + > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > -- <https://www.alejandro-colomar.es> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-08 21:25 ` Alejandro Colomar @ 2026-11-12 17:54 ` Kees Cook 2026-11-12 19:07 ` David Laight 2026-11-12 22:07 ` Alejandro Colomar 0 siblings, 2 replies; 14+ messages in thread From: Kees Cook @ 2026-11-12 17:54 UTC (permalink / raw) To: Alejandro Colomar Cc: David Laight, Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, justinstitt, morbo On Sun, Nov 08, 2026 at 10:25:35PM +0100, Alejandro Colomar wrote: > Hi David, > > > Date: 2026-11-08 21:02:32+0000 > > From: David Laight <david.laight.linux@gmail.com> > > > [...] > > > > seq_buf is just OTT. > > Using to replace a single strcat() is just silly. > > There is no point doing these patches until there is a sensible alternative. > > Agree. > > [...] > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > > > What is wrong with (and almost OTT): > > #define TEA5777 " TEA5777" > > BUILD_BUG_ON(sizeof(TEA5777) <= sizeof(v->card)) > > > > len = strscpy(v->card, tea->card, sizeof(v->card) - sizeof(TEA5777) + 1); > > I can answer this one: bugs (particularly, off by one) are quite prone > in such code. > > From the Authors of strlcat(3), you can look at OpenBSD's manual page: > > Since it is known how many characters were copied the first > time, things can be sped up a bit by using a copy instead of an > append: > > char *dir, *file, pname[PATH_MAX]; > size_t n; > > ... > > n = strlcpy(pname, dir, sizeof(pname)); > if (n >= sizeof(pname)) > goto toolong; > if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n) > goto toolong; > > However, one may question the validity of such optimizations, as > they defeat the whole purpose of strlcpy() and strlcat(). As a > matter of fact, the first version of this manual page got it > wrong. > > > if (len < 0) > > goto fail; > > memcpy(v->card + len, TEA5777, sizeof(TEA5777); > > > > What might be useful is a helper that would let you write: > > len = strscpy(v->card, tea->card); > > len = strscpy_at(v->card, len, " TEA5777" [, implied_length]); > > if (len < 0) > > goto fail; > > Indeed, as said in other threads, I have such an API: > > p = v->card; > e = ARRAY_END(v->card); > p = stpecpy(p, e, tea->card); > p = stpecpy(p, e, " TEA5777"); > if (p == NULL) > goto fail; > > Linus didn't like my function name. We could indeed call it strscpy_at(). I really just don't want to have bare pointers or lengths being used for any of these manipulations. strlcat needs to go away because it's part of the whole C string API that is confused about array vs pointer and has no sense of handling bounds. Yes, FORTIFY does its best, but between lack of sane bounds and doing a strlen for every action, it has to go. And I'd like _fewer_ APIs (I realize that didn't happen at all for seq_buf, but that our current best direction). And I especially don't want a "len" getting passed around. It needs bounds to be *in* the data type. And that means either true arrays, or internal bounds tracking (like seq_buf), and it shouldn't have "extra work" associated with it (e.g. stpecpy above still has to find the current end of the C string). C strings were a mistake, but here we are. So, for "easy" constructions, sprintf-family, and for complex constructions, seq_buf. And probably the large bit of thought at each place where it is possible, is "how should truncation be communicated?" -Kees -- Kees Cook ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-12 17:54 ` Kees Cook @ 2026-11-12 19:07 ` David Laight 2026-11-12 20:31 ` Kees Cook 2026-11-12 22:07 ` Alejandro Colomar 1 sibling, 1 reply; 14+ messages in thread From: David Laight @ 2026-11-12 19:07 UTC (permalink / raw) To: Kees Cook Cc: Alejandro Colomar, Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, justinstitt, morbo On Thu, 12 Nov 2026 09:54:15 -0800 Kees Cook <kees@kernel.org> wrote: > On Sun, Nov 08, 2026 at 10:25:35PM +0100, Alejandro Colomar wrote: > > Hi David, > > > > > Date: 2026-11-08 21:02:32+0000 > > > From: David Laight <david.laight.linux@gmail.com> > > > > > [...] > > > > > > seq_buf is just OTT. > > > Using to replace a single strcat() is just silly. > > > There is no point doing these patches until there is a sensible alternative. > > > > Agree. > > > > [...] > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > > > > > What is wrong with (and almost OTT): > > > #define TEA5777 " TEA5777" > > > BUILD_BUG_ON(sizeof(TEA5777) <= sizeof(v->card)) > > > > > > len = strscpy(v->card, tea->card, sizeof(v->card) - sizeof(TEA5777) + 1); > > > > I can answer this one: bugs (particularly, off by one) are quite prone > > in such code. > > > > From the Authors of strlcat(3), you can look at OpenBSD's manual page: > > > > Since it is known how many characters were copied the first > > time, things can be sped up a bit by using a copy instead of an > > append: > > > > char *dir, *file, pname[PATH_MAX]; > > size_t n; > > > > ... > > > > n = strlcpy(pname, dir, sizeof(pname)); > > if (n >= sizeof(pname)) > > goto toolong; > > if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n) > > goto toolong; > > > > However, one may question the validity of such optimizations, as > > they defeat the whole purpose of strlcpy() and strlcat(). As a > > matter of fact, the first version of this manual page got it > > wrong. > > > > > if (len < 0) > > > goto fail; > > > memcpy(v->card + len, TEA5777, sizeof(TEA5777); > > > > > > What might be useful is a helper that would let you write: > > > len = strscpy(v->card, tea->card); > > > len = strscpy_at(v->card, len, " TEA5777" [, implied_length]); > > > if (len < 0) > > > goto fail; > > > > Indeed, as said in other threads, I have such an API: > > > > p = v->card; > > e = ARRAY_END(v->card); > > p = stpecpy(p, e, tea->card); > > p = stpecpy(p, e, " TEA5777"); > > if (p == NULL) > > goto fail; That one is playing with pointers. They do make it harder to do any kind of compile-time (or compler helped) sanity checks. > > Linus didn't like my function name. We could indeed call it strscpy_at(). > > I really just don't want to have bare pointers or lengths being used for > any of these manipulations. strlcat needs to go away because it's part > of the whole C string API that is confused about array vs pointer and > has no sense of handling bounds. Yes, FORTIFY does its best, but between > lack of sane bounds and doing a strlen for every action, it has to go. But both snprintf() and seq_buf are far more expensive than doing the strlen(). There is the separate issue that strlcpy() manages to needlessly inline a strnlen() in a lot of the call sites - instead of deferring it to the helper function. David > > And I'd like _fewer_ APIs (I realize that didn't happen at all for > seq_buf, but that our current best direction). And I especially don't > want a "len" getting passed around. It needs bounds to be *in* the data > type. And that means either true arrays, or internal bounds tracking > (like seq_buf), and it shouldn't have "extra work" associated with it > (e.g. stpecpy above still has to find the current end of the C string). > C strings were a mistake, but here we are. > > So, for "easy" constructions, sprintf-family, and for complex > constructions, seq_buf. And probably the large bit of thought at each > place where it is possible, is "how should truncation be communicated?" > > -Kees > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-12 19:07 ` David Laight @ 2026-11-12 20:31 ` Kees Cook 0 siblings, 0 replies; 14+ messages in thread From: Kees Cook @ 2026-11-12 20:31 UTC (permalink / raw) To: David Laight Cc: Alejandro Colomar, Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, justinstitt, morbo On Thu, Nov 12, 2026 at 07:07:02PM +0000, David Laight wrote: > But both snprintf() and seq_buf are far more expensive than doing the > strlen(). > There is the separate issue that strlcpy() manages to needlessly inline a > strnlen() in a lot of the call sites - instead of deferring it to the > helper function. Right, my driving goal here isn't about performance, it's about correctness (as much as possible given our giant codebase). We don't need the most perfect fast implementation if it's too easy to shoot our feet. strlcat() requires an external bounds that has no strict tie to the destination argument, and it has no bounds information at all for the source argument. If we're in fast-path, we have a different set of criteria. And seq_buf was actually designed for that, as it trades storage for speed: it keeps the needed offsets in memory, but that makes it fast for stuff like perf. -- Kees Cook ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-12 17:54 ` Kees Cook 2026-11-12 19:07 ` David Laight @ 2026-11-12 22:07 ` Alejandro Colomar 1 sibling, 0 replies; 14+ messages in thread From: Alejandro Colomar @ 2026-11-12 22:07 UTC (permalink / raw) To: Kees Cook Cc: David Laight, Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, justinstitt, morbo [-- Attachment #1: Type: text/plain, Size: 8756 bytes --] Hi Kees, > Date: 2026-11-12 09:54:15-0800 > From: Kees Cook <kees@kernel.org> > > On Sun, Nov 08, 2026 at 10:25:35PM +0100, Alejandro Colomar wrote: > > Hi David, > > > > > Date: 2026-11-08 21:02:32+0000 > > > From: David Laight <david.laight.linux@gmail.com> > > > [...] > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > > > > > What is wrong with (and almost OTT): > > > #define TEA5777 " TEA5777" > > > BUILD_BUG_ON(sizeof(TEA5777) <= sizeof(v->card)) > > > > > > len = strscpy(v->card, tea->card, sizeof(v->card) - sizeof(TEA5777) + 1); > > > > I can answer this one: bugs (particularly, off by one) are quite prone > > in such code. > > > > From the Authors of strlcat(3), you can look at OpenBSD's manual page: > > > > Since it is known how many characters were copied the first > > time, things can be sped up a bit by using a copy instead of an > > append: > > > > char *dir, *file, pname[PATH_MAX]; > > size_t n; > > > > ... > > > > n = strlcpy(pname, dir, sizeof(pname)); > > if (n >= sizeof(pname)) > > goto toolong; > > if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n) > > goto toolong; > > > > However, one may question the validity of such optimizations, as > > they defeat the whole purpose of strlcpy() and strlcat(). As a > > matter of fact, the first version of this manual page got it > > wrong. > > > > > if (len < 0) > > > goto fail; > > > memcpy(v->card + len, TEA5777, sizeof(TEA5777); > > > > > > What might be useful is a helper that would let you write: > > > len = strscpy(v->card, tea->card); > > > len = strscpy_at(v->card, len, " TEA5777" [, implied_length]); > > > if (len < 0) > > > goto fail; > > > > Indeed, as said in other threads, I have such an API: > > > > p = v->card; > > e = ARRAY_END(v->card); > > p = stpecpy(p, e, tea->card); > > p = stpecpy(p, e, " TEA5777"); > > if (p == NULL) > > goto fail; > > > > Linus didn't like my function name. We could indeed call it strscpy_at(). > > I really just don't want to have bare pointers or lengths being used for > any of these manipulations. > strlcat needs to go away because it's part > of the whole C string API that is confused about array vs pointer and > has no sense of handling bounds. Yes, FORTIFY does its best, but between > lack of sane bounds and doing a strlen for every action, it has to go. I disagree that the whole C string API is confused. In the future, when array parameters become actual arrays (so you can use _Countof() on them), you'll have better language support for that. strlcat(3) indeed has some problems, and has to go, but I would like to not put the whole C string API in that sack. > > And I'd like _fewer_ APIs That's a mistake, IMO. The reason why programmers write bugs using the string APIs is precisely because they try to use few APIs, and try to use them even in places where a more appropriate API would be better. Take for example strncpy(3). It has been abused in so many ways, and we all know the results of that. Now look at what you've done in the kernel: it's been replaced by around a dozen different APIs. Quoting the documentation: The replacements for strncpy() are: - strscpy() when the destination must be NUL-terminated. - strscpy_pad() when the destination must be NUL-terminated and zero-padded (e.g., structs crossing privilege boundaries). - memtostr() for NUL-terminated destinations from non-NUL-terminated fixed-width sources (with the `__nonstring` attribute on the source). - memtostr_pad() for the same, but with zero-padding. - strtomem() for non-NUL-terminated fixed-width destinations, with the `__nonstring` attribute on the destination. - strtomem_pad() for non-NUL-terminated destinations that also need zero-padding. - memcpy_and_pad() for bounded copies from potentially unterminated sources where the destination size is a runtime value. And that is the right thing to do. In parallel, we've developed fundamentally the same functions in shadow-utils. I think that's where research converges to: one API for each different use case. That makes the APIs more descriptive of the action they perform, which let's the programmer better understand the code. They're also way more robust, as you can add many safety checks in the macros that implement them. > (I realize that didn't happen at all for > seq_buf, but that our current best direction). I think the problem in seq_buf is not the amount of functions, but rather the fact that it tries to support both strings and nonstrings at the same time. That's literally repeating the mistake of strncpy(3) with this new type. You may try to patch it with tape, but it's fundamentally flawed, and it will eventually show up (we've already seen the bugs in its implementation). > And I especially don't > want a "len" getting passed around. I partially agree with this. I don't like passing a length, because lengths and sizes are too problematic. However, I would like you to trust me that pointers aren't that bad. We've been using them in shadow-utils extensively, and they're super-comfortable if the functions are well designed. > It needs bounds to be *in* the data > type. And that means either true arrays, Indeed, there's work towards that. I'll show some preview of what may come in future dialects of C. Now, we can have a stpecpy() function: char * stpecpy(char dst[], const char end[0], const char *restrict src) { ssize_t dlen; if (dst == NULL) return NULL; dlen = strscpy(dst, src, end - dst); if (dlen < 0) return NULL; return dst + dlen; } In GCC, you can improve the prototype: char * stpecpy(char dst[], const char end[]; char dst[dst?end-dst:0], const char end[0], const char *restrict src) With a patch I'm working on for GCC (it might land in GCC 17 if we're lucky, but it's more likely to end up in GCC 18), we'll be able to use _Countof() on array parameters, so we could use the two-arg version of strscpy() for implementing this: char * stpecpy(char dst[], const char end[]; char dst[dst?end-dst:0], const char end[0], const char *restrict src) { ssize_t dlen; if (dst == NULL) return NULL; dlen = strscpy(dst, src); if (dlen < 0) return NULL; return dst + dlen; } And in a few years, we might end up having slices in C, which would allow having the same functionality with just 2 arguments: char stpecpy(char dst[:], const char *restrict src)[:] { ssize_t dlen; if (dst == NULL) return NULL; dlen = strscpy(dst, src); if (dlen == -1) return NULL; return dst + dlen; } So, there's a bright future for traditional C string APIs. And it's not too far away. > or internal bounds tracking > (like seq_buf), I believe that's going to bite eventually, and it will also be difficult to return to the simplicity of the C string API once we have these few features that make it safe. > and it shouldn't have "extra work" associated with it > (e.g. stpecpy above still has to find the current end of the C string). No! stpecpy() is really the same as strscpy(9). It's *not* a cat function. See the implementation(s) above: there's no strlen(3) in it. The closest relative to it is stpcpy(3) from POSIX, which is really just strcpy(3), but returning a pointer that encodes the position. That was designed precisely to solve the performance issues of strcat(3). > C strings were a mistake, but here we are. Trust me: it's not. The problems with C strings are, as you said above, the limited support for array parameters in the language. But it's not too difficult to solve that problem. And once that is solved, magically the traditional string APIs become much better than the structure types, by being at least as safe, but much simpler. So, I'd like you to trust me to add stpecpy() --whatever we end up calling it--, and perhaps the sprintf() variant of it, and see how it really improves the code. In the coming years, when we solve the issues with array parameters in the language, they will become even better. > So, for "easy" constructions, sprintf-family, and for complex > constructions, seq_buf. And probably the large bit of thought at each > place where it is possible, is "how should truncation be communicated?" > > -Kees Have a lovely night! Alex -- <https://www.alejandro-colomar.es> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-06 7:46 [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers Mariia Nikitash 2026-11-06 10:39 ` Alejandro Colomar 2026-11-08 21:02 ` David Laight @ 2026-11-10 10:08 ` Hans Verkuil 2026-11-10 13:54 ` David Laight 2 siblings, 1 reply; 14+ messages in thread From: Hans Verkuil @ 2026-11-10 10:08 UTC (permalink / raw) To: Mariia Nikitash, hverkuil, mchehab Cc: linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On 06/11/2026 08:46, Mariia Nikitash wrote: > In preparation for removing the deprecated strlcat() API[1], > replace the strscpy() and strlcat() calls used to construct > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > seq_buf tracks the current write position and remaining capacity > across appends, avoiding repeated scans of the destination buffer. > This preserves the resulting strings, including truncation behavior. > > Link: https://github.com/KSPP/linux/issues/370 [1] > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> Nacked-by: Hans Verkuil <hverkuil+cisco@kernel.org> This is silly. Just use scnprintf(). Regards, Hans > --- > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > drivers/media/radio/tea575x.c | 10 ++++++++-- > 2 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > index fb9de7bbcd19..2b1c7f6ddd60 100644 > --- a/drivers/media/radio/radio-tea5777.c > +++ b/drivers/media/radio/radio-tea5777.c > @@ -13,6 +13,7 @@ > #include <linux/init.h> > #include <linux/module.h> > #include <linux/sched.h> > +#include <linux/seq_buf.h> > #include <linux/slab.h> > #include <media/v4l2-device.h> > #include <media/v4l2-dev.h> > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct radio_tea5777 *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, " TEA5777", sizeof(v->card)); > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, " TEA5777"); > + seq_buf_terminate(&s); > + > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > index c37315226c42..e49228eb7c46 100644 > --- a/drivers/media/radio/tea575x.c > +++ b/drivers/media/radio/tea575x.c > @@ -9,6 +9,7 @@ > #include <linux/module.h> > #include <linux/init.h> > #include <linux/slab.h> > +#include <linux/seq_buf.h> > #include <linux/sched.h> > #include <asm/io.h> > #include <media/v4l2-device.h> > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > struct v4l2_capability *v) > { > struct snd_tea575x *tea = video_drvdata(file); > + struct seq_buf s; > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > - strscpy(v->card, tea->card, sizeof(v->card)); > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > + > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > + seq_buf_puts(&s, (const char *)tea->card); > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > + seq_buf_terminate(&s); > + > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > return 0; > } ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-10 10:08 ` Hans Verkuil @ 2026-11-10 13:54 ` David Laight 2026-11-10 18:41 ` Mariia Nikitash 0 siblings, 1 reply; 14+ messages in thread From: David Laight @ 2026-11-10 13:54 UTC (permalink / raw) To: Hans Verkuil Cc: Mariia Nikitash, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On Tue, 10 Nov 2026 11:08:30 +0100 Hans Verkuil <hverkuil+cisco@kernel.org> wrote: > On 06/11/2026 08:46, Mariia Nikitash wrote: > > In preparation for removing the deprecated strlcat() API[1], > > replace the strscpy() and strlcat() calls used to construct > > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > > > seq_buf tracks the current write position and remaining capacity > > across appends, avoiding repeated scans of the destination buffer. > > This preserves the resulting strings, including truncation behavior. > > > > Link: https://github.com/KSPP/linux/issues/370 [1] > > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> > > Nacked-by: Hans Verkuil <hverkuil+cisco@kernel.org> > > This is silly. Just use scnprintf(). Or wait for someone to add a call that just does what is needed. In this case the first stscpy() returns the length (and it is often known). So you could have: len = strscpy(buf, tea->card[, buflen]); len = strscpy_at(buf, len, " TEA5777"[, buflen]); or: len = strscat(buf, buflen, tea->card, " TEA5777", ....); or some variant that will do a strnlen(buf, buflen) to get the offset. But it really is best to leave the strlcat() calls in there for now. David > > Regards, > > Hans > > > --- > > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > > drivers/media/radio/tea575x.c | 10 ++++++++-- > > 2 files changed, 16 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > > index fb9de7bbcd19..2b1c7f6ddd60 100644 > > --- a/drivers/media/radio/radio-tea5777.c > > +++ b/drivers/media/radio/radio-tea5777.c > > @@ -13,6 +13,7 @@ > > #include <linux/init.h> > > #include <linux/module.h> > > #include <linux/sched.h> > > +#include <linux/seq_buf.h> > > #include <linux/slab.h> > > #include <media/v4l2-device.h> > > #include <media/v4l2-dev.h> > > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > struct v4l2_capability *v) > > { > > struct radio_tea5777 *tea = video_drvdata(file); > > + struct seq_buf s; > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, " TEA5777"); > > + seq_buf_terminate(&s); > > + > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > > index c37315226c42..e49228eb7c46 100644 > > --- a/drivers/media/radio/tea575x.c > > +++ b/drivers/media/radio/tea575x.c > > @@ -9,6 +9,7 @@ > > #include <linux/module.h> > > #include <linux/init.h> > > #include <linux/slab.h> > > +#include <linux/seq_buf.h> > > #include <linux/sched.h> > > #include <asm/io.h> > > #include <media/v4l2-device.h> > > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > struct v4l2_capability *v) > > { > > struct snd_tea575x *tea = video_drvdata(file); > > + struct seq_buf s; > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > - strscpy(v->card, tea->card, sizeof(v->card)); > > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > > + > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > + seq_buf_puts(&s, (const char *)tea->card); > > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > > + seq_buf_terminate(&s); > > + > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > return 0; > > } > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-10 13:54 ` David Laight @ 2026-11-10 18:41 ` Mariia Nikitash 2026-11-10 20:58 ` David Laight 0 siblings, 1 reply; 14+ messages in thread From: Mariia Nikitash @ 2026-11-10 18:41 UTC (permalink / raw) To: David Laight Cc: Hans Verkuil, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On Tue, Nov 10, 2026 at 5:54 AM David Laight <david.laight.linux@gmail.com> wrote: > > On Tue, 10 Nov 2026 11:08:30 +0100 > Hans Verkuil <hverkuil+cisco@kernel.org> wrote: > > > On 06/11/2026 08:46, Mariia Nikitash wrote: > > > In preparation for removing the deprecated strlcat() API[1], > > > replace the strscpy() and strlcat() calls used to construct > > > V4L2 card names in the TEA5777 and TEA575x radio drivers. > > > > > > seq_buf tracks the current write position and remaining capacity > > > across appends, avoiding repeated scans of the destination buffer. > > > This preserves the resulting strings, including truncation behavior. > > > > > > Link: https://github.com/KSPP/linux/issues/370 [1] > > > Signed-off-by: Mariia Nikitash <nikitash.mariiaw@gmail.com> > > > > Nacked-by: Hans Verkuil <hverkuil+cisco@kernel.org> > > Hi, > > This is silly. Just use scnprintf(). > > Or wait for someone to add a call that just does what is needed. > In this case the first stscpy() returns the length (and it is often > known). > So you could have: > len = strscpy(buf, tea->card[, buflen]); > len = strscpy_at(buf, len, " TEA5777"[, buflen]); > or: > len = strscat(buf, buflen, tea->card, " TEA5777", ....); > or some variant that will do a strnlen(buf, buflen) to get the offset. > > But it really is best to leave the strlcat() calls in there for now. > Thanks Hans and David for the feedback. I agree that seq_buf is too complex here. I'll look into using scnprintf() as Hans suggested. David, I also see your point about leaving strlcat() in place until a more suitable append helper is available. I'll revisit the approach before deciding on a v2. Best, Mariia > David > > > > > Regards, > > > > Hans > > > > > --- > > > drivers/media/radio/radio-tea5777.c | 10 ++++++++-- > > > drivers/media/radio/tea575x.c | 10 ++++++++-- > > > 2 files changed, 16 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c > > > index fb9de7bbcd19..2b1c7f6ddd60 100644 > > > --- a/drivers/media/radio/radio-tea5777.c > > > +++ b/drivers/media/radio/radio-tea5777.c > > > @@ -13,6 +13,7 @@ > > > #include <linux/init.h> > > > #include <linux/module.h> > > > #include <linux/sched.h> > > > +#include <linux/seq_buf.h> > > > #include <linux/slab.h> > > > #include <media/v4l2-device.h> > > > #include <media/v4l2-dev.h> > > > @@ -255,10 +256,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > > struct v4l2_capability *v) > > > { > > > struct radio_tea5777 *tea = video_drvdata(file); > > > + struct seq_buf s; > > > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > - strlcat(v->card, " TEA5777", sizeof(v->card)); > > > + > > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > > + seq_buf_puts(&s, (const char *)tea->card); > > > + seq_buf_puts(&s, " TEA5777"); > > > + seq_buf_terminate(&s); > > > + > > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > > return 0; > > > } > > > diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c > > > index c37315226c42..e49228eb7c46 100644 > > > --- a/drivers/media/radio/tea575x.c > > > +++ b/drivers/media/radio/tea575x.c > > > @@ -9,6 +9,7 @@ > > > #include <linux/module.h> > > > #include <linux/init.h> > > > #include <linux/slab.h> > > > +#include <linux/seq_buf.h> > > > #include <linux/sched.h> > > > #include <asm/io.h> > > > #include <media/v4l2-device.h> > > > @@ -221,10 +222,15 @@ static int vidioc_querycap(struct file *file, void *priv, > > > struct v4l2_capability *v) > > > { > > > struct snd_tea575x *tea = video_drvdata(file); > > > + struct seq_buf s; > > > > > > strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); > > > - strscpy(v->card, tea->card, sizeof(v->card)); > > > - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); > > > + > > > + seq_buf_init(&s, (char *)v->card, sizeof(v->card)); > > > + seq_buf_puts(&s, (const char *)tea->card); > > > + seq_buf_puts(&s, tea->tea5759 ? " TEA5759" : " TEA5757"); > > > + seq_buf_terminate(&s); > > > + > > > strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); > > > return 0; > > > } > > > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers 2026-11-10 18:41 ` Mariia Nikitash @ 2026-11-10 20:58 ` David Laight 0 siblings, 0 replies; 14+ messages in thread From: David Laight @ 2026-11-10 20:58 UTC (permalink / raw) To: Mariia Nikitash Cc: Hans Verkuil, hverkuil, mchehab, linux-media, linux-kernel, linux-hardening, kees, justinstitt, morbo On Tue, 10 Nov 2026 10:41:06 -0800 Mariia Nikitash <nikitash.mariiaw@gmail.com> wrote: > David, I also see your point about leaving strlcat() in place until a > more suitable append helper is available. I'll revisit the approach > before deciding on a v2. I really don't understand why strlcat() got marked deprecated without a suitable replacement. The performance of any form of strcpy(t + strlen(t), s) is horrid. The only extra issue strlcat() has is to do with it doing strlen(s) to generated the return value that most code doesn't want (and in pretty much all reasonable cases is actually fine). David ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-11-12 22:07 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-06 7:46 [PATCH] media: radio: Replace strlcat() with seq_buf in TEA drivers Mariia Nikitash 2026-11-06 10:39 ` Alejandro Colomar 2026-11-07 4:31 ` Mariia Nikitash 2026-11-07 7:39 ` Alejandro Colomar 2026-11-08 21:02 ` David Laight 2026-11-08 21:25 ` Alejandro Colomar 2026-11-12 17:54 ` Kees Cook 2026-11-12 19:07 ` David Laight 2026-11-12 20:31 ` Kees Cook 2026-11-12 22:07 ` Alejandro Colomar 2026-11-10 10:08 ` Hans Verkuil 2026-11-10 13:54 ` David Laight 2026-11-10 18:41 ` Mariia Nikitash 2026-11-10 20:58 ` David Laight
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox