aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/uprobes.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2012-07-29 14:22:29 -0400
committerIngo Molnar <mingo@kernel.org>2012-07-30 05:27:20 -0400
commit665605a2a207dbe1fa429b474f932d6ea138ba92 (patch)
treea9f99fcb3972a73066af4591dd3e818b8b14ab27 /kernel/events/uprobes.c
parent9f92448ceeea5326db7d114005a7e7ac03904edf (diff)
uprobes: Uprobe_mmap/munmap needs list_for_each_entry_safe()
The bug was introduced by me in 449d0d7c ("uprobes: Simplify the usage of uprobe->pending_list"). Yes, we do not care about uprobe->pending_list after return and nobody can remove the current list entry, but put_uprobe(uprobe) can actually free it and thus we need list_for_each_safe(). Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Srikar Dronamraju <srikar.vnet.ibm.com> Cc: Anton Arapov <anton@redhat.com> Link: http://lkml.kernel.org/r/20120729182229.GA20329@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r--kernel/events/uprobes.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 5db150b306d2..bed2161620d7 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1010,7 +1010,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head)
1010int uprobe_mmap(struct vm_area_struct *vma) 1010int uprobe_mmap(struct vm_area_struct *vma)
1011{ 1011{
1012 struct list_head tmp_list; 1012 struct list_head tmp_list;
1013 struct uprobe *uprobe; 1013 struct uprobe *uprobe, *u;
1014 struct inode *inode; 1014 struct inode *inode;
1015 int ret, count; 1015 int ret, count;
1016 1016
@@ -1028,7 +1028,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
1028 ret = 0; 1028 ret = 0;
1029 count = 0; 1029 count = 0;
1030 1030
1031 list_for_each_entry(uprobe, &tmp_list, pending_list) { 1031 list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
1032 if (!ret) { 1032 if (!ret) {
1033 loff_t vaddr = vma_address(vma, uprobe->offset); 1033 loff_t vaddr = vma_address(vma, uprobe->offset);
1034 1034
@@ -1076,7 +1076,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
1076void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) 1076void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
1077{ 1077{
1078 struct list_head tmp_list; 1078 struct list_head tmp_list;
1079 struct uprobe *uprobe; 1079 struct uprobe *uprobe, *u;
1080 struct inode *inode; 1080 struct inode *inode;
1081 1081
1082 if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) 1082 if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
@@ -1093,7 +1093,7 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
1093 mutex_lock(uprobes_mmap_hash(inode)); 1093 mutex_lock(uprobes_mmap_hash(inode));
1094 build_probe_list(inode, &tmp_list); 1094 build_probe_list(inode, &tmp_list);
1095 1095
1096 list_for_each_entry(uprobe, &tmp_list, pending_list) { 1096 list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
1097 loff_t vaddr = vma_address(vma, uprobe->offset); 1097 loff_t vaddr = vma_address(vma, uprobe->offset);
1098 1098
1099 if (vaddr >= start && vaddr < end) { 1099 if (vaddr >= start && vaddr < end) {