seq_buf: Add seq_buf_strlen()
Subsystems (6)
cover seq_buf: Add seq_buf_strlen()
Hi,
While working on seq_buf conversions, we found there was a need for seq_buf_strlen() (since calling strlen(seq_buf_str()) would be a waste of time: seq_buf already knows the length). And while implementing that, I found a bunch of other related things that needed fixing. This is that series, with tests for each fix.
-Kees
Kees Cook (7):
seq_buf: Do not pop from an overflowed seq_buf
seq_buf: Copy what fits when seq_buf_puts() and seq_buf_putmem()
overflow
seq_buf: Clear what a writer did not claim when a seq_buf overflows
seq_buf: Add seq_buf_strlen()
seq_buf: Use seq_buf_strlen() for the string end in
seq_buf_do_printk()
powerpc/papr_scm: Return the string length from the sysfs show
functions
nvdimm: ndtest: Return the string length from flags_show()
include/linux/seq_buf.h | 69 ++++- include/linux/trace_seq.h | 4 +- arch/powerpc/platforms/pseries/papr_scm.c | 4 +- lib/seq_buf.c | 25 +- lib/tests/seq_buf_kunit.c | 290 +++++++++++++++++++++- tools/testing/nvdimm/test/ndtest.c | 2 +- 6 files changed, 377 insertions(+), 17 deletions(-)
Signature · 1 line
2.34.1
PATCH 1/7 seq_buf: Do not pop from an overflowed seq_buf
When a seq_buf has overflowed, its len is size + 1, so seq_buf_pop() decrements len to size and reads buffer[size], one byte past the end of the buffer. It also leaves len equal to size, which no longer counts as overflowed, so a truncated seq_buf then looks like a complete, full one.
An overflowed seq_buf has no last character to pop: the length of what was written has been lost, and the last byte of the buffer may be the NUL written by vsnprintf() or bytes that were never committed. Return -1 for an overflowed seq_buf, as for an empty one, and leave it overflowed, as the rest of the seq_buf API does until seq_buf_clear() or seq_buf_init().
The current callers do not reach this, e.g. trace_syscalls only calls trace_seq_pop() when the trace_seq it pops from has not overflowed, and kernel/bpf/diagnostics.c sets the length from strnlen() before popping.
Add tests for the pop corner cases.
Tests passed under qemu on ARCH=x86_64 with GCC 16.2.0 and CONFIG_KASAN=y, and on big-endian ARCH=s390 with GCC s390x-linux-gnu 16.1.0.
---
Cc: Steven Rostedt <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Cc: "Mickaël Salaün" <[email protected]>
Cc: "Günther Noack" <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: "Matthew Wilcox (Oracle)" <[email protected]>
Cc: Shuvam Pandey <[email protected]>
Cc: David Gow <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
--- include/linux/seq_buf.h | 4 ++-- include/linux/trace_seq.h | 4 +++- lib/tests/seq_buf_kunit.c | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-)
include/linux/seq_buf.h +2 -2
@@ -155,11 +155,11 @@ static inline void seq_buf_commit(struct seq_buf *s, int num)* * Removes the last written character to the seq_buf @s. * -* Returns the last character or -1 if it is empty. +* Returns the last character, or -1 if @s is empty or has overflowed. */ static inline int seq_buf_pop (struct seq_buf *s) { -if (!s->len) +if (!s->len ||seq_buf_has_overflowed (s))return -1 ; s->len--;
include/linux/trace_seq.h +3 -1
@@ -86,7 +86,9 @@ static inline bool trace_seq_has_overflowed(struct trace_seq *s)* * Removes the last written character to the trace_seq @s. * -* Returns the last character or -1 if it is empty. +* Returns the last character, or -1 if @s is empty or its buffer has +* overflowed. Note that a @s that is full, but has not overflowed, still +* pops. */ static inline int trace_seq_pop (struct trace_seq *s) {
lib/tests/seq_buf_kunit.c +42 -0
54 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH 2/7 seq_buf: Copy what fits when seq_buf_puts() and seq_buf_putmem() overflow
In reply to Kees CookWhen seq_buf_puts() or seq_buf_putmem() is given more than fits, it copies nothing and only marks the seq_buf as overflowed. If seq_buf_str() is used, it will terminate the buffer in its last byte, so every byte between the end of the data and the end of the buffer becomes part of the string, though the seq_buf never wrote them.
seq_buf_printf() does not have this problem, because vsnprintf() writes as much of the output as fits, followed by a NUL. Repeat this behavior in seq_buf_puts(), using strscpy(), and in seq_buf_putmem(), which also covers seq_buf_putmem_hex(). seq_buf_putc() needs no change, as it can only overflow when the buffer is already full.
Each writer now records the buffer as full once it has copied what fits, so that what it wrote can be told apart from bytes nothing touched.
Update seq_buf_putmem_hex_overflow_test, which expected a hex group that did not fit whole to be left out entirely, and add tests that overflow seq_buf_puts() and seq_buf_putmem_hex() with stale bytes in the buffer.
Tests passed under qemu on ARCH=x86_64 with GCC 16.2.0 and CONFIG_KASAN=y, and on big-endian ARCH=s390 with GCC s390x-linux-gnu 16.1.0.
---
Cc: Andrew Morton <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: "Matthew Wilcox (Oracle)" <[email protected]>
Cc: Shuvam Pandey <[email protected]>
Cc: David Gow <[email protected]>
--- include/linux/seq_buf.h | 6 +++++ lib/seq_buf.c | 16 +++++++++++-- lib/tests/seq_buf_kunit.c | 47 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 4 deletions(-)
include/linux/seq_buf.h +6 -0
@@ -55,6 +55,12 @@ seq_buf_has_overflowed(struct seq_buf *s)return s->len > s->size; } +/* +* Mark @s as overflowed, which discards the length of what it holds. The +* bytes up to its last one are the string from then on, as that is where +* seq_buf_str() terminates it, so a caller that could not fill the buffer +* has to NUL them itself before calling this. +*/ static inline void seq_buf_set_overflow (struct seq_buf *s) {
lib/seq_buf.c +14 -2
@@ -175,7 +175,9 @@ int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)* @s: seq_buf descriptor * @str: simple string to record * -* Copy a simple string into the sequence buffer. +* Copy a simple string into the sequence buffer. If @str does not fit, +* as much of it as fits is copied, followed by a null byte, as +* seq_buf_printf() does. * * Returns: zero on success, -1 on overflow. */
@@ -194,6 +196,11 @@ int seq_buf_puts(struct seq_buf *s, const char *str) s->len += len -1 ;return 0 ; } +/* Copy what fits, so the buffer never holds stale bytes */ +if (s->len < s->size) { +strscpy (s->buffer + s->len, str, s->size - s->len); + s->len = s->size; + }seq_buf_set_overflow (s);return -1 ; }
@@ -229,7 +236,7 @@ EXPORT_SYMBOL_GPL(seq_buf_putc);* * There may be cases where raw memory needs to be written into the * buffer and a strcpy() would not work. Using this function allows -* for such cases. +* for such cases. If @mem does not fit, as much of it as fits is copied. * * Returns: zero on success, -1 on overflow. */
@@ -242,6 +249,11 @@ int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len) s->len += len;return 0 ; } +/* Copy what fits, so the buffer never holds stale bytes */ +if (s->len < s->size) { +memcpy (s->buffer + s->len, mem, s->size - s->len); + s->len = s->size; + }seq_buf_set_overflow (s);return -1 ; }
lib/tests/seq_buf_kunit.c +45 -2
66 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH 3/7 seq_buf: Clear what a writer did not claim when a seq_buf overflows
In reply to Kees CookUsing seq_buf_set_overflow() would leave the bytes between "len" and "size" untouched, so if seq_buf_str() is used on an overflowed seq_buf, those bytes may be exposed. For any paths that don't claim partially written bytes, by setting "len = size" before calling seq_buf_set_overflow(), wipe the unclaimed bytes. The seq_buf_puts() and related APIs already claim those bytes now, so only the unclaimed cases remain. A specific example of this was seq_buf_path() which uses d_path() and would write to the tail before discovering it was out of space, and would correctly mark a seq_buf as overflowed, but the path fragment would be left over.
Clear from len to the end of the buffer in seq_buf_set_overflow(), which every overflow goes through, including seq_buf_commit() with a negative count.
Add a test that fills a seq_buf, leaves it too little room for a path, and checks that nothing of the path is left in the buffer. The tests run before anything writable is mounted, so it takes its file from shmem.
Tests passed under qemu on ARCH=x86_64 with GCC 16.2.0 and CONFIG_KASAN=y, and on big-endian ARCH=s390 with GCC s390x-linux-gnu 16.1.0.
---
Cc: Andrew Morton <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Shuvam Pandey <[email protected]>
Cc: David Gow <[email protected]>
Cc: Jiri Kosina <[email protected]>
Cc: Petr Mladek <[email protected]>
--- include/linux/seq_buf.h | 8 +++++-- lib/seq_buf.c | 4 ++++ lib/tests/seq_buf_kunit.c | 44 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-)
include/linux/seq_buf.h +6 -2
@@ -5,6 +5,7 @@#include <linux/bug.h> #include <linux/minmax.h> #include <linux/seq_file.h> +#include <linux/string.h> #include <linux/types.h> /*
@@ -58,12 +59,15 @@ seq_buf_has_overflowed(struct seq_buf *s)/* * Mark @s as overflowed, which discards the length of what it holds. The * bytes up to its last one are the string from then on, as that is where -* seq_buf_str() terminates it, so a caller that could not fill the buffer -* has to NUL them itself before calling this. +* seq_buf_str() terminates it, so clear whatever was not written: a writer +* sets len to how much it filled, and anything past that was never adopted. */ static inline void seq_buf_set_overflow (struct seq_buf *s) { +if (s->len < s->size) +memset (s->buffer + s->len,0 , s->size - s->len); + s->len = s->size +1 ; }
lib/seq_buf.c +4 -0
@@ -76,6 +76,8 @@ int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args) s->len += len;return 0 ; } +/* vsnprintf() wrote as much as fits, so none of it is stale */ + s->len = s->size; }seq_buf_set_overflow (s);return -1 ;
@@ -164,6 +166,8 @@ int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary) s->len += ret;return 0 ; } +/* bstr_printf() wrote as much as fits, so none of it is stale */ + s->len = s->size; }seq_buf_set_overflow (s);return -1 ;
lib/tests/seq_buf_kunit.c +44 -0
63 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH 4/7 seq_buf: Add seq_buf_strlen()
In reply to Kees Cookseq_buf_used() is not the length of the string in a seq_buf. Once the buffer is full or has overflowed it returns the buffer size, which counts the byte that seq_buf_str() replaces with the NUL, so a caller that needs the string and its length has to call seq_buf_str() and then walk the string with strlen().
Move the termination out of seq_buf_str() into a helper that returns where it put the NUL, and add seq_buf_strlen(), which terminates the buffer in the same way and returns that offset.
Add tests comparing seq_buf_strlen() against strlen() of seq_buf_str() for empty, appended, truncated, exactly full, and overflowed buffers, and checking that seq_buf_strlen() alone terminates a full buffer.
Tests passed under qemu on ARCH=x86_64 with GCC 16.2.0 and CONFIG_KASAN=y, and on big-endian ARCH=s390 with GCC s390x-linux-gnu 16.1.0.
---
Cc: Steven Rostedt <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: "Matthew Wilcox (Oracle)" <[email protected]>
Cc: Shuvam Pandey <[email protected]>
Cc: David Gow <[email protected]>
Cc: Andrew Morton <[email protected]>
--- include/linux/seq_buf.h | 55 ++++++++++++++++++++--- lib/tests/seq_buf_kunit.c | 94 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 5 deletions(-)
include/linux/seq_buf.h +50 -5
@@ -89,6 +89,27 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)return min (s->len, s->size); } +/* +* NUL-terminate the buffer in @s: directly after the data when there is +* room for it, otherwise in the last byte of the buffer. @s->size must not +* be zero. +* +* Returns: the offset of the NUL. +*/ +static inline size_t __seq_buf_terminate (struct seq_buf *s) +{ +size_t end; + +if (seq_buf_buffer_left (s)) + end = s->len; +else + end = s->size -1 ; + + s->buffer[end] =0 ; + +return end; +} +/** * seq_buf_str - get NUL-terminated C string from seq_buf * @s: the seq_buf handle
@@ -98,7 +119,9 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)* * Note, if this is called when the buffer has overflowed, then * the last byte of the buffer is zeroed, and the len will still -* point passed it. +* point passed it. The same happens when the buffer is exactly +* full: the NUL takes the place of the last byte written, which is +* lost, though seq_buf_used() still counts it. * * After this function is called, s->buffer is safe to use * in string operations.
@@ -110,14 +133,36 @@ static inline const char *seq_buf_str(struct seq_buf *s)if (WARN_ON (s->size ==0 ))return "" ; -if (seq_buf_buffer_left (s)) - s->buffer[s->len] =0 ; -else - s->buffer[s->size -1 ] =0 ; +__seq_buf_terminate (s);return s->buffer; } +/** +* seq_buf_strlen - get the length of the NUL-terminated C string in seq_buf +* @s: the seq_buf handle +* +* This makes sure that the buffer in @s is NUL-terminated, exactly as +* seq_buf_str() does, and returns the length of the resulting string +* without walking it. Unlike seq_buf_used(), this does not count the byte +* given up to the NUL when the buffer is full or has overflowed. When the +* buffer is exactly full, that byte is the last one written, and calling +* either function loses it. +* +* After this function is called, s->buffer is safe to use +* in string operations. +* +* Returns: the offset of the NUL in @s->buffer, which is the length of the +* string unless the data written to @s itself contains a NUL. +*/ +static inline size_t seq_buf_strlen (struct seq_buf *s) +{ +if (WARN_ON (s->size ==0 )) +return 0 ; + +return __seq_buf_terminate (s); +} +/** * seq_buf_get_buf - get buffer to write arbitrary data to * @s: the seq_buf handle
lib/tests/seq_buf_kunit.c +94 -0
106 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH 5/7 seq_buf: Use seq_buf_strlen() for the string end in seq_buf_do_printk()
In reply to Kees Cookseq_buf_do_printk() prints whatever follows the last line feed when "start" is still inside the buffer, and for an overflowed seq_buf, this may end up pointing at the NUL, so an extra blank line would be emitted.
Take the end from seq_buf_strlen() instead, which is where the string ends whether the buffer overflowed, is exactly full, or has room left.
The only caller is the memory cgroup OOM report, so this only ever added a blank line to a report whose stats did not fit.
Add a test that registers a console to count the records that seq_buf_do_printk() emits, with a seq_buf filled so that its string ends in a line feed. It counts only the records carrying the test's marker and the records holding nothing but a line feed, so that unrelated kernel messages do not disturb it.
Tests passed under qemu on ARCH=x86_64 with GCC 16.2.0 and CONFIG_KASAN=y, and on big-endian ARCH=s390 with GCC s390x-linux-gnu 16.1.0.
---
Cc: Andrew Morton <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Shuvam Pandey <[email protected]>
Cc: David Gow <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: Sergey Senozhatsky <[email protected]>
--- lib/seq_buf.c | 5 ++-- lib/tests/seq_buf_kunit.c | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-)
lib/seq_buf.c +3 -2
@@ -116,12 +116,13 @@ EXPORT_SYMBOL_GPL(seq_buf_printf);*/ void seq_buf_do_printk (struct seq_buf *s,const char *lvl) { -const char *start, *lf; +const char *start, *lf, *end;if (s->size ==0 || s->len ==0 )return ; start =seq_buf_str (s); + end = s->buffer +seq_buf_strlen (s);while ((lf =strchr (start,'\n' ))) {int len = lf - start +1 ;
@@ -130,7 +131,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl) }/* No trailing LF */ -if (start < s->buffer + s->len) +if (start < end)printk ("%s%s\n" , lvl, start); }EXPORT_SYMBOL_GPL (seq_buf_do_printk);
lib/tests/seq_buf_kunit.c +63 -0
81 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH 6/7 powerpc/papr_scm: Return the string length from the sysfs show functions
In reply to Kees Cookperf_stats_show() and flags_show() build their output with a seq_buf and return seq_buf_used(), which may include the trailing NUL byte when the seq_buf has overflowed. Use seq_buf_strlen() instead.
Build tested ARCH=powerpc ppc64_defconfig with GCC powerpc64-linux-gnu 16.1.0:arch/powerpc/platforms/pseries/papr_scm.o
---
Cc: Madhavan Srinivasan <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: Nicholas Piggin <[email protected]>
Cc: "Christophe Leroy (CS GROUP)" <[email protected]>
Cc: "Uwe Kleine-König" <[email protected]>
Cc: Thorsten Blum <[email protected]>
Cc: Shivaprasad G Bhat <[email protected]>
Cc: <[email protected]>
--- arch/powerpc/platforms/pseries/papr_scm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/platforms/pseries/papr_scm.c +2 -2
@@ -1108,7 +1108,7 @@ static ssize_t perf_stats_show(struct device *dev, free_stats:kfree (stats); -return rc ? rc : (ssize_t )seq_buf_used (&s); +return rc ? rc : (ssize_t )seq_buf_strlen (&s); }static DEVICE_ATTR_ADMIN_RO (perf_stats);
@@ -1150,7 +1150,7 @@ static ssize_t flags_show(struct device *dev,if (seq_buf_used (&s))seq_buf_printf (&s,"\n" ); -return seq_buf_used (&s); +return seq_buf_strlen (&s); }DEVICE_ATTR_RO (flags);
Signature · 1 line
2.34.1
Re: [PATCH 6/7] powerpc/papr_scm: Return the string length from the sysfs show functions
Quoted 7 lines · Kees Cook
perf_stats_show()andflags_show()build their output with aseq_bufand returnseq_buf_used(), which may include the trailing NUL byte when theseq_bufhas overflowed. Useseq_buf_strlen()instead.Build tested ARCH=powerpc
ppc64_defconfigwith GCC powerpc64-linux-gnu 16.1.0:arch/powerpc/platforms/pseries/papr_scm.o
...
arch/powerpc/platforms/pseries/papr_scm.c static ssize_t perf_stats_show(struct device *dev, · line 1112
Quoted 5 lines
free_stats:arch/powerpc/platforms/pseries/papr_scm.c +1
-1kfree (stats); -return rc ? rc : (ssize_t )seq_buf_used (&s); +return rc ? rc : (ssize_t )seq_buf_strlen (&s); }
On a brief look it's a single ternary like this in the file, perhaps while at it move to Elvis op?
return rc ?: (ssize_t)seq_buf_strlen(&s);
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: [PATCH 6/7] powerpc/papr_scm: Return the string length from the sysfs show functions
Quoted 20 lines · Andy Shevchenko
Quoted 7 lines · Kees Cook
perf_stats_show()andflags_show()build their output with aseq_bufand returnseq_buf_used(), which may include the trailing NUL byte when theseq_bufhas overflowed. Useseq_buf_strlen()instead.Build tested ARCH=powerpc
ppc64_defconfigwith GCC powerpc64-linux-gnu 16.1.0:arch/powerpc/platforms/pseries/papr_scm.o...
arch/powerpc/platforms/pseries/papr_scm.c static ssize_t perf_stats_show(struct device *dev, · line 1112
Quoted 5 lines
free_stats:arch/powerpc/platforms/pseries/papr_scm.c +1
-1kfree (stats); -return rc ? rc : (ssize_t )seq_buf_used (&s); +return rc ? rc : (ssize_t )seq_buf_strlen (&s); }On a brief look it's a single ternary like this in the file, perhaps while at it move to Elvis op?
Quoted 1 line
return rc ?: (ssize_t)seq_buf_strlen(&s);
Sure! I've updated this for v2.
Signature · 1 line
Kees Cook
PATCH 7/7 nvdimm: ndtest: Return the string length from flags_show()
In reply to Kees Cookflags_show() build their output with a seq_buf and return seq_buf_used(), which may include the trailing NUL byte when the seq_buf has overflowed. Use seq_buf_strlen() instead.
The flag names are far shorter than the PAGE_SIZE buffer sysfs provides, so this cannot overflow today.
Build tested ARCH=x86_64 with GCC 16.2.0, built out of tree with make M=tools/testing/nvdimm:tools/testing/nvdimm/test/ndtest.o
---
Cc: Alison Schofield <[email protected]>
Cc: Vishal Verma <[email protected]>
Cc: Dave Jiang <[email protected]>
Cc: Ira Weiny <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Uwe Kleine-König <[email protected]>
Cc: Guangshuo Li <[email protected]>
Cc: <[email protected]>
--- tools/testing/nvdimm/test/ndtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/nvdimm/test/ndtest.c +1 -1
@@ -693,7 +693,7 @@ static ssize_t flags_show(struct device *dev,if (seq_buf_used (&s))seq_buf_printf (&s,"\n" ); -return seq_buf_used (&s); +return seq_buf_strlen (&s); }static DEVICE_ATTR_RO (flags);
Signature · 1 line
2.34.1
Re: [PATCH 7/7] nvdimm: ndtest: Return the string length from flags_show()
Quoted 7 lines · Kees Cook
flags_show()build their output with aseq_bufand returnseq_buf_used(), which may include the trailing NUL byte when theseq_bufhas overflowed. Useseq_buf_strlen()instead.The flag names are far shorter than the
PAGE_SIZEbuffer sysfs provides, so this cannot overflow today.
Quoted 6 lines
Build tested ARCH=x86_64 with GCC 16.2.0, built out of tree with make M=tools/testing/nvdimm:
tools/testing/nvdimm/test/ndtest.oAssisted-by LLMSigned-off-by Kees Cook <[email protected]>
Quoted 26 lines
---
Cc: Alison Schofield <[email protected]>
Cc: Vishal Verma <[email protected]>
Cc: Dave Jiang <[email protected]>
Cc: Ira Weiny <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Uwe Kleine-König <[email protected]>
Cc: Guangshuo Li <[email protected]>
Cc: <[email protected]>--- tools/testing/nvdimm/test/ndtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/testing/nvdimm/test/ndtest.c +1
-1@@ -693,7 +693,7 @@ static ssize_t flags_show(struct device *dev,if (seq_buf_used (&s))seq_buf_printf (&s,"\n" ); -return seq_buf_used (&s); +return seq_buf_strlen (&s); }static DEVICE_ATTR_RO (flags);
Quoted 5 lines · Kees Cook
While working on
seq_bufconversions, we found there was a need forseq_buf_strlen()(since calling strlen(seq_buf_str()) would be a waste of time:seq_bufalready knows the length). And while implementing that, I found a bunch of other related things that needed fixing. This is that series, with tests for each fix.
I like the series, especially the trick on how to capture printk() messages.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 10 lines · Andy Shevchenko
Quoted 5 lines · Kees Cook
While working on
seq_bufconversions, we found there was a need forseq_buf_strlen()(since calling strlen(seq_buf_str()) would be a waste of time:seq_bufalready knows the length). And while implementing that, I found a bunch of other related things that needed fixing. This is that series, with tests for each fix.I like the series, especially the trick on how to capture
printk()messages.Reviewed-by Andy Shevchenko <[email protected]>
Thanks! I'm going to spin a v2 with Bill's seq_buf_init_append()[1] (though I think I want to call it seq_buf_init_existing()? I'm open to ideas here...)
-Kees
[1] https://lore.kernel.org/lkml/[email protected]/
Signature · 1 line
Kees Cook
Steven Rostedt
maintainerQuoted 3 lines · On Thu, 17 Sep 2026 14:21:34 -0700 Kees Cook <[email protected]> wrote:
Thanks! I'm going to spin a v2 with Bill's seq_buf_init_append()[1] (though I think I want to call it
seq_buf_init_existing()? I'm open to ideas here...)
After I finish my slides for Kernel Recipes, I'll take a look at all this. Probably over the weekend.
-- Steve