seq_buf: Introduce DECLARE_SEQ_BUF and seq_buf_str()
Subsystems (2)
PATCH v3 1/1 seq_buf: Introduce DECLARE_SEQ_BUF and seq_buf_str()
Solve two ergonomic issues with struct seq_buf;
1) Too much boilerplate is required to initialize:
struct seq_buf s; char buf[32]; seq_buf_init(s, buf, sizeof(buf));
Instead, we can build this directly on the stack. Provide DECLARE_SEQ_BUF() macro to do this:
DECLARE_SEQ_BUF(s, 32);
2) %NUL termination is fragile and requires 2 steps to get a valid C String (and is a layering violation exposing the "internals" of seq_buf):
seq_buf_terminate(s); do_something(s->buffer);
Instead, we can just return s->buffer directly after terminating it in the refactored seq_buf_terminate(), now known as seq_buf_str():
do_something(seq_buf_str(s));
---
v3
- fix commit log typos
- improve code style for DECLARE_SEQ_BUF (shevchenko)
- const-ify seq_bug_str() return (rostedt)
v2 - https://lore.kernel.org/lkml/[email protected]
v1 - https://lore.kernel.org/lkml/[email protected]
--- include/linux/seq_buf.h | 21 +++++++++++++++++---- kernel/trace/trace.c | 11 +---------- lib/seq_buf.c | 4 +--- 3 files changed, 19 insertions(+), 17 deletions(-)
include/linux/seq_buf.h +17 -4
@@ -21,9 +21,18 @@ struct seq_buf {size_t len; }; +#define DECLARE_SEQ_BUF (NAME ,SIZE ) \ + char __ ## NAME ## _buffer[SIZE] = ""; \ + struct seq_buf NAME = { \ + .buffer = &__ ## NAME ## _buffer, \ + .size = SIZE, \ + } +static inline void seq_buf_clear (struct seq_buf *s) { s->len =0 ; +if (s->size) + s->buffer[0 ] ='\0' ; } static inline void
@@ -69,8 +78,8 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) }/** -* seq_buf_terminate - Make sure buffer is nul terminated -* @s: the seq_buf descriptor to terminate. +* seq_buf_str - get %NUL-terminated C string from seq_buf +* @s: the seq_buf handle * * This makes sure that the buffer in @s is nul terminated and * safe to read as a string.
@@ -81,16 +90,20 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)* * After this function is called, s->buffer is safe to use * in string operations. +* +* Returns @s->buf after making sure it is terminated. */ -static inline void seq_buf_terminate (struct seq_buf *s) +static inline const char *seq_buf_str (struct seq_buf *s) {if (WARN_ON (s->size ==0 )) -return ; +return "" ;if (seq_buf_buffer_left (s)) s->buffer[s->len] =0 ;else s->buffer[s->size -1 ] =0 ; + +return s->buffer; }/**
kernel/trace/trace.c +1 -10
@@ -3828,15 +3828,6 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str,return false; } -static const char *show_buffer (struct trace_seq *s) -{ -struct seq_buf *seq = &s->seq; - -seq_buf_terminate (seq); - -return seq->buffer; -} -static DEFINE_STATIC_KEY_FALSE (trace_no_verify);static int test_can_verify_check (const char *fmt, ...)
@@ -3976,7 +3967,7 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,*/ if (WARN_ONCE (!trace_safe_str (iter, str, star, len),"fmt: '%s' current_buffer: '%s'" , - fmt,show_buffer (&iter->seq))) { + fmt,seq_buf_str (&iter->seq.seq))) {int ret;/* Try to safely read the string */
lib/seq_buf.c +1 -3
@@ -109,9 +109,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl)if (s->size ==0 || s->len ==0 )return ; -seq_buf_terminate (s); - - start = s->buffer; + start =seq_buf_str (s);while ((lf =strchr (start,'\n' ))) {int len = lf - start +1 ;
Signature · 1 line
2.34.1
Le 27/10/2023 à 17:56, Kees Cook a écrit :
Quoted 63 lines
Solve two ergonomic issues with struct
seq_buf;1) Too much boilerplate is required to initialize:
struct seq_buf s; char buf[32]; seq_buf_init(s, buf, sizeof(buf));Instead, we can build this directly on the stack. Provide
DECLARE_SEQ_BUF()macro to do this:DECLARE_SEQ_BUF(s, 32);2) %NUL termination is fragile and requires 2 steps to get a valid
C String (and is a layering violation exposing the "internals" of seq_buf): seq_buf_terminate(s); do_something(s->buffer);Instead, we can just return
s->bufferdirectly after terminating it in the refactoredseq_buf_terminate(), now known asseq_buf_str():do_something(seq_buf_str(s));Cc Steven Rostedt <[email protected]>Cc "Matthew Wilcox (Oracle)" <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Justin Stitt <[email protected]>Cc Kent Overstreet <[email protected]>Cc Petr Mladek <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Rasmus Villemoes <[email protected]>Cc Sergey Senozhatsky <[email protected]>Cc Masami Hiramatsu <[email protected]>Cc Greg Kroah-Hartman <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Jonathan Corbet <[email protected]>Cc Yun Zhou <[email protected]>Cc Jacob Keller <[email protected]>Cc Zhen Lei <[email protected]>Signed-off-by Kees Cook <[email protected]>---
v3
- fix commit log typos
- improve code style forDECLARE_SEQ_BUF(shevchenko)
- const-ifyseq_bug_str()return (rostedt)
v2 - https://lore.kernel.org/lkml/[email protected]
v1 - https://lore.kernel.org/lkml/[email protected]--- include/linux/seq_buf.h | 21 +++++++++++++++++---- kernel/trace/trace.c | 11 +---------- lib/seq_buf.c | 4 +--- 3 files changed, 19 insertions(+), 17 deletions(-)include/linux/seq_buf.h +0
-0
include/linux/seq_buf.h struct seq_buf { · line 27
Quoted 7 lines
include/linux/seq_buf.h +4
-0@@ -21,9 +21,18 @@ struct seq_buf {size_t len; }; +#define DECLARE_SEQ_BUF (NAME ,SIZE ) \ + char __ ## NAME ## _buffer[SIZE] = ""; \ + struct seq_buf NAME = { \ + .buffer = &__ ## NAME ## _buffer, \
~~~
Is the & needed here?
CJ
Quoted 89 lines
include/linux/seq_buf.h +13
-4+ .size = SIZE, \ + } +static inline void seq_buf_clear (struct seq_buf *s) { s->len =0 ; +if (s->size) + s->buffer[0 ] ='\0' ; } static inline void@@ -69,8 +78,8 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) }/** -* seq_buf_terminate - Make sure buffer is nul terminated -* @s: the seq_buf descriptor to terminate. +* seq_buf_str - get %NUL-terminated C string from seq_buf +* @s: the seq_buf handle * * This makes sure that the buffer in @s is nul terminated and * safe to read as a string. @@ -81,16 +90,20 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)* * After this function is called, s->buffer is safe to use * in string operations. +* +* Returns @s->buf after making sure it is terminated. */ -static inline void seq_buf_terminate (struct seq_buf *s) +static inline const char *seq_buf_str (struct seq_buf *s) {if (WARN_ON (s->size ==0 )) -return ; +return "" ;if (seq_buf_buffer_left (s)) s->buffer[s->len] =0 ;else s->buffer[s->size -1 ] =0 ; + +return s->buffer; }/** kernel/trace/trace.c +1
-10@@ -3828,15 +3828,6 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str,return false; } -static const char *show_buffer (struct trace_seq *s) -{ -struct seq_buf *seq = &s->seq; - -seq_buf_terminate (seq); - -return seq->buffer; -} -static DEFINE_STATIC_KEY_FALSE (trace_no_verify);static int test_can_verify_check (const char *fmt, ...)@@ -3976,7 +3967,7 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,*/ if (WARN_ONCE (!trace_safe_str (iter, str, star, len),"fmt: '%s' current_buffer: '%s'" , - fmt,show_buffer (&iter->seq))) { + fmt,seq_buf_str (&iter->seq.seq))) {int ret;/* Try to safely read the string */ lib/seq_buf.c +1
-3@@ -109,9 +109,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl)if (s->size ==0 || s->len ==0 )return ; -seq_buf_terminate (s); - - start = s->buffer; + start =seq_buf_str (s);while ((lf =strchr (start,'\n' ))) {int len = lf - start +1 ;