Commit d6718941 authored by David Hildenbrand's avatar David Hildenbrand Committed by Michael Ellerman
Browse files

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



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
parent c74cf7a3
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct memtrace_entry {
	char name[16];
};

static DEFINE_MUTEX(memtrace_mutex);
static u64 memtrace_size;

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

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

	/*
@@ -291,25 +293,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)