1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <errno.h> |
3 | #include <inttypes.h> |
4 | #include <api/fs/tracing_path.h> |
5 | #include <linux/err.h> |
6 | #include <linux/string.h> |
7 | #include <sys/types.h> |
8 | #include <sys/stat.h> |
9 | #include <fcntl.h> |
10 | #include <unistd.h> |
11 | #include "thread_map.h" |
12 | #include "evsel.h" |
13 | #include "debug.h" |
14 | #include "tests.h" |
15 | #include "util/counts.h" |
16 | |
17 | static int test__openat_syscall_event(struct test_suite *test __maybe_unused, |
18 | int subtest __maybe_unused) |
19 | { |
20 | int err = TEST_FAIL, fd; |
21 | struct evsel *evsel; |
22 | unsigned int nr_openat_calls = 111, i; |
23 | struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); |
24 | char sbuf[STRERR_BUFSIZE]; |
25 | char errbuf[BUFSIZ]; |
26 | |
27 | if (threads == NULL) { |
28 | pr_debug("thread_map__new\n" ); |
29 | return TEST_FAIL; |
30 | } |
31 | |
32 | evsel = evsel__newtp("syscalls" , "sys_enter_openat" ); |
33 | if (IS_ERR(ptr: evsel)) { |
34 | tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls" , "sys_enter_openat" ); |
35 | pr_debug("%s\n" , errbuf); |
36 | err = TEST_SKIP; |
37 | goto out_thread_map_delete; |
38 | } |
39 | |
40 | if (evsel__open_per_thread(evsel, threads) < 0) { |
41 | pr_debug("failed to open counter: %s, " |
42 | "tweak /proc/sys/kernel/perf_event_paranoid?\n" , |
43 | str_error_r(errno, sbuf, sizeof(sbuf))); |
44 | err = TEST_SKIP; |
45 | goto out_evsel_delete; |
46 | } |
47 | |
48 | for (i = 0; i < nr_openat_calls; ++i) { |
49 | fd = openat(0, "/etc/passwd" , O_RDONLY); |
50 | close(fd); |
51 | } |
52 | |
53 | if (evsel__read_on_cpu(evsel, 0, 0) < 0) { |
54 | pr_debug("evsel__read_on_cpu\n" ); |
55 | goto out_close_fd; |
56 | } |
57 | |
58 | if (perf_counts(evsel->counts, 0, 0)->val != nr_openat_calls) { |
59 | pr_debug("evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n" , |
60 | nr_openat_calls, perf_counts(evsel->counts, 0, 0)->val); |
61 | goto out_close_fd; |
62 | } |
63 | |
64 | err = TEST_OK; |
65 | out_close_fd: |
66 | perf_evsel__close_fd(&evsel->core); |
67 | out_evsel_delete: |
68 | evsel__delete(evsel); |
69 | out_thread_map_delete: |
70 | perf_thread_map__put(threads); |
71 | return err; |
72 | } |
73 | |
74 | static struct test_case tests__openat_syscall_event[] = { |
75 | TEST_CASE_REASON("Detect openat syscall event" , |
76 | openat_syscall_event, |
77 | "permissions" ), |
78 | { .name = NULL, } |
79 | }; |
80 | |
81 | struct test_suite suite__openat_syscall_event = { |
82 | .desc = "Detect openat syscall event" , |
83 | .test_cases = tests__openat_syscall_event, |
84 | }; |
85 | |