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

Configure Feed

Select the types of activity you want to include in your feed.

kprobes: Fix a double lock bug of kprobe_mutex

Fix a double locking bug caused when debug.kprobe-optimization=0.
While the proc_kprobes_optimization_handler locks kprobe_mutex,
wait_for_kprobe_optimizer locks it again and that causes a double lock.
To fix the bug, this introduces different mutex for protecting
sysctl parameter and locks it in proc_kprobes_optimization_handler.
Of course, since we need to lock kprobe_mutex when touching kprobes
resources, that is done in *optimize_all_kprobes().

This bug was introduced by commit ad72b3bea744 ("kprobes: fix
wait_for_kprobe_optimizer()")

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Masami Hiramatsu and committed by
Linus Torvalds
5c51543b d202f051

+13 -6
+13 -6
kernel/kprobes.c
··· 794 794 } 795 795 796 796 #ifdef CONFIG_SYSCTL 797 - /* This should be called with kprobe_mutex locked */ 798 797 static void __kprobes optimize_all_kprobes(void) 799 798 { 800 799 struct hlist_head *head; 801 800 struct kprobe *p; 802 801 unsigned int i; 803 802 803 + mutex_lock(&kprobe_mutex); 804 804 /* If optimization is already allowed, just return */ 805 805 if (kprobes_allow_optimization) 806 - return; 806 + goto out; 807 807 808 808 kprobes_allow_optimization = true; 809 809 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { ··· 813 813 optimize_kprobe(p); 814 814 } 815 815 printk(KERN_INFO "Kprobes globally optimized\n"); 816 + out: 817 + mutex_unlock(&kprobe_mutex); 816 818 } 817 819 818 - /* This should be called with kprobe_mutex locked */ 819 820 static void __kprobes unoptimize_all_kprobes(void) 820 821 { 821 822 struct hlist_head *head; 822 823 struct kprobe *p; 823 824 unsigned int i; 824 825 826 + mutex_lock(&kprobe_mutex); 825 827 /* If optimization is already prohibited, just return */ 826 - if (!kprobes_allow_optimization) 828 + if (!kprobes_allow_optimization) { 829 + mutex_unlock(&kprobe_mutex); 827 830 return; 831 + } 828 832 829 833 kprobes_allow_optimization = false; 830 834 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { ··· 838 834 unoptimize_kprobe(p, false); 839 835 } 840 836 } 837 + mutex_unlock(&kprobe_mutex); 838 + 841 839 /* Wait for unoptimizing completion */ 842 840 wait_for_kprobe_optimizer(); 843 841 printk(KERN_INFO "Kprobes globally unoptimized\n"); 844 842 } 845 843 844 + static DEFINE_MUTEX(kprobe_sysctl_mutex); 846 845 int sysctl_kprobes_optimization; 847 846 int proc_kprobes_optimization_handler(struct ctl_table *table, int write, 848 847 void __user *buffer, size_t *length, ··· 853 846 { 854 847 int ret; 855 848 856 - mutex_lock(&kprobe_mutex); 849 + mutex_lock(&kprobe_sysctl_mutex); 857 850 sysctl_kprobes_optimization = kprobes_allow_optimization ? 1 : 0; 858 851 ret = proc_dointvec_minmax(table, write, buffer, length, ppos); 859 852 ··· 861 854 optimize_all_kprobes(); 862 855 else 863 856 unoptimize_all_kprobes(); 864 - mutex_unlock(&kprobe_mutex); 857 + mutex_unlock(&kprobe_sysctl_mutex); 865 858 866 859 return ret; 867 860 }