diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2012-01-12 11:59:46 -0500 |
---|---|---|
committer | Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> | 2012-02-13 15:14:55 -0500 |
commit | 441fb4a782ea687b85c896a1deefe3cc86edc703 (patch) | |
tree | 7227b45ef70fe16328fcabd653167b902946987b /fs/notify | |
parent | 668fa6f76d98bb4721f94ba944fd920da6e257d6 (diff) |
fsnotify: don't BUG in fsnotify_destroy_mark()
BugLink: http://bugs.launchpad.net/bugs/922799
commit fed474857efbed79cd390d0aee224231ca718f63 upstream.
Removing the parent of a watched file results in "kernel BUG at
fs/notify/mark.c:139".
To reproduce
add "-w /tmp/audit/dir/watched_file" to audit.rules
rm -rf /tmp/audit/dir
This is caused by fsnotify_destroy_mark() being called without an
extra reference taken by the caller.
Reported by Francesco Cosoleto here:
https://bugzilla.novell.com/show_bug.cgi?id=689860
Fix by removing the BUG_ON and adding a comment about not accessing mark after
the iput.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/mark.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 2199b9ba883..8b98a42c099 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -136,9 +136,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) | |||
136 | 136 | ||
137 | mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; | 137 | mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; |
138 | 138 | ||
139 | /* 1 from caller and 1 for being on i_list/g_list */ | ||
140 | BUG_ON(atomic_read(&mark->refcnt) < 2); | ||
141 | |||
142 | spin_lock(&group->mark_lock); | 139 | spin_lock(&group->mark_lock); |
143 | 140 | ||
144 | if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { | 141 | if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { |
@@ -183,6 +180,11 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) | |||
183 | iput(inode); | 180 | iput(inode); |
184 | 181 | ||
185 | /* | 182 | /* |
183 | * We don't necessarily have a ref on mark from caller so the above iput | ||
184 | * may have already destroyed it. Don't touch from now on. | ||
185 | */ | ||
186 | |||
187 | /* | ||
186 | * it's possible that this group tried to destroy itself, but this | 188 | * it's possible that this group tried to destroy itself, but this |
187 | * this mark was simultaneously being freed by inode. If that's the | 189 | * this mark was simultaneously being freed by inode. If that's the |
188 | * case, we finish freeing the group here. | 190 | * case, we finish freeing the group here. |