1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021 SUSE LLC <mdoucha@suse.cz>
4 * Copyright (c) 2022 Linux Test Project
5 *
6 * CVE-2020-25704
7 *
8 * Check for memory leak in PERF_EVENT_IOC_SET_FILTER ioctl command. Fixed in:
9 *
10 * commit 7bdb157cdebbf95a1cd94ed2e01b338714075d00
11 * Author: kiyin(尹亮) <kiyin@tencent.com>
12 * Date: Wed Nov 4 08:23:22 2020 +0300
13 *
14 * perf/core: Fix a memory leak in perf_event_parse_addr_filter()
15 */
16
17 #include "config.h"
18 #include "tst_test.h"
19 #include "tst_timer.h"
20 #include "lapi/syscalls.h"
21
22 #include "perf_event_open.h"
23
24 #define INTEL_PT_PATH "/sys/bus/event_source/devices/intel_pt/type"
25
26 const int iterations = 12000000;
27 static int fd = -1;
28 static int runtime;
29
setup(void)30 static void setup(void)
31 {
32 struct perf_event_attr ev = {
33 .size = sizeof(struct perf_event_attr),
34 .exclude_kernel = 1,
35 .exclude_hv = 1,
36 .exclude_idle = 1
37 };
38
39 /* intel_pt is currently the only event source that supports filters */
40 if (access(INTEL_PT_PATH, F_OK))
41 tst_brk(TCONF, "intel_pt is not available");
42
43 SAFE_FILE_SCANF(INTEL_PT_PATH, "%d", &ev.type);
44 fd = perf_event_open(&ev, getpid(), -1, -1, 0);
45
46 runtime = tst_remaining_runtime();
47 }
48
49 /*
50 * Check how fast we can do the iterations after 5 seconds of runtime.
51 * If the rate is too small to complete for current runtime then
52 * stop the test.
53 */
check_progress(int i)54 static void check_progress(int i)
55 {
56 static float iter_per_ms;
57 long long elapsed_ms;
58
59 if (iter_per_ms)
60 return;
61
62 if (i % 1000 != 0)
63 return;
64
65 tst_timer_stop();
66 elapsed_ms = tst_timer_elapsed_ms();
67 if (elapsed_ms > 5000) {
68 iter_per_ms = (float) i / elapsed_ms;
69 tst_res(TINFO, "rate: %f iters/ms", iter_per_ms);
70 tst_res(TINFO, "needed rate for current test runtime: %f iters/ms",
71 (float) iterations / (runtime * 1000));
72
73 if (iter_per_ms * 1000 * (runtime - 1) < iterations)
74 tst_brk(TCONF, "System too slow to complete test in specified runtime");
75 }
76 }
77
run(void)78 static void run(void)
79 {
80 long diff;
81 int i;
82
83 diff = SAFE_READ_MEMINFO("MemAvailable:");
84 tst_timer_start(CLOCK_MONOTONIC);
85
86 /* leak about 100MB of RAM */
87 for (i = 0; i < iterations; i++) {
88 ioctl(fd, PERF_EVENT_IOC_SET_FILTER, "filter,0/0@abcd");
89 check_progress(i);
90 }
91
92 diff -= SAFE_READ_MEMINFO("MemAvailable:");
93
94 if (diff > 50 * 1024)
95 tst_res(TFAIL, "Likely kernel memory leak detected");
96 else
97 tst_res(TPASS, "No memory leak found");
98 }
99
cleanup(void)100 static void cleanup(void)
101 {
102 if (fd >= 0)
103 SAFE_CLOSE(fd);
104 }
105
106 static struct tst_test test = {
107 .test_all = run,
108 .setup = setup,
109 .cleanup = cleanup,
110 .needs_root = 1,
111 .max_runtime = 300,
112 .tags = (const struct tst_tag[]) {
113 {"linux-git", "7bdb157cdebb"},
114 {"CVE", "2020-25704"},
115 {}
116 }
117 };
118