]>
Commit | Line | Data |
---|---|---|
5e3c2993 GKH |
1 | From fed474857efbed79cd390d0aee224231ca718f63 Mon Sep 17 00:00:00 2001 |
2 | From: Miklos Szeredi <mszeredi@suse.cz> | |
3 | Date: Thu, 12 Jan 2012 17:59:46 +0100 | |
4 | Subject: fsnotify: don't BUG in fsnotify_destroy_mark() | |
5 | ||
6 | From: Miklos Szeredi <mszeredi@suse.cz> | |
7 | ||
8 | commit fed474857efbed79cd390d0aee224231ca718f63 upstream. | |
9 | ||
10 | Removing the parent of a watched file results in "kernel BUG at | |
11 | fs/notify/mark.c:139". | |
12 | ||
13 | To reproduce | |
14 | ||
15 | add "-w /tmp/audit/dir/watched_file" to audit.rules | |
16 | rm -rf /tmp/audit/dir | |
17 | ||
18 | This is caused by fsnotify_destroy_mark() being called without an | |
19 | extra reference taken by the caller. | |
20 | ||
21 | Reported by Francesco Cosoleto here: | |
22 | ||
23 | https://bugzilla.novell.com/show_bug.cgi?id=689860 | |
24 | ||
25 | Fix by removing the BUG_ON and adding a comment about not accessing mark after | |
26 | the iput. | |
27 | ||
28 | Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> | |
29 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
31 | ||
32 | --- | |
33 | fs/notify/mark.c | 8 +++++--- | |
34 | 1 file changed, 5 insertions(+), 3 deletions(-) | |
35 | ||
36 | --- a/fs/notify/mark.c | |
37 | +++ b/fs/notify/mark.c | |
38 | @@ -135,9 +135,6 @@ void fsnotify_destroy_mark(struct fsnoti | |
39 | ||
40 | mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; | |
41 | ||
42 | - /* 1 from caller and 1 for being on i_list/g_list */ | |
43 | - BUG_ON(atomic_read(&mark->refcnt) < 2); | |
44 | - | |
45 | spin_lock(&group->mark_lock); | |
46 | ||
47 | if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { | |
48 | @@ -182,6 +179,11 @@ void fsnotify_destroy_mark(struct fsnoti | |
49 | iput(inode); | |
50 | ||
51 | /* | |
52 | + * We don't necessarily have a ref on mark from caller so the above iput | |
53 | + * may have already destroyed it. Don't touch from now on. | |
54 | + */ | |
55 | + | |
56 | + /* | |
57 | * it's possible that this group tried to destroy itself, but this | |
58 | * this mark was simultaneously being freed by inode. If that's the | |
59 | * case, we finish freeing the group here. |