Commit 4dfc896e authored by Jiri Kosina's avatar Jiri Kosina Committed by Linus Torvalds

[PATCH] oprofile: fix potential deadlock on oprofilefs_lock

nmi_cpu_setup() is called from hardirq context and acquires oprofilefs_lock.
alloc_event_buffer() and oprofilefs_ulong_from_user() acquire this lock
without disabling irqs, which could deadlock.
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 6faee84b
...@@ -70,11 +70,12 @@ void wake_up_buffer_waiter(void) ...@@ -70,11 +70,12 @@ void wake_up_buffer_waiter(void)
int alloc_event_buffer(void) int alloc_event_buffer(void)
{ {
int err = -ENOMEM; int err = -ENOMEM;
unsigned long flags;
spin_lock(&oprofilefs_lock); spin_lock_irqsave(&oprofilefs_lock, flags);
buffer_size = fs_buffer_size; buffer_size = fs_buffer_size;
buffer_watershed = fs_buffer_watershed; buffer_watershed = fs_buffer_watershed;
spin_unlock(&oprofilefs_lock); spin_unlock_irqrestore(&oprofilefs_lock, flags);
if (buffer_watershed >= buffer_size) if (buffer_watershed >= buffer_size)
return -EINVAL; return -EINVAL;
......
...@@ -65,6 +65,7 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t co ...@@ -65,6 +65,7 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t co
int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count) int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count)
{ {
char tmpbuf[TMPBUFSIZE]; char tmpbuf[TMPBUFSIZE];
unsigned long flags;
if (!count) if (!count)
return 0; return 0;
...@@ -77,9 +78,9 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz ...@@ -77,9 +78,9 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz
if (copy_from_user(tmpbuf, buf, count)) if (copy_from_user(tmpbuf, buf, count))
return -EFAULT; return -EFAULT;
spin_lock(&oprofilefs_lock); spin_lock_irqsave(&oprofilefs_lock, flags);
*val = simple_strtoul(tmpbuf, NULL, 0); *val = simple_strtoul(tmpbuf, NULL, 0);
spin_unlock(&oprofilefs_lock); spin_unlock_irqrestore(&oprofilefs_lock, flags);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment