powerpc/powernv/memtrace: Fix crashing the kernel when enabling concurrently
commit5.4-rM2-2.2.x-imx-squashedd6718941a2
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:9d5171a8f2
("powerpc/powernv: Enable removal of memory for in memory tracing") Cc: stable@vger.kernel.org# v4.14+ Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Oscar Salvador <osalvador@suse.de> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20201111145322.15793-3-david@redhat.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
45bf367c85
commit
a89b91fcb0
|
@ -30,6 +30,7 @@ struct memtrace_entry {
|
||||||
char name[16];
|
char name[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(memtrace_mutex);
|
||||||
static u64 memtrace_size;
|
static u64 memtrace_size;
|
||||||
|
|
||||||
static struct memtrace_entry *memtrace_array;
|
static struct memtrace_entry *memtrace_array;
|
||||||
|
@ -290,6 +291,7 @@ static int memtrace_online(void)
|
||||||
|
|
||||||
static int memtrace_enable_set(void *data, u64 val)
|
static int memtrace_enable_set(void *data, u64 val)
|
||||||
{
|
{
|
||||||
|
int rc = -EAGAIN;
|
||||||
u64 bytes;
|
u64 bytes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -302,25 +304,31 @@ static int memtrace_enable_set(void *data, u64 val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&memtrace_mutex);
|
||||||
|
|
||||||
/* Re-add/online previously removed/offlined memory */
|
/* Re-add/online previously removed/offlined memory */
|
||||||
if (memtrace_size) {
|
if (memtrace_size) {
|
||||||
if (memtrace_online())
|
if (memtrace_online())
|
||||||
return -EAGAIN;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!val)
|
if (!val) {
|
||||||
return 0;
|
rc = 0;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
/* Offline and remove memory */
|
/* Offline and remove memory */
|
||||||
if (memtrace_init_regions_runtime(val))
|
if (memtrace_init_regions_runtime(val))
|
||||||
return -EINVAL;
|
goto out_unlock;
|
||||||
|
|
||||||
if (memtrace_init_debugfs())
|
if (memtrace_init_debugfs())
|
||||||
return -EINVAL;
|
goto out_unlock;
|
||||||
|
|
||||||
memtrace_size = val;
|
memtrace_size = val;
|
||||||
|
rc = 0;
|
||||||
return 0;
|
out_unlock:
|
||||||
|
mutex_unlock(&memtrace_mutex);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int memtrace_enable_get(void *data, u64 *val)
|
static int memtrace_enable_get(void *data, u64 *val)
|
||||||
|
|
Loading…
Reference in New Issue