summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Dudau <adrian.dudau@enea.com>2016-05-26 10:08:31 +0200
committerMartin Borg <martin.borg@enea.com>2016-05-31 11:47:02 +0200
commit474070edd3023267ef9ba9d23f1a1ef79dc3d831 (patch)
tree7c67dcf6b28e9ddd6263eaefefaf49f384f8b35c
parent52b95c9dbd2fb8c30bd02e7cf0b17bddfc29aa4c (diff)
downloadmeta-enea-bsp-ppc-474070edd3023267ef9ba9d23f1a1ef79dc3d831.tar.gz
linux-qoriq: Fix kernel oops caused by fsnotify race condition
Backport from mainline. Only kernels <4.2 are affected by this. Signed-off-by: Adrian Dudau <adrian.dudau@enea.com> Signed-off-by: Martin Borg <martin.borg@enea.com>
-rw-r--r--recipes-kernel/linux/files/0001-fsnotify-fix-oops-in-fsnotify_clear_marks_by_group_f.patch80
-rw-r--r--recipes-kernel/linux/linux-qoriq-common.inc1
2 files changed, 81 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/0001-fsnotify-fix-oops-in-fsnotify_clear_marks_by_group_f.patch b/recipes-kernel/linux/files/0001-fsnotify-fix-oops-in-fsnotify_clear_marks_by_group_f.patch
new file mode 100644
index 0000000..250c8db
--- /dev/null
+++ b/recipes-kernel/linux/files/0001-fsnotify-fix-oops-in-fsnotify_clear_marks_by_group_f.patch
@@ -0,0 +1,80 @@
1From 8f2f3eb59dff4ec538de55f2e0592fec85966aab Mon Sep 17 00:00:00 2001
2From: Jan Kara <jack@suse.com>
3Date: Thu, 6 Aug 2015 15:46:42 -0700
4Subject: [PATCH] fsnotify: fix oops in fsnotify_clear_marks_by_group_flags()
5
6fsnotify_clear_marks_by_group_flags() can race with
7fsnotify_destroy_marks() so that when fsnotify_destroy_mark_locked()
8drops mark_mutex, a mark from the list iterated by
9fsnotify_clear_marks_by_group_flags() can be freed and thus the next
10entry pointer we have cached may become stale and we dereference free
11memory.
12
13Fix the problem by first moving marks to free to a special private list
14and then always free the first entry in the special list. This method
15is safe even when entries from the list can disappear once we drop the
16lock.
17
18Upstream-Status: Backported
19
20Signed-off-by: Jan Kara <jack@suse.com>
21Reported-by: Ashish Sangwan <a.sangwan@samsung.com>
22Reviewed-by: Ashish Sangwan <a.sangwan@samsung.com>
23Cc: Lino Sanfilippo <LinoSanfilippo@gmx.de>
24Cc: <stable@vger.kernel.org>
25Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
26Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
27Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
28---
29 fs/notify/mark.c | 30 +++++++++++++++++++++++++-----
30 1 file changed, 25 insertions(+), 5 deletions(-)
31
32diff --git a/fs/notify/mark.c b/fs/notify/mark.c
33index 92e48c7..39ddcaf 100644
34--- a/fs/notify/mark.c
35+++ b/fs/notify/mark.c
36@@ -412,16 +412,36 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
37 unsigned int flags)
38 {
39 struct fsnotify_mark *lmark, *mark;
40+ LIST_HEAD(to_free);
41
42+ /*
43+ * We have to be really careful here. Anytime we drop mark_mutex, e.g.
44+ * fsnotify_clear_marks_by_inode() can come and free marks. Even in our
45+ * to_free list so we have to use mark_mutex even when accessing that
46+ * list. And freeing mark requires us to drop mark_mutex. So we can
47+ * reliably free only the first mark in the list. That's why we first
48+ * move marks to free to to_free list in one go and then free marks in
49+ * to_free list one by one.
50+ */
51 mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
52 list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
53- if (mark->flags & flags) {
54- fsnotify_get_mark(mark);
55- fsnotify_destroy_mark_locked(mark, group);
56- fsnotify_put_mark(mark);
57- }
58+ if (mark->flags & flags)
59+ list_move(&mark->g_list, &to_free);
60 }
61 mutex_unlock(&group->mark_mutex);
62+
63+ while (1) {
64+ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
65+ if (list_empty(&to_free)) {
66+ mutex_unlock(&group->mark_mutex);
67+ break;
68+ }
69+ mark = list_first_entry(&to_free, struct fsnotify_mark, g_list);
70+ fsnotify_get_mark(mark);
71+ fsnotify_destroy_mark_locked(mark, group);
72+ mutex_unlock(&group->mark_mutex);
73+ fsnotify_put_mark(mark);
74+ }
75 }
76
77 /*
78--
791.9.1
80
diff --git a/recipes-kernel/linux/linux-qoriq-common.inc b/recipes-kernel/linux/linux-qoriq-common.inc
index 8270093..d6f0565 100644
--- a/recipes-kernel/linux/linux-qoriq-common.inc
+++ b/recipes-kernel/linux/linux-qoriq-common.inc
@@ -5,6 +5,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
5SRC_URI += "file://b4860-hard_irq_disable-bug.patch \ 5SRC_URI += "file://b4860-hard_irq_disable-bug.patch \
6 file://0001-sdhci-fix-Timeout-error-messages.patch \ 6 file://0001-sdhci-fix-Timeout-error-messages.patch \
7 file://powerpc-fsl-booke64-Set-vmemmap_psize-to-4K.patch \ 7 file://powerpc-fsl-booke64-Set-vmemmap_psize-to-4K.patch \
8 file://0001-fsnotify-fix-oops-in-fsnotify_clear_marks_by_group_f.patch \
8 " 9 "
9 10
10ENEA_KERNEL_FRAGMENTS += "\ 11ENEA_KERNEL_FRAGMENTS += "\