Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jiri Kosina and committed by
Linus Torvalds
4dfc896e 6faee84b

+6 -4
+3 -2
drivers/oprofile/event_buffer.c
··· 70 70 int alloc_event_buffer(void) 71 71 { 72 72 int err = -ENOMEM; 73 + unsigned long flags; 73 74 74 - spin_lock(&oprofilefs_lock); 75 + spin_lock_irqsave(&oprofilefs_lock, flags); 75 76 buffer_size = fs_buffer_size; 76 77 buffer_watershed = fs_buffer_watershed; 77 - spin_unlock(&oprofilefs_lock); 78 + spin_unlock_irqrestore(&oprofilefs_lock, flags); 78 79 79 80 if (buffer_watershed >= buffer_size) 80 81 return -EINVAL;
+3 -2
drivers/oprofile/oprofilefs.c
··· 65 65 int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count) 66 66 { 67 67 char tmpbuf[TMPBUFSIZE]; 68 + unsigned long flags; 68 69 69 70 if (!count) 70 71 return 0; ··· 78 77 if (copy_from_user(tmpbuf, buf, count)) 79 78 return -EFAULT; 80 79 81 - spin_lock(&oprofilefs_lock); 80 + spin_lock_irqsave(&oprofilefs_lock, flags); 82 81 *val = simple_strtoul(tmpbuf, NULL, 0); 83 - spin_unlock(&oprofilefs_lock); 82 + spin_unlock_irqrestore(&oprofilefs_lock, flags); 84 83 return 0; 85 84 } 86 85