diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2012-01-12 17:59:46 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 18:01:42 -0800 |
commit | fed474857efbed79cd390d0aee224231ca718f63 (patch) | |
tree | 8935acfe89c87fe63f72bb114fa17f97f7c26564 /fs/notify | |
parent | 1e6c4dfdeb040b2dd5c4d6d803ab95c3971ad80c (diff) | |
download | linux-stable-fed474857efbed79cd390d0aee224231ca718f63.tar.gz linux-stable-fed474857efbed79cd390d0aee224231ca718f63.tar.bz2 linux-stable-fed474857efbed79cd390d0aee224231ca718f63.zip |
fsnotify: don't BUG in fsnotify_destroy_mark()
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>
CC: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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 e14587d55689..f104d565b682 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -135,9 +135,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; - /* 1 from caller and 1 for being on i_list/g_list */ - BUG_ON(atomic_read(&mark->refcnt) < 2); - spin_lock(&group->mark_lock); if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { @@ -182,6 +179,11 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) iput(inode); /* + * We don't necessarily have a ref on mark from caller so the above iput + * may have already destroyed it. Don't touch from now on. + */ + + /* * it's possible that this group tried to destroy itself, but this * this mark was simultaneously being freed by inode. If that's the * case, we finish freeing the group here. |