• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021 SUSE LLC <mdoucha@suse.cz>
4  *
5  * CVE-2020-25704
6  *
7  * Check for memory leak in PERF_EVENT_IOC_SET_FILTER ioctl command. Fixed in:
8  *
9  *  commit 7bdb157cdebbf95a1cd94ed2e01b338714075d00
10  *  Author: kiyin(尹亮) <kiyin@tencent.com>
11  *  Date:   Wed Nov 4 08:23:22 2020 +0300
12  *
13  *  perf/core: Fix a memory leak in perf_event_parse_addr_filter()
14  */
15 
16 #include "config.h"
17 #include "tst_test.h"
18 #include "lapi/syscalls.h"
19 
20 #if HAVE_PERF_EVENT_ATTR
21 #include "perf_event_open.h"
22 
23 #define INTEL_PT_PATH "/sys/bus/event_source/devices/intel_pt/type"
24 
25 static int fd = -1;
26 
setup(void)27 static void setup(void)
28 {
29 	struct perf_event_attr ev = {
30 		.size = sizeof(struct perf_event_attr),
31 		.exclude_kernel = 1,
32 		.exclude_hv = 1,
33 		.exclude_idle = 1
34 	};
35 
36 	/* intel_pt is currently the only event source that supports filters */
37 	if (access(INTEL_PT_PATH, F_OK))
38 		tst_brk(TCONF, "intel_pt is not available");
39 
40 	SAFE_FILE_SCANF(INTEL_PT_PATH, "%d", &ev.type);
41 	fd = perf_event_open(&ev, getpid(), -1, -1, 0);
42 }
43 
run(void)44 static void run(void)
45 {
46 	long diff;
47 	int i;
48 
49 	diff = SAFE_READ_MEMINFO("MemAvailable:");
50 
51 	/* leak about 100MB of RAM */
52 	for (i = 0; i < 12000000; i++)
53 		ioctl(fd, PERF_EVENT_IOC_SET_FILTER, "filter,0/0@abcd");
54 
55 	diff -= SAFE_READ_MEMINFO("MemAvailable:");
56 
57 	if (diff > 50 * 1024)
58 		tst_res(TFAIL, "Likely kernel memory leak detected");
59 	else
60 		tst_res(TPASS, "No memory leak found");
61 }
62 
cleanup(void)63 static void cleanup(void)
64 {
65 	if (fd >= 0)
66 		SAFE_CLOSE(fd);
67 }
68 
69 static struct tst_test test = {
70 	.test_all = run,
71 	.setup = setup,
72 	.cleanup = cleanup,
73 	.needs_root = 1,
74 	.tags = (const struct tst_tag[]) {
75 		{"linux-git", "7bdb157cdebb"},
76 		{"CVE", "2020-25704"},
77 		{}
78 	}
79 };
80 
81 #else /* HAVE_PERF_EVENT_ATTR */
82 TST_TEST_TCONF("This system doesn't have <linux/perf_event.h> or "
83 	"struct perf_event_attr is not defined.");
84 #endif
85