From 528da3e9e237059a84a2625e942811cf824a6efd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 12 Jun 2009 16:04:26 -0400 Subject: inotify: inotify_destroy_mark_entry could get called twice inotify_destroy_mark_entry could get called twice for the same mark since it is called directly in inotify_rm_watch and when the mark is being destroyed for another reason. As an example assume that the file being watched was just deleted so inotify_destroy_mark_entry would get called from the path fsnotify_inoderemove() -> fsnotify_destroy_marks_by_inode() -> fsnotify_destroy_mark_entry() -> inotify_destroy_mark_entry(). If this happened at the same time as userspace tried to remove a watch via inotify_rm_watch we could attempt to remove the mark from the idr twice and could thus double dec the ref cnt and potentially could be in a use after free/double free situation. The fix is to have inotify_rm_watch use the generic recursive safe fsnotify_destroy_mark_by_entry() so we are sure the inotify_destroy_mark_entry() function can only be called one. This patch also renames the function to inotify_ingored_remove_idr() so it is clear what is actually going on in the function. Hopefully this fixes: [ 20.342058] idr_remove called for id=20 which is not allocated. [ 20.348000] Pid: 1860, comm: udevd Not tainted 2.6.30-tip #1077 [ 20.353933] Call Trace: [ 20.356410] [] idr_remove+0x115/0x18f [ 20.361737] [] ? _spin_lock+0x6d/0x75 [ 20.367061] [] ? inotify_destroy_mark_entry+0xa3/0xcf [ 20.373771] [] inotify_destroy_mark_entry+0xb7/0xcf [ 20.380306] [] inotify_freeing_mark+0xe/0x10 [ 20.386238] [] fsnotify_destroy_mark_by_entry+0x143/0x170 [ 20.393293] [] inotify_destroy_mark_entry+0x3c/0xcf [ 20.399829] [] sys_inotify_rm_watch+0x9b/0xc6 [ 20.405850] [] system_call_fastpath+0x16/0x1b Reported-by: Peter Zijlstra Signed-off-by: Eric Paris Tested-by: Peter Ziljlstra --- fs/notify/inotify/inotify.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/notify/inotify/inotify.h') diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index ea2605a58b8a..f234f3a4c8ca 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -15,7 +15,8 @@ struct inotify_inode_mark_entry { int wd; }; -extern void inotify_destroy_mark_entry(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); +extern void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, + struct fsnotify_group *group); extern void inotify_free_event_priv(struct fsnotify_event_private_data *event_priv); extern const struct fsnotify_ops inotify_fsnotify_ops; -- cgit v1.2.1