Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96ffece6 authored by David Hildenbrand's avatar David Hildenbrand Committed by Greg Kroah-Hartman
Browse files

powerpc/powernv/memtrace: Fix crashing the kernel when enabling concurrently



commit d6718941a2767fb383e105d257d2105fe4f15f0e upstream.

It's very easy to crash the kernel right now by simply trying to
enable memtrace concurrently, hammering on the "enable" interface

loop.sh:
  #!/bin/bash

  dmesg --console-off

  while true; do
          echo 0x40000000 > /sys/kernel/debug/powerpc/memtrace/enable
  done

[root@localhost ~]# loop.sh &
[root@localhost ~]# loop.sh &

Resulting quickly in a kernel crash. Let's properly protect using a
mutex.

Fixes: 9d5171a8 ("powerpc/powernv: Enable removal of memory for in memory tracing")
Cc: stable@vger.kernel.org# v4.14+
Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarOscar Salvador <osalvador@suse.de>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201111145322.15793-3-david@redhat.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f3f19058
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct memtrace_entry {
	char name[16];
};

static DEFINE_MUTEX(memtrace_mutex);
static u64 memtrace_size;

static struct memtrace_entry *memtrace_array;
@@ -294,6 +295,7 @@ static int memtrace_online(void)

static int memtrace_enable_set(void *data, u64 val)
{
	int rc = -EAGAIN;
	u64 bytes;

	/*
@@ -306,25 +308,31 @@ static int memtrace_enable_set(void *data, u64 val)
		return -EINVAL;
	}

	mutex_lock(&memtrace_mutex);

	/* Re-add/online previously removed/offlined memory */
	if (memtrace_size) {
		if (memtrace_online())
			return -EAGAIN;
			goto out_unlock;
	}

	if (!val)
		return 0;
	if (!val) {
		rc = 0;
		goto out_unlock;
	}

	/* Offline and remove memory */
	if (memtrace_init_regions_runtime(val))
		return -EINVAL;
		goto out_unlock;

	if (memtrace_init_debugfs())
		return -EINVAL;
		goto out_unlock;

	memtrace_size = val;

	return 0;
	rc = 0;
out_unlock:
	mutex_unlock(&memtrace_mutex);
	return rc;
}

static int memtrace_enable_get(void *data, u64 *val)