summaryrefslogtreecommitdiff
path: root/lib/tests/seq_buf_kunit.c
AgeCommit message (Collapse)Author
2026-10-11seq_buf: Add seq_buf_init_append()Bill Wendling
Several strlcat() call sites being converted to seq_buf need behavior seq_buf doesn't currently provide. The normal seq_buf_init() always empties the buffer (sets its "len" to 0) via seq_buf_clear(). Code migrating from strlcat(buf, ...), which appends to whatever buf already contains, can't use seq_buf_init() without discarding that existing content. Add seq_buf_init_append(), which preserves the existing contents and positions the seq_buf to append after it. A buffer with no NUL within its size starts out overflowed, as strlcat() treats it as already truncated. Add KUnit tests for behavior coverage. 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.2.0. Assisted-by: LLM Signed-off-by: Bill Wendling <morbo@google.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Co-developed-by: Kees Cook <kees@kernel.org> Link: https://patch.msgid.link/20261005155708.1471260-9-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Add seq_buf_terminate()Kees Cook
Seven callers call seq_buf_str() only to NUL-terminate the buffer, discarding the returned pointer. Two of them need a comment to say so. Add seq_buf_terminate(), wrapping the __seq_buf_terminate() helper that seq_buf_str() and seq_buf_strlen() already use, and convert those callers. It returns void: returning the offset would just be seq_buf_strlen() under another name. A zero-sized seq_buf is left untouched, as in the other accessors. Add tests for the three cases: room for the NUL after the data, an overflowed buffer where it lands in the last byte, and a zero-sized buffer that must not be written to. Build tested ARCH=x86_64 defconfig with GCC 16.2.0, plus CONFIG_HIST_TRIGGERS=y and CONFIG_BPF_SYSCALL=y to reach the converted call sites in kernel/trace/trace_events_hist.c and kernel/bpf/diagnostics.c. Tests run 24/24 passing on ARCH=um. Assisted-by: LLM Acked-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261005155708.1471260-7-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Add seq_buf_strlen()Kees Cook
Several strlcat() call sites being converted to seq_buf need behavior seq_buf doesn't currently provide. The return from seq_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. As discussed in review, don't add WARN_ON() for seq_buf_strlen() and drop it from seq_buf_str(). Add tests comparing seq_buf_strlen() against strlen() of seq_buf_str() for empty, appended, truncated, exactly full, and overflowed buffers, checking that seq_buf_strlen() alone terminates a full buffer, and checking that a zero-sized seq_buf reports an empty string from both accessors without touching 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.2.0. Assisted-by: LLM Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20261005155708.1471260-6-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Clear what a writer did not claim when a seq_buf overflowsKees Cook
Using 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. seq_buf_path() was not exported, so the test failed to link as a module. Export 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.2.0, and the test builds as a module (CONFIG_SEQ_BUF_KUNIT_TEST=m). Assisted-by: LLM Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20261005155708.1471260-5-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Copy what fits when seq_buf_puts() and seq_buf_putmem() overflowKees Cook
When 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. Of the callers that check the return value or test for overflow afterward, only lpfc_rx_monitor_report() relied on a string that did not fit being left out, and the previous patch has it drop such a record itself. The others treat overflow as an error or report it. The callers that ignore overflow use whatever the buffer holds, which now ends with the part of the string that fit. 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(), seq_buf_putmem() and seq_buf_putmem_hex() with stale bytes in the buffer. The three partial-overflow tests check the buffer itself rather than seq_buf_str(). Neither writer leaves the last byte of the buffer alone: seq_buf_putmem() copies raw bytes and writes no NUL, and seq_buf_puts() relies on strscpy() to write one. That byte is exactly where seq_buf_str() writes its terminator, so asserting only on the string would pass whether the copy stopped a byte early or dropped the NUL entirely. seq_buf_putmem() was not exported, so the test failed to link as a module. Export 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.2.0, and the test builds as a module (CONFIG_SEQ_BUF_KUNIT_TEST=m). Assisted-by: LLM Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20261005155708.1471260-4-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Do not pop from an overflowed seq_bufKees Cook
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 logically 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. Fixes: 32e0f607ac6a2 ("tracing: Add trace_seq_pop() and seq_buf_pop()") Assisted-by: LLM Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20261005155708.1471260-2-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-10-11seq_buf: Do not print an empty line from an overflowed seq_buf_do_printk()Kees Cook
seq_buf_do_printk() prints a buffer line by line, then prints whatever follows the last newline. When a string has overflowed at exactly a newline, an empty line is printed since the pointer hasn't reached the overflow mark of the seq_buf. Switch to just check if the string is already empty and only print if not. The only caller is the memory cgroup OOM report, so this could only ever add a blank line to a report whose statistics already did not fit. Add a test that registers a console to count the records that seq_buf_do_printk() emits. It counts the records carrying the test's marker, and the records holding nothing but a line feed that arrive after one, so that unrelated kernel messages do not disturb it. Both states that reach the flaw are covered: exactly full, and overflowed. 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.2.0. Fixes: 96928d9032a7c ("seq_buf: Add seq_buf_do_printk() helper") Assisted-by: LLM Link: https://patch.msgid.link/20261005155708.1471260-1-kees@kernel.org Signed-off-by: Kees Cook <kees@kernel.org>
2026-05-21seq_buf: Export seq_buf_putmem_hex() and add KUnit testsShuvam Pandey
The seq_buf KUnit suite does not exercise seq_buf_putmem_hex(). Add one test for the len > 8 chunking path and one overflow test where a later chunk no longer fits in the buffer. Export seq_buf_putmem_hex() as well so SEQ_BUF_KUNIT_TEST=m links cleanly. Without the export, modpost reports seq_buf_putmem_hex as undefined when seq_buf_kunit is built as a module. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: David Gow <david@davidgow.net> Link: https://patch.msgid.link/20260408202351.21829-1-shuvampandey1@gmail.com Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
2025-07-19seq_buf: Introduce KUnit testsKees Cook
Add KUnit tests for the seq_buf API to ensure its correctness and prevent future regressions, covering the following functions: - seq_buf_init() - DECLARE_SEQ_BUF() - seq_buf_clear() - seq_buf_puts() - seq_buf_putc() - seq_buf_printf() - seq_buf_get_buf() - seq_buf_commit() $ tools/testing/kunit/kunit.py run seq_buf =================== seq_buf (9 subtests) =================== [PASSED] seq_buf_init_test [PASSED] seq_buf_declare_test [PASSED] seq_buf_clear_test [PASSED] seq_buf_puts_test [PASSED] seq_buf_puts_overflow_test [PASSED] seq_buf_putc_test [PASSED] seq_buf_printf_test [PASSED] seq_buf_printf_overflow_test [PASSED] seq_buf_get_buf_commit_test ===================== [PASSED] seq_buf ===================== Link: https://lore.kernel.org/r/20250717085156.work.363-kees@kernel.org Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: Kees Cook <kees@kernel.org>