Skip to content

Commit

Permalink
powerpc/powernv/memtrace: Fix crashing the kernel when enabling concu…
Browse files Browse the repository at this point in the history
…rrently

commit d671894 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: 9d5171a ("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>
  • Loading branch information
davidhildenbrand authored and gregkh committed Dec 30, 2020
1 parent 45bf367 commit a89b91f
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions arch/powerpc/platforms/powernv/memtrace.c
Expand Up @@ -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;
Expand Down Expand Up @@ -290,6 +291,7 @@ static int memtrace_online(void)

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

/*
Expand All @@ -302,25 +304,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)
Expand Down

0 comments on commit a89b91f

Please sign in to comment.