linux-stable/arch
Namhyung Kim d4a2a965d6 perf/x86: Fix out of range data
commit dec8ced871 upstream.

On x86 each struct cpu_hw_events maintains a table for counter assignment but
it missed to update one for the deleted event in x86_pmu_del().  This
can make perf_clear_dirty_counters() reset used counter if it's called
before event scheduling or enabling.  Then it would return out of range
data which doesn't make sense.

The following code can reproduce the problem.

  $ cat repro.c
  #include <pthread.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <linux/perf_event.h>
  #include <sys/ioctl.h>
  #include <sys/mman.h>
  #include <sys/syscall.h>

  struct perf_event_attr attr = {
  	.type = PERF_TYPE_HARDWARE,
  	.config = PERF_COUNT_HW_CPU_CYCLES,
  	.disabled = 1,
  };

  void *worker(void *arg)
  {
  	int cpu = (long)arg;
  	int fd1 = syscall(SYS_perf_event_open, &attr, -1, cpu, -1, 0);
  	int fd2 = syscall(SYS_perf_event_open, &attr, -1, cpu, -1, 0);
  	void *p;

  	do {
  		ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
  		p = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd1, 0);
  		ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);

  		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
  		munmap(p, 4096);
  		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
  	} while (1);

  	return NULL;
  }

  int main(void)
  {
  	int i;
  	int n = sysconf(_SC_NPROCESSORS_ONLN);
  	pthread_t *th = calloc(n, sizeof(*th));

  	for (i = 0; i < n; i++)
  		pthread_create(&th[i], NULL, worker, (void *)(long)i);
  	for (i = 0; i < n; i++)
  		pthread_join(th[i], NULL);

  	free(th);
  	return 0;
  }

And you can see the out of range data using perf stat like this.
Probably it'd be easier to see on a large machine.

  $ gcc -o repro repro.c -pthread
  $ ./repro &
  $ sudo perf stat -A -I 1000 2>&1 | awk '{ if (length($3) > 15) print }'
       1.001028462 CPU6   196,719,295,683,763      cycles                           # 194290.996 GHz                       (71.54%)
       1.001028462 CPU3   396,077,485,787,730      branch-misses                    # 15804359784.80% of all branches      (71.07%)
       1.001028462 CPU17  197,608,350,727,877      branch-misses                    # 14594186554.56% of all branches      (71.22%)
       2.020064073 CPU4   198,372,472,612,140      cycles                           # 194681.113 GHz                       (70.95%)
       2.020064073 CPU6   199,419,277,896,696      cycles                           # 195720.007 GHz                       (70.57%)
       2.020064073 CPU20  198,147,174,025,639      cycles                           # 194474.654 GHz                       (71.03%)
       2.020064073 CPU20  198,421,240,580,145      stalled-cycles-frontend          #  100.14% frontend cycles idle        (70.93%)
       3.037443155 CPU4   197,382,689,923,416      cycles                           # 194043.065 GHz                       (71.30%)
       3.037443155 CPU20  196,324,797,879,414      cycles                           # 193003.773 GHz                       (71.69%)
       3.037443155 CPU5   197,679,956,608,205      stalled-cycles-backend           # 1315606428.66% backend cycles idle   (71.19%)
       3.037443155 CPU5   198,571,860,474,851      instructions                     # 13215422.58  insn per cycle

It should move the contents in the cpuc->assign as well.

Fixes: 5471eea5d3 ("perf/x86: Reset the dirty counter to prevent the leak for an RDPMC task")
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240306061003.1894224-1-namhyung@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-04-17 11:19:36 +02:00
..
alpha rtc: Add support for configuring the UIP timeout for RTC reads 2024-01-31 16:18:56 -08:00
arc work around gcc bugs with 'asm goto' with outputs 2024-02-23 09:24:47 +01:00
arm ARM: OMAP2+: fix USB regression on Nokia N8x0 2024-04-17 11:19:26 +02:00
arm64 arm64: dts: imx8-ss-dma: fix spi lpcg indices 2024-04-17 11:19:35 +02:00
csky work around gcc bugs with 'asm goto' with outputs 2024-02-23 09:24:47 +01:00
hexagon hexagon: vmlinux.lds.S: handle attributes section 2024-04-03 15:28:55 +02:00
ia64
loongarch LoongArch/crypto: Clean up useless assignment operations 2024-04-03 15:28:36 +02:00
m68k mm: Introduce flush_cache_vmap_early() 2024-02-16 19:10:52 +01:00
microblaze
mips MIPS: Clear Cause.BD in instruction_pointer_set 2024-03-26 18:19:10 -04:00
nios2 mm: Introduce flush_cache_vmap_early() 2024-02-16 19:10:52 +01:00
openrisc
parisc prctl: generalize PR_SET_MDWE support check to be per-arch 2024-04-03 15:28:54 +02:00
powerpc mm/treewide: replace pud_large() with pud_leaf() 2024-04-10 16:35:46 +02:00
riscv riscv: process: Fix kernel gp leakage 2024-04-10 16:36:04 +02:00
s390 s390/entry: align system call table on 8 bytes 2024-04-10 16:36:04 +02:00
sh mm: Introduce flush_cache_vmap_early() 2024-02-16 19:10:52 +01:00
sparc mm/treewide: replace pud_large() with pud_leaf() 2024-04-10 16:35:46 +02:00
um um: Fix adding '-no-pie' for clang 2024-02-23 09:25:03 +01:00
x86 perf/x86: Fix out of range data 2024-04-17 11:19:36 +02:00
xtensa work around gcc bugs with 'asm goto' with outputs 2024-02-23 09:24:47 +01:00
.gitignore
Kconfig scs: add CONFIG_MMU dependency for vfree_atomic() 2024-02-23 09:24:54 +01:00