lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 30 Jul 2020 05:38:15 -0700
From:   kan.liang@...ux.intel.com
To:     peterz@...radead.org, mingo@...hat.com, acme@...nel.org,
        linux-kernel@...r.kernel.org
Cc:     ak@...ux.intel.com, Kan Liang <kan.liang@...ux.intel.com>
Subject: [PATCH] perf/x86: Reset the counter to prevent the leak for a RDPMC task

From: Kan Liang <kan.liang@...ux.intel.com>

The counter value of a perf task may leak to another RDPMC task.
For example, a perf stat task as below is running on CPU 0.

    perf stat -e 'branches,cycles' -- taskset -c 0 ./workload

In the meantime, an RDPMC task, which is also running on CPU 0, may read
the GP counters periodically. (The RDPMC task creates a fixed event,
but read four GP counters.)

    $ taskset -c 0 ./rdpmc_read_all_counters
    index 0x0 value 0x8001e5970f99
    index 0x1 value 0x8005d750edb6
    index 0x2 value 0x0
    index 0x3 value 0x0

    index 0x0 value 0x8002358e48a5
    index 0x1 value 0x8006bd1e3bc9
    index 0x2 value 0x0
    index 0x3 value 0x0

The counter value of the perf stat task leaks to the RDPMC task because
perf never clears the counter when it's stopped.

A counter/event stops for the following cases:
- Schedule the monitored task, e.g., context switch or task exit;
- Adjust the event period, e.g., Throttle, in frequency mode;
- Update the event's address range filters.

For the first case, following tasks may reuse the counter. To
prevent the leak, the counter has to be reset, when the event is
scheduled out. The del() is eventually invoked for the schedule out.
The counter should be reset in x86_pmu_del().

For the rest of the cases, the counter/event is temporarily stopped and
will be restarted soon. Other tasks don't have a chance to reuse the
counter. Reset the counter is not necessary.

The RDPMC instruction is only available for the X86 platform. Only apply
the fix for the X86 platform.

After applying the patch,

    $ taskset -c 0 ./rdpmc_read_all_counters
    index 0x0 value 0x0
    index 0x1 value 0x0
    index 0x2 value 0x0
    index 0x3 value 0x0

    index 0x0 value 0x0
    index 0x1 value 0x0
    index 0x2 value 0x0
    index 0x3 value 0x0

Signed-off-by: Kan Liang <kan.liang@...ux.intel.com>
---
 arch/x86/events/core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 01ba5fec5765..72b2c7e1bb20 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1499,6 +1499,13 @@ static void x86_pmu_del(struct perf_event *event, int flags)
 	 */
 	x86_pmu_stop(event, PERF_EF_UPDATE);
 
+	/*
+	 * The counter value may leak to an RDPMC task.
+	 * Clear the counter if the userspace RDPMC usage is enabled.
+	 */
+	if (READ_ONCE(x86_pmu.attr_rdpmc))
+		wrmsrl(event->hw.event_base, 0);
+
 	for (i = 0; i < cpuc->n_events; i++) {
 		if (event == cpuc->event_list[i])
 			break;
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ