#include <libarena/asan.h>
#include <libarena/buddy.h>
+/* Required for parsing the ASAN call stacks. */
+#include "test_progs_compat.h"
+
extern buddy_t buddy;
#ifdef BPF_ARENA_ASAN
}
SEC("syscall")
+__stderr("Memory violation for address {{.*}} for write of size 1")
+__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
+__stderr("Call trace:\n"
+"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n"
+"|[ \t]+[^\n]+\n)*}}")
__weak int asan_test_buddy_oob(void)
{
size_t sizes[] = {
}
SEC("syscall")
+__stderr("Memory violation for address {{.*}} for write of size 1")
+__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
+__stderr("Call trace:\n"
+"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n"
+"|[ \t]+[^\n]+\n)*}}")
__weak int asan_test_buddy_uaf(void)
{
size_t sizes[] = { 16, 32, 64, 128, 256, 512, 1024, 16384 };
}
SEC("syscall")
+__stderr("Memory violation for address {{.*}} for write of size 1")
+__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
+__stderr("Call trace:\n"
+"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n"
+"|[ \t]+[^\n]+\n)*}}")
__weak int asan_test_buddy_blob(void)
{
const int iters = 10;
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+#pragma once
+
+#ifdef __BPF__
+
+/* Selftests use these tags for compatibility with test_progs. */
+#define __test_tag(tag) __attribute__((btf_decl_tag("comment:" XSTR(__COUNTER__) ":" tag)))
+#define __stderr(msg) __test_tag("test_expect_stderr=" msg)
+#define __stderr_unpriv(msg) __test_tag("test_expect_stderr_unpriv=" msg)
+
+#define XSTR(s) STR(s)
+#define STR(s) #s
+
+#endif
free(tester->log_buf);
}
-static void free_msgs(struct expected_msgs *msgs)
+void free_msgs(struct expected_msgs *msgs)
{
int i;
fprintf(stdout, "STDERR:\n=============\n%s=============\n", stderr);
}
+static void verify_stderr(int prog_fd, struct expected_msgs *msgs)
+{
+ LIBBPF_OPTS(bpf_prog_stream_read_opts, ropts);
+ char *buf;
+ int ret;
+
+ if (!msgs->cnt)
+ return;
+
+ buf = malloc(TEST_LOADER_LOG_BUF_SZ);
+ if (!ASSERT_OK_PTR(buf, "malloc"))
+ return;
+
+ ret = bpf_prog_stream_read(prog_fd, 2, buf, TEST_LOADER_LOG_BUF_SZ - 1,
+ &ropts);
+ if (ret > 0) {
+ buf[ret] = '\0';
+ emit_stderr(buf, false);
+ validate_msgs(buf, msgs, emit_stderr);
+ } else {
+ ASSERT_GT(ret, 0, "stderr stream read");
+ }
+
+ free(buf);
+}
+
+void verify_test_stderr(struct bpf_object *obj, struct bpf_program *prog)
+{
+ struct test_spec spec = {};
+
+ if (parse_test_spec(NULL, obj, prog, &spec))
+ return;
+
+ verify_stderr(bpf_program__fd(prog), &spec.priv.stderr);
+ free_test_spec(&spec);
+}
+
static void emit_stdout(const char *bpf_stdout, bool force)
{
if (!force && env.verbosity == VERBOSE_NONE)
goto tobj_cleanup;
}
- if (subspec->stderr.cnt) {
- err = get_stream(2, bpf_program__fd(tprog),
- tester->log_buf, tester->log_buf_sz);
- if (err <= 0) {
- PRINT_FAIL("Unexpected retval from get_stream(): %d, errno = %d\n",
- err, errno);
- goto tobj_cleanup;
- }
- emit_stderr(tester->log_buf, false /*force*/);
- validate_msgs(tester->log_buf, &subspec->stderr, emit_stderr);
- }
+ verify_stderr(bpf_program__fd(tprog), &subspec->stderr);
if (subspec->stdout.cnt) {
err = get_stream(1, bpf_program__fd(tprog),