1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3 #include <test_progs.h> 4 #include <sys/mman.h> 5 6 #include "stream.skel.h" 7 #include "stream_fail.skel.h" 8 9 void test_stream_failure(void) 10 { 11 RUN_TESTS(stream_fail); 12 } 13 14 void test_stream_success(void) 15 { 16 RUN_TESTS(stream); 17 return; 18 } 19 20 void test_stream_syscall(void) 21 { 22 LIBBPF_OPTS(bpf_test_run_opts, opts); 23 LIBBPF_OPTS(bpf_prog_stream_read_opts, ropts); 24 struct stream *skel; 25 int ret, prog_fd; 26 char buf[64]; 27 28 skel = stream__open_and_load(); 29 if (!ASSERT_OK_PTR(skel, "stream__open_and_load")) 30 return; 31 32 prog_fd = bpf_program__fd(skel->progs.stream_syscall); 33 ret = bpf_prog_test_run_opts(prog_fd, &opts); 34 ASSERT_OK(ret, "ret"); 35 ASSERT_OK(opts.retval, "retval"); 36 37 ASSERT_LT(bpf_prog_stream_read(0, BPF_STREAM_STDOUT, buf, sizeof(buf), &ropts), 0, "error"); 38 ret = -errno; 39 ASSERT_EQ(ret, -EINVAL, "bad prog_fd"); 40 41 ASSERT_LT(bpf_prog_stream_read(prog_fd, 0, buf, sizeof(buf), &ropts), 0, "error"); 42 ret = -errno; 43 ASSERT_EQ(ret, -ENOENT, "bad stream id"); 44 45 ASSERT_LT(bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, NULL, sizeof(buf), NULL), 0, "error"); 46 ret = -errno; 47 ASSERT_EQ(ret, -EFAULT, "bad stream buf"); 48 49 ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, buf, 2, NULL); 50 ASSERT_EQ(ret, 2, "bytes"); 51 ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, buf, 2, NULL); 52 ASSERT_EQ(ret, 1, "bytes"); 53 ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, buf, 1, &ropts); 54 ASSERT_EQ(ret, 0, "no bytes stdout"); 55 ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDERR, buf, 1, &ropts); 56 ASSERT_EQ(ret, 0, "no bytes stderr"); 57 58 stream__destroy(skel); 59 } 60 61 static void test_address(struct bpf_program *prog, unsigned long *fault_addr_p) 62 { 63 LIBBPF_OPTS(bpf_test_run_opts, opts); 64 LIBBPF_OPTS(bpf_prog_stream_read_opts, ropts); 65 int ret, prog_fd; 66 char fault_addr[64]; 67 char buf[1024]; 68 69 prog_fd = bpf_program__fd(prog); 70 71 ret = bpf_prog_test_run_opts(prog_fd, &opts); 72 ASSERT_OK(ret, "ret"); 73 ASSERT_OK(opts.retval, "retval"); 74 75 sprintf(fault_addr, "0x%lx", *fault_addr_p); 76 77 ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDERR, buf, sizeof(buf), &ropts); 78 ASSERT_GT(ret, 0, "stream read"); 79 ASSERT_LE(ret, 1023, "len for buf"); 80 buf[ret] = '\0'; 81 82 if (!ASSERT_HAS_SUBSTR(buf, fault_addr, "fault_addr")) { 83 fprintf(stderr, "Output from stream:\n%s\n", buf); 84 fprintf(stderr, "Fault Addr: %s\n", fault_addr); 85 } 86 } 87 88 void test_stream_arena_fault_address(void) 89 { 90 struct stream *skel; 91 92 #if !defined(__x86_64__) && !defined(__aarch64__) 93 printf("%s:SKIP: arena fault reporting not supported\n", __func__); 94 test__skip(); 95 return; 96 #endif 97 98 skel = stream__open_and_load(); 99 if (!ASSERT_OK_PTR(skel, "stream__open_and_load")) 100 return; 101 102 if (test__start_subtest("read_fault")) 103 test_address(skel->progs.stream_arena_read_fault, &skel->bss->fault_addr); 104 if (test__start_subtest("write_fault")) 105 test_address(skel->progs.stream_arena_write_fault, &skel->bss->fault_addr); 106 107 stream__destroy(skel); 108 } 109