// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2021 SUSE LLC * Copyright (c) 2022 Linux Test Project * * CVE-2020-25704 * * Check for memory leak in PERF_EVENT_IOC_SET_FILTER ioctl command. Fixed in: * * commit 7bdb157cdebbf95a1cd94ed2e01b338714075d00 * Author: kiyin(尹亮) * Date: Wed Nov 4 08:23:22 2020 +0300 * * perf/core: Fix a memory leak in perf_event_parse_addr_filter() */ #include "config.h" #include "tst_test.h" #include "tst_timer.h" #include "lapi/syscalls.h" #include "perf_event_open.h" #define INTEL_PT_PATH "/sys/bus/event_source/devices/intel_pt/type" const int iterations = 12000000; static int fd = -1; static int runtime; static void setup(void) { struct perf_event_attr ev = { .size = sizeof(struct perf_event_attr), .exclude_kernel = 1, .exclude_hv = 1, .exclude_idle = 1 }; /* intel_pt is currently the only event source that supports filters */ if (access(INTEL_PT_PATH, F_OK)) tst_brk(TCONF, "intel_pt is not available"); SAFE_FILE_SCANF(INTEL_PT_PATH, "%d", &ev.type); fd = perf_event_open(&ev, getpid(), -1, -1, 0); runtime = tst_remaining_runtime(); } /* * Check how fast we can do the iterations after 5 seconds of runtime. * If the rate is too small to complete for current runtime then * stop the test. */ static void check_progress(int i) { static float iter_per_ms; long long elapsed_ms; if (iter_per_ms) return; if (i % 1000 != 0) return; tst_timer_stop(); elapsed_ms = tst_timer_elapsed_ms(); if (elapsed_ms > 5000) { iter_per_ms = (float) i / elapsed_ms; tst_res(TINFO, "rate: %f iters/ms", iter_per_ms); tst_res(TINFO, "needed rate for current test runtime: %f iters/ms", (float) iterations / (runtime * 1000)); if (iter_per_ms * 1000 * (runtime - 1) < iterations) tst_brk(TCONF, "System too slow to complete test in specified runtime"); } } static void run(void) { long diff; int i; diff = SAFE_READ_MEMINFO("MemAvailable:"); tst_timer_start(CLOCK_MONOTONIC); /* leak about 100MB of RAM */ for (i = 0; i < iterations; i++) { ioctl(fd, PERF_EVENT_IOC_SET_FILTER, "filter,0/0@abcd"); check_progress(i); } diff -= SAFE_READ_MEMINFO("MemAvailable:"); if (diff > 50 * 1024) tst_res(TFAIL, "Likely kernel memory leak detected"); else tst_res(TPASS, "No memory leak found"); } static void cleanup(void) { if (fd >= 0) SAFE_CLOSE(fd); } static struct tst_test test = { .test_all = run, .setup = setup, .cleanup = cleanup, .needs_root = 1, .max_runtime = 300, .tags = (const struct tst_tag[]) { {"linux-git", "7bdb157cdebb"}, {"CVE", "2020-25704"}, {} } };